 So, my name is Daryl Coopersmith, people call me Coop. I'm a WordPress core developer and I have a confession to make. WordPress is written in PHP. And so, I really hope you guys don't run away. We're not going to talk about PHP today, so we're going to talk about JavaScript. I write a bunch of our JavaScript, I review most of our JavaScript and I work on our features, which is pretty sweet. I work at Automatic where my job is to contribute to the project full-time, which is just unbelievably amazing. And my colleagues are awesome. There's a booth over there. Go check them out. That's as far as I'm going to go for plugging this. So, here's the low-down. I'm going to cover a whole bunch of stuff today. So, I'm going to give you a little bit of a backstory. We're going to talk about techniques that we learned about when building a live preview. And then we're going to go a little bit more low-level, which is events, observables, and binding, and then we're going to party. So, WordPress and jQuery. jQuery uses WordPress. All of the new community sites are going to use WordPress. When I flew out to D.C. and Andrew Nason was in D.C., we went and worked with the team to get a configuration that is really sweet, kind of giant WordPress multi-site install, really easy to set up and continue with... So, yay. We also use jQuery pretty much all over our admin. It's the only real library that's used everywhere. It is the library we've committed to. It's been great. It's really increased the number of contributors we've gotten. And so, yeah, let's be friends. WordPress 3.4 was just released. And in WordPress 3.4, the big focus was on appearance, right? We used to have this workflow where a user, when they wanted to pick a theme, they would log in and they say, all right, they're scrolling, they want to pick their theme. They can choose their theme and then they activate it. And then all of their settings get screwed up and they have to run through the site, slowly changing everyone while the site is live and broken. And only then would you know how to do that unless... Only if you were a power user. You would only know how to do that if you were a power user. Everyone else would just be like, oh, my site broke. How do I fix it? I don't know. I'm totally screwed. I guess I'll revert. Oh, it's still broken. So we dubbed that save and surprise, which sounds really exciting, but that doesn't make it not suck. So instead of save and surprise, we went with the live preview. And the live preview is pretty much built so that we can use it for pretty much all of our visual features from now on. And so right now we were focused on theme switching for the first version. So to take a look, we're inside WordPress right now on an install, right? And it's really easy to just customize my theme, right? Maybe we'll make it dark. Change the background color a bit. Save and publish, and we're done, right? And if I had canceled, instead, that's not the front end of my site, right? We're controlling this, and this is here only for us, which is awesome. And so what we do here is basically allow users to try and fail safely, to get immediate feedback, and to really create customizations that they wouldn't have been able to do before. And it's built in an incredibly flexible way so that plugins can continue to extend it and themes as well, because we can only do so much in the core. So actually here, the theme, our default theme extends it, and this CSS plugin is just a small thing that I've written to add. Do it, see, right? And you get live CSS editing. And that's not part of core, but it's pretty small. So how does it work, right? The most important thing for you to know is that themes can do whatever they want. WordPress themes can run PHP. That's probably the last time I will mention PHP in the talk. Which means that if they want to blow everything up, that's great, but we have no way of just saying recompile a template. Great, we have to hit the server. And that preview that you saw was hitting the server and refreshing, right? Behind the scenes. Like that's, it's saying, oh, all right, I need to make that change. And so here, we have two frames. We have the controls, we have the preview. The preview keeps refreshing, right? But here's the problem. They might not have the same origin, right? And you say, well, why don't you just force one to run through the admin, and force one to run through the front end, because the controls are in the admin, the preview's in the front end. We can't do that. We tried, it doesn't work. Basically, we can't do that in WordPress without breaking everything. So we have to deal with same origin policy. For those of you who are not familiar or want to refresh your same origin policy is the browser security fence. So say we have the jQuery events page. We could communicate with a frame that may be the old Boston page, for example, right? But if the frame has a different port, if it has a different protocol or if it has a different host name, we can't talk to it, right? And so luckily, the browser provides a couple of cross-domain tools for us to circumvent this problem. The first one is post message, which allows you to communicate between cross-origin iframes. It works in modern browsers in IE8 and above, and you can simulate it using hash transports, but they're slow, and in this case, will not work for us because they're too slow. The other one is cores, cross-origin resource sharing, and that allows you to run cross-origin scripts and make cross-origin Ajax requests. You can test if it's supported in your browser using jQuery support cores, and it is supported in modern browsers in IE10 and above. That's the one bummer. You're losing IE in this case. But again, only for cross-domain situations. So I guess I should preface this with the fact that almost all WordPress installs run on the same domain, but there's enough of them that don't that we need to handle this. So there are a bunch of different techniques we could use for refreshing, potentially, right? The first thought is, what if we wrote every value we changed to the database, right? That means we're sending only the latest change, the request is really small, and the downside is that we're writing to the database on every change, so you're probably going to set it on fire. So let's not do that. Instead, what if you try to get request an iframe injection, right? So you create an iframe, stick it into the document, and immediately set the source attribute, right? And you're passing the entire request, all of the changes, all of the customizations with every single request. Now, that actually works really well, but URLs are limited to about 2,000 characters in most modern browsers. If your requests are less than 2,000 characters, go with this route, it's the, like, super easy, but sadly, since this is built to be extended, that CSS control alone could have, like, a couple thousand characters. Probably won't, but at the same time, we need to be able to support that, especially if this is built to grow and move forward. So we have to use post, right? First thing we tried is using post, where we have an unlimited request size, and then a form element and an iframe target. So we use the target and action attributes to send the data from the controls to that frame. Awesome, unlimited request size. We can just do it, it works. Everything is beautiful except browser history just completely explodes. Every single request logs a new thing in the browser history. You can't get rid of it with pop state. You just lose browser history entirely. This totally sucks, and for us, means we can't do it. So we were left with one option, which was using post, Ajax, and iframe stuffing. So what we do is we hit the URL we want to render, right? So we say we send an Ajax request to that URL with all the customizations. It sends us back all of the HTML that's now been customized, and then we create an iframe element and say document right all of this HTML, right? And that works except we do have to work around core's restrictions, which is kind of a bummer, but pretty much the best trade-off in this situation. The other really cool thing about this is it means that we can inspect the responses and do a lot of cool things with it, and I'll talk about that a bit more later. So managing requests. We figured out how we're going to refresh the page, but how do we make it so that the user doesn't constantly see a white refreshing screen, right? Because that would just be terrible and pretty useless. In that case, I wouldn't want it to be a live preview anymore. If you just kept refreshing all the time and I kept seeing that, I'd be like, please just give me a button. That's all I want, because you want to be able to see what's happening. So the first thing here is throttling, right? We're not constantly sending off requests because we don't want to burn the server to the ground. What we do, we use a unique method of throttling, so it's not just a normal debounce. When the user changes something, they click and we immediately fire off a request. If that request hasn't resolved by the time they make another change, we stop it, and then we wait for them to stop making changes. So that's when we start debouncing. That's where we wait for 200 milliseconds before sending off the final request, right? The next method is seamless refreshing. I haven't seen this used anywhere before, and it's probably my favorite part of the entire preview. It's what prevents it from seeming like it's constantly refreshing. It's why you don't see white flashes anywhere at all. And so what it is is that when we send off that request, we actually render it in a separate iframe. So when a user makes a change, an iframe appears, and it starts loading, if that request completes, we sync it with the controls, and then once everything is synced enough to date, we pop the old one off the stack, and now we have an updated preview, and the user is none the wiser. This is totally awesome. But it's not good enough. Each request takes time, and we want this to be closer and closer to instant. And while we can't predict exactly what the theme will do because it can run arbitrary code, the theme can. Or in a couple of cases, like background color, if we know we're using the default implementation, we can. So in those cases, we use post message. And what happens there is that the theme or a plugin or anything says, don't refresh the page when we change this value. I got this. I'm going to handle this in JavaScript. And so we actually keep values in sync between the controls and the preview frame. And so you get that instant update. And you can see the difference here with our header color, which is going to update only periodically when I stop moving the mouse, as opposed to the background color, which is completely instant. And that's using post message. And the more things that use post message, the better experience the user is going to have. The last thing we did is we really... It's like the difference between the 90% and the 100% is make the experience great, right? When I said we can inspect those replies, those requests, what we can do is we have the content. When we customize the content, we sign it with a special string. We search for that string. So if that string isn't in the response, we know something went wrong. So we hide it and do the request again. We can tell when the user has a cookie that expires because we're constantly refreshing. So one has the old cookie, one has the new. And we can actually let you log in from the preview frame while leaving all of the controls intact so you don't lose your session. We can handle redirects on the page. And if someone tries to make a malicious request in the preview frame, we can wipe the whole page clean. The most important thing, though, the most important feature is backwards compatibility, right? Now, WordPress, we use backwards compatibility pretty much to make most of our decisions. It's one of the most important things. This live preview feature is compatible with every theme ever made for WordPress. That's huge. That was the hardest thing when building this. And it's not just important to us, right? Backwards compatibility is important for every major open source project, especially as they grow mature. Backwards compatibility is important for jQuery. So... I just had this idea. JQuery Core, guys. You know how the arguments of each are reversed? Can we, like, turn those around? With that, we should do that. That won't be great, right? No, we can't do it. No, we can't... Exactly. If you switch that around, you break the internet. Like, that's not hyperbole. You break the internet. And so sometimes you make mistakes, and sometimes you're stuck with your decisions. We have a few in our... We have one in our schema that's just, like, we did one thing wrong. We reversed one thing. And now we can't fix it, right? Each. At the time, it seemed made total sense. You do okay, key value. Wait, no. That's wrong. The browser implements it differently for arrays. You can't change it, right? You have to live with it and work around it. So, let's change pace, right? Where are we? Everyone has their own take on how to structure a web application, right? And we've heard a bunch about it this entire presentation, this entire conference, rather. Hear about Model View Presenter, Model View Controller, Model View View Model. But really, I think what we can agree on is that it's important to separate your data and your UI. What we can't agree on is how. I really like this abbreviation. NVWTF is probably the best description for all of these libraries. And really, I see a lot of people blindly subscribing to one or the other, and it's not that one's right or wrong, but that when we went to build this live preview, we needed some way of separating our data and UI. And as a project, it's a big deal when we adopt another open-source project. It was a huge deal when we adopted jQuery. And the fact that all of these libraries are moving and progressing so quickly, these techniques are moving and progressing so quickly, it doesn't make sense for us to commit to one yet without us experimenting with it and without us letting our developers and our community experiment with it first. So what I would really encourage is that everyone kind of understand the concepts behind each of these libraries before just starting to use it, right? Understand the concepts behind separating your data and your UI. And we use a bunch of different ones behind the scenes. And so I've distilled some of them down, so we're going to talk about them, Mixins, data binding, observable values, events, and how they can influence your application, right? Because these are the foundation of ModelViewController, ModelViewPresenter, ModelView, whatever the hell you want to call it, right? Make good decisions, make informed decisions. If I can encourage you to do one thing here, if the code's over your head, or if you don't care, or if you've heard it all before, just think about what you're doing, right? Care about what you're doing. Just don't say, like, oh, yeah, this is a popular thing. I'm just going to click. You know, community's important, but really dive into the code first and understand what you're subscribing to. And for us, we built our own thing, right? A little lightweight system to let us separate the data in the UI. And what do we have to work with? jQuery, right? And jQuery has a ton of utilities behind the hood, especially recently. Things like deferreds and callbacks that are amazing for structuring and improving your application, right? There have been a bunch of sessions on deferreds, so I'm not going to talk about them very much today, but I'm going to discuss them all over. So those requests I talked about before, but does this complex handshake, that's a deferred. That request object is its own thing. You start up the process, and there's a bunch of different states, a bunch of different things you're juggling, and at the end of it, you just get a deferred, you get a promise back, and it's like, I'm done, and then you do your thing once the request is resolved. And that allows us to separate our concerns. Mixins are completely awesome. Mixins are basically these bunches of functionality that you can just stick on objects, and the nice thing about them is that they're just plain JavaScript objects for the most part. So a mixin is a bunch of features. So in this example, we have a person, and a person can eat and sleep, right? Pretty simple. If we wanted to create an instance of it, just like a random person, we can create Cori and give him a name, right? And that, we're just using jQuery Extend. jQuery Extend, pass in the object that you want everything applied to, pass in the object where you're grabbing your stuff, or multiple objects, right? Mixins are also stackable. So a JavaScripter can code and punch ducks. But a JavaScripter doesn't have to be a person. A JavaScripter could be a robot, or a vendor who can bleep and code and punch ducks, right? Or it can be a person. It can be someone like Adam Sontag who can eat and sleep and code and punch ducks and bull strikes and also scream Larry. But most of all, Mixins are inheritance agnostic. Thank you, Adam. So it works with whatever type of inheritance you're using. If you're using prototypal inheritance, Adam Sontag, ladies and gentlemen. If you're using prototypal inheritance, it works with that. If you're using classical inheritance, it works with that. You can extend the class itself. You can extend the prototype. You can extend anything at all. It's great. And so this is a simple example that we're going to use throughout the rest of the presentation where if you just create a constructor and use the prototype as the Mixin, we can take advantage of the new keyword to create new instances, right? The main theory of the Mixin is just to assume no initialization phase, right? That's the difference between most inheritance models and Mixins is that there is no initialization. You just have to watch out and be like, oh, do I need this property? Is it initialized? Great. If not, initialize it. And you have to do that all over or just run a little initialization script at the beginning of every function to check if you've initialized and if not, do that. It's probably the main drawback, but I think it's a good price to pay. So let's create our first real Mixin, an advanced object, right? Pretty simple. Our setup is just going to be a plain function, no initialization, like we talked about, and we're going to grab the slice method so that we can easily pass around all the arguments but the first one, and you'll see why in a minute. Every single one of our functions of which there are three, follow the same pattern. One, make sure the stuff exists, and two, if everything exists, we pass all of our arguments except the ID to callbacks. Native jQuery callbacks calls, we can leverage them to just create a simple events object. So we have an on function. It takes an ID and a callback. First two lines, these two, check the stuff, right? Do we have a topics variable? If not, create an empty object. Okay, now that we have topics, do we have a callbacks object for this event? Yes? Great. If not, create a new object. And then we pass it off to callbacks. We say, all right, now that we have a callbacks object, we're going to add the callback passed in and any other arguments that came with it. But not the ID because the ID because the ID is the key in the array. Off follows a similar pattern. Do topics and the callbacks object exist? Great. If so, remove it. If not, don't do anything because we don't care. And then return this for chaining. Likewise, trigger. All right? It takes an ID. If there are topics and there are callbacks, then pass everything to callbacks. Fire the stuff. If not, we don't care. Congratulations. We've created our first mix-in. Pretty simple. But now we can make objects have their own events loops. We can make a global events loop. So use case for this. How many of you have triggered events on the body? Just custom events on the body because you don't have a global events loop or you're not using a callback array? All right. I see a bunch of hands. To me, that always feels hacky. And on top of that, it's not very efficient because you're creating a DOM event and normalizing that when, if you're already using a variable for your plugin, your code in general, there's no need for it to be attached to the body. You should have an events loop for your plugin. That's what this is for. That or per object. The next concept is an observable value. Which will have events. Right? Observable values are great for large ecosystems like WordPress. Because we have a ton of plugin developers and we have a ton of components that aren't aware of each other. Right? We need these central values which you can call a model or you can just call data or whatever. And then we need UI that will automatically update when any of those change. Or be able to change those and make sure all the other UI updates. Right? And forcing everyone to write that glue kind of sucks. So we need something in place value that we can watch and know when it changes to be able to do anything at all. So the setup here is the same thing. We're not running any initialization code but we will add a little something, a set method so that it can take a default value. Just a little sugar, but you don't need it. You can still use the prototype as a mix in itself. Next thing we're going to do is mix in events. So with this line the observable prototype now has everything from the events prototype that on, off, and trigger function. They're all there now. We can use them. We're going to add a simple get method which is going to return an internal value which is what we're going to be tracking. We're going to add an update value which is the thing that's going to update the internal value that we're tracking. We're not actually going to call the update method directly though. We're going to use set like we did before. And set has a bunch of magic in it, right? So the first thing we do is check if we're trying to set the same value that we already have. That's this line, the from equals to. And the issue there is that that's going to prevent infinite loops which suck. I mean, I don't know if I should say anything more about infinite loops. They suck. You're stuck in them forever. Then we pass all of our arguments in an infinite loop to that update method. The update method will change the value as necessary. So you actually will be able to overload it and change exactly how that works. But for vanilla stuff, you just leave it the same. It tracks the value. That's how it works. Then we fetch it again to make sure you didn't make any weird changes to it. And then we trigger the change event. And we pass in the new value and the old value. And since we already have on, off and trigger, people can subscribe to these changes by just saying this.on change and pass in a callback. That's it. That's all of these functions. This isn't observable. Right there. Not very much. You have this value. And we have the events for free because we've already created that mix in. So now we have an example. Let's create a new one. It's the weather. And we say whenever the weather changes, just log it is whatever the weather is today. Today it's sunny. So we set the weather as sunny. And immediately we see that the console logs it is sunny today. Fairly simple. But powerful. Because we're not done. Observables can also be used for data binding. And we can add a couple more methods to this class as sugar. To be able to link observables together exceptionally easily. The first thing we're going to have to do is proxy the set method to make sure that it will work on the observable that we're using at the time. It's also going to work as our setup method. It's initialization when we need it. So it's internal. You don't really need to know about it or how it works. But all we're actually doing is using the jQuery proxy method. Basically lock set to this function. But we want to keep track of it so that we can unbind it later on. Pull. It is a method that takes any number of observables. And what it says is whenever one of these observables updates update me too with that value. And so we say grab our set method and for every argument passed in just say whenever that target changes whenever that observable changes set me. Give me that value. Unpull is the exact same function just with off instead. Simple. Bind unbind. We have push which is the opposite concept. Whenever my value changes send it out to these other observables and so we keep track of our own object for every observable passed in whenever we change they should change too. And then lastly we have bidirectional syncing. These are each one direction. We have syncing, right? Where whatever observable is passed in we call both pull and push so that when one changes the other changes and when the other changes the first one changes. And both can be leveraged in different ways. And then here though really comes from integrating it with UI. And so I have a plugin that's attached to this called jcray function observable and I can't go into it now because it will eat way too much time. But all that it really does is grabs an element and applies syncing to it automatically so if it's an input it will watch the key up event and we make changes easily and synced to the UI. And an improvement here could be that we could let this observable actually recognize selectors instead of having to pass in another observable and then you get one line binding between your UI. You don't have to worry about anything else. For a more complex example say we have a model first name, last name, full name standard example update function. Remember we talked about that earlier. That will set the value to first name plus space plus last name. And then we say full name pull. Whenever first name or last name is updated update the full name right? And then the view becomes incredibly simple. We just say for first name sync last name sync right? And so we have UI that ties together incredibly easily and you can see how with just this one concept that isn't model or view specifically we can simulate almost any model view controller, model view presenter, model view view model paradigm. And so that's why to me it's model view WTF because it doesn't matter. And so that is what's going on behind the scenes here. This is attached to the model and it syncs with the back end and it will automatically work. That's my talk. Thank you. So we have about three and a half minutes for questions. Any questions? I can't see so I can't point. Could you explain the basic difference between mixing and singleton in object oriented? Pretty much sounds like the same. Well singletons you can't just drop so the question is can you explain the difference between a mixing and a singleton? And a singleton is an object that can only be instantiated once, right? You can create a new one and you can't really plop it into other things. You can't just pick a singleton and say add this functionality to something else. A mixing is more similar to horizontal inheritance like in PHP now traits or just horizontal inheritance. Basically the stackability of them, the fact that you can add a lot of them together means that it's way more than what a singleton would be. There's one in the back. You're like the only person in the room I can see by the way. How do you deal with conflicts between the methods that you're putting onto your mix ins? So the last one on the chain is the one that wins with jQuery Extend. Yeah, that's tricky. So if you do want to change that you can create a new object that kind of resolves whatever conflicts those are. But the deal is that when you're extending an object you are in full control of at least one of those mix ins. You're the one doing the mixing. So if there is a conflict you're just going to have to resolve it manually. It doesn't have language support so there's no like resolve this is that you can use A as A prime whatever it is. But you can work around that problem fairly easily. Sorry, can't quite hear you. Why are you using iFrames? Why are you using iFrames? So iFrames are like I was talking to a bunch of people about this talk and people said that they basically run from iFrames or try to kill them as soon as they see them. We really had to embrace them here. iFrames are effectively a sandbox, right? And so when we create the iFrame here we have no control over the theme. Whatever the theme does we don't have any control over it so we can't reset the CSS for that side pane and we also have to constantly refresh this page by hitting the server, right? If we were refreshing this page we'd be refreshing the controls. So we need a separate frame, a separate instance to be able to constantly refresh. And that's all. It actually lives in its own little iFrame because we have to simulate the theme to run this sidebar too so that we're not getting the effects from the old theme. We want to know what the theme we're customizing has specified and what options it supports. Does that answer your question? I hope so. Anyone else? We have like 30 seconds. Right there. Yeah, so the communication between the iFrames that's how we sync the values. So you can send custom messages between the two but each one has a collection of those values that always are in sync. That's what we use these observable values for. We actually have a connection between the two frames where they observe each other and so you always have an up-to-date version of whatever's going on in the controls over in the iFrame but without some of the details. It helps keep a separation of concerns and helps keep the preview concerned with what's going on there and the control is concerned with what's going on there. All right. Think I'm over time? Thank you guys so much.