Okay, it's one o'clock, let's make a start. Just in case you're in the wrong room, this presentation is GSS grid style sheets, the layout system that's two generations ahead. So yeah, this is your chance to go if this is not the right session. Put away your phones and laptops, try and pay some attention. We'll do this short and sharp because otherwise the room is gonna get very warm. So, who is this fool? I'm Alan Burke and I'm one of the directors of Lanartik, Drupal Development Shop in Ireland. You'll find me absent on Twitter at that handle and you'll find me on Drupal.org at that address. I've been using Drupal for far too long. Since about 2005, I've organized Drupal camps in Ireland. I was the founding chair of Drupal Ireland. I've spoken at DrupalCon, Drupal Dev Days, front end uniters, bar camps, all sorts of other stuff. These days I don't do as much web development because I'd like to concentrate in running a small business to a large degree but one of the other things I do is the trivia night, I'm the emcee for trivia night. So hope to see you all there on Thursday night. More details about that as we go. And I'm also a cyclist so I was one of the tour de Drupal team. So thanks very much to the people who organized tour de Drupal. I know there's some of the cyclists here in the room. Raise your hands if you made it. There's Lewis, good stuff he cycles. He's still sore. So what is GSS? So the best way I could describe it is as an alternative layout engine, though that is not doing it justice. It can do an awful lot more than that. This is the spiel, I guess. It reimagines CSS layout and replaces the browser's layout engine with one that harnesses the category constraint solver. And it's the same algorithm that Apple uses to compute native layout. So if you've written native mobile apps, that's the kind of stuff that the layout algorithms that is used to build those apps, that's what we're talking about here. It's the same algorithm, not in precisely the same code. Oh yeah, so one of the things, if there are questions, feel free to interrupt me. I'll do my best to answer them. Another tagline they've used from their side is they describe the CSS polyfills from the future. That's what we're trying to do here. We're basically have decided that CSS isn't quite up to scratch, so we're gonna use an alternative layout engine to layout things on the page. What I'm gonna go through this session is I'm gonna look at some of the features of what CSS is, look at the syntax, some basic examples, a slightly more advanced example. And hopefully the objective is to give you an idea of what it is and what it does. I won't pretend that you'll be experts having walked away from this session because I certainly am an expert now. So in some ways it's better to think about what CSS is not. So this gets rid of some of the preconceptions that people might have when they come to a session like this. It is not a preprocessor.  This is not a preprocessor, at least not yet. At some point in the future, it might be seen as a way that we are, it might be developed in such a fashion that it can be used as a preprocessor and therefore the browser has us work to do, though that's not the case just yet. It is not widely used, at least by me. So the backstory to this presentation is that when Drupalcon called for talks what six months ago now, this was a brand new thing that I'd seen tweeted on and seen a couple of presentations and thought, this is really cool. At six months time, this could be huge and Drupalcon really should have a presentation about it. Now that hasn't quite come to pass. But obviously the people who chose the sessions agreed with me and thought, this might prove to be very useful at some point in the future. But I will say this, the first time I started using SAS, I remember using it and going, this is really complicated. Do you really need SAS? I can do pretty much everything I need to do in CSS. And I left it, I went back to standard CSS and then a couple of years later, I found my way back to SAS again. And what I'll say is that the feelings I have about this are very similar, that it's complicated and I'm not gonna show you many examples that you can't really do with standard CSS or various layout libraries let's say. But at the same time, I think that over time the advantages of what this can do and the certainly things that it can do that CSS can't, I think they will become more prevalent. We'll start seeing some demos from people who've cracked one or two problems that are really, really hard to do in CSS. So that's how things might evolve, but no one knows for sure. It is not a grid system. So despite its name, and I'll come back to the name at some point, it is not a grid system like 960 Grids or Zen Grids or Suzy or other grid systems where they'll vary in their implementations slightly, but they'll more than likely give you a series of classes that you apply to elements. And then those classes are defined in the library or the other CSS files to handle the layout on the screen. Or if you're using Compass, then you can apply the styles directly to the elements using a preprocessor or something similar like that. But this, you don't get that with grid styles sheets. And it's not a browser implementation. So you won't go to canayuse.com and see whether this is available for use in the browser. Is it in the latest version of Opera or will IE8 support this? Because it's not implemented at the browser level. It's JavaScript. But we're friends with JavaScript now, right? Things have moved on. Bit of a non-tank cordial, so to speak. So we're happy that JavaScript is responsible for some things. An immediate question is, will it degrade? No, it will not. So the layout that you have tried to achieve or you have achieved through grid style sheets, you will not have available if JavaScript is disabled in the browser. So it's kind of up to yourself as to how you deal with that. Do you say, well, the layout's fine. You know, the content is there on the screen anyway, even if I don't get layout. But that's a call you have to make yourself. So this is how a preprocessor works. With a preprocessor, so SAS, less, stylus, and others, you will write flavored CSS. So it's an enhanced version of CSS with extra little pieces of syntax. You'll run it through a compiler, perhaps Ruby, or a JavaScript compiler, maybe, with Node. It will compile it down into vanilla or ordinary CSS that the browser with the look of God will actually understand and parse and then lay out the things on the screen. So that's your standard model. Like, can I just see a show of hands? Those are using SAS or similar. Less or similar? Nothing at all, just plain CSS. Hardcore, okay. So, okay, so now we know how that works, but maybe a little bit. But this is how grid style sheet works. Now I did a check earlier on and I'm told that this is readable at the back of the room. So, you know, if you can't read it, it's obviously your problem. So the way grid style sheets works is you will still write flavored CSS, and we're gonna see some examples of that very shortly. It runs through a compiler which generates JSON and that is sent to a layout engine, which then interacts with the DOM, but really at the same time, it's also interacting with a constrained solver to try and meet the rules and suggestions that you've made. I'll talk about the rules and suggestions, which is, I guess, my explanation of what CSS is. So it is slightly different. It's not something that this all happens at the browser side. This is not something you do on the server and then generate this stuff and send it down to the browser. At least not yet, that's in the pipeline or at least one of the plans for grid style sheets. So this works. So all that stuff happens in the browser itself using JavaScript. Okay, so the simple example. So let's do some live coding so you know what could possibly go wrong. Okay, let's see what we got. So bear with me, we'll see how we go. Okay, that's the more advanced example. Okay, here's a very simple example. Okay, so what we have here on the screen is just a very simple thing with two elements. We've got a cloud, we've got some lightning. I'm not a graphic designer just in case it wasn't immediately obvious. I didn't want to pester the graphic designers that I work with to do some work for this presentation. Anyway, we want to center the top of this lightning bolt in the center of this cloud and we want to center the whole lot in the middle of the screen. So I'll let you, as an exercise to the audience you can all imagine how you'd write that in standard CSS now, okay? How many lines are we thinking in CSS? Two, three, four? One really long one, you know? I guess they're all valid answers. I'm not going to go through alternative ways to approach this in CSS. There's a good bit of stuff to get through and I'm not sure that's going to serve much purpose, but yeah, you could probably do that in CSS. One way or the other, you'll work it out. So let's see how we'll approach that here. So this is our simple HTML file. Okay, just a double check in fairness. Now, legible from the back. Got a thumbs up and nods. Yeah, very discreet nods. You people do a lot of options. Okay, so we're pulling in our grid style sheets. One small thing to just point out here is it's served as CSS and that's kind of important. So if you look at the local demo, it's been served through a local web browser so that it's served as CSS. If you were to use this as an ordinary HTML file, it wouldn't really work or it wouldn't work at all. So just be aware of that. I just use a simple local web browser to serve that. So I'm pulling that in. I also have the grid style sheets JavaScript that I downloaded from GitHub and I also have some configuration settings that I send to there. This is all pretty much out of the box stuff. There's nothing particularly ordinary here. So in terms of the markup, you'll note that I've just had two simple image tags. Forgive my use of IDs, Morten, and others just for the purposes of this presentation. So if you could just look beyond my heinous CSS and just see what we're trying to achieve here, it'll be tough, but you can do it. I believe in you. So there is no difference there. That's a very good point because I don't need any divs to do what I need to do. So let's have a look at the grid style sheets. So right now it's empty. So the first thing we're gonna do is try and take this cloud and centers on the screen. So let's look at the first bit of CSS that we're gonna pass in there. So here's some that I wrote earlier, like any good cookery show. Okay, so let's look at the syntax of this. So the first thing to point out is, it's flavored CSS. It looks to a large degree like CSS, but there's a lot of little bits and pieces going on there. So the first thing is, actually, I'll just put that down a bit, okay. So what we're saying is for the center X value of the cloud, hash cloud, so that being the image tag of cloud, I want that to be equal to the center of the window. So this is some special syntax to get me properties of the window. It's not a variable declaration, and neither is it a test for equality, for other people, from other program languages. This is simply how we define a constraint. And we're always thinking about constraints. We are not deciding rules. We are setting boundaries that we would like the engine to resolve and to come up with a value that will satisfy all of our conditions. Okay, so this is not standard program. I'm not declaring a variable here. I'm not setting a rule that the browser must do. This I found a little bit easier to get my head around when, at some point in the past, you might have read that, sure, you can write all the CSS in the world you like, but you can't tell the browser what to do. You're merely suggesting to the browser, hey, this is how I'd like to do it, but the browser might have a user style sheet or something like that that will override your styles. And you always have to be aware of that as a web developer. So what we're saying here is I want the center of the cloud on the X axis to be equal to the center of the window on the X axis. And I want to do the same on the Y axis. I want the center Y of the cloud to be equal to the center of the window. So I've defined my grid style sheet rules. I go back to the browser. I don't have all the reload working just for the shazam effect. And I go, oh, I wasn't expecting that. Sorry? It worked. That's a very good point. It worked. It is exactly what I asked the browser to do. And that's the key point here. All of your constraints that you're set, you don't get, you have to be quite explicit in terms of defining your constraints. So we have asked for the center of the cloud to be in the center of the window. And that's exactly what we got. So, right, well, okay, yeah, fine. Thanks, thanks very much. You've done exactly what I asked you to do, but it's not really what I wanted. So the way you start thinking about this, I've got to give it more details. I've got to give it more constraints to satisfy such that I get the layout that I was trying to achieve. So let's go back and add some more constraints. So again, we'll take some extra code. I will put it in here. So now what I've done is I've added two more constraints that I'd like the engine to meet when it's deciding how to lay out the things through the DOM. So we got some special syntax here to grab the intrinsic height of the div or the image tag in this case and to grab the intrinsic width of the div and, oh sorry, the image tag and apply those as other constraints. So we want that to be matched. And you'll notice at the end here, we have something similar to the oft-used important declaration in CSS. And this is kind of similar, except we've got a number of different values. We have require, which is at the top. In other words, this is a value that we are constrained that we absolutely, excuse me, that we absolutely want to have met. So this is very, very important if you wanted to think of it like that. But there are other values that we could have said there to the engine. We could have said strong, meaning yeah, we'd really like it, but it's not the end of the world if you can't achieve it. We've also got weak and another one that escapes the mind at the moment. But again, we can just use numeric values there as well and they'll work to a large degree as well. So let's have a look and see whether that achieved anything for us. So we reload and yay, lovely stuff. It's centered in the browser. So I'm very happy with that. It's all centered, it's all super responsive. That's really good. Okay, so now we've got to deal with our lightning bolts and we want to move that to the center of the cloud. So let's see what we need to do to do that. So let's take this value here. Okay, so what we're saying is we want the top of the lightning bolt to be equal to, if possible, the center of the cloud on the y-axis. Okay, so let's do that. So we reload the page and we go, so yet again, on closer inspection, the browser or rather the engine has actually achieved the constraint that we've asked it to meet. I hope we're in for time. Okay, we're good. Okay, so the top of the lightning bolt is actually towards or at the center of the cloud. So that's actually worked, but we need it to be in the middle as well. So we're gonna need some more code for that. So we take some more here and we say, we want the center on the x-axis of the lightning to be equal to the cloud on the center of the x-axis. So hopefully this will do exactly what we, oh. Oh man, that's a shame. So yet again, something hasn't gone quite right, but yet again, if we look at what the browser has done, it has actually done exactly what we asked, but we weren't explicit enough about what we wanted. Think of this as a really poorly defined requirements, or maybe you've never had to come across that from a client going, you know. Oh, that's what I said I wanted, but that's not what I meant, you know. So it's quite similar. So like every good client, we just get more details out of the clients and we put some more information here. And again, this is similar to the rules that we had above where we said that we want the lightning's height and width to be equal to its original and intrinsic values. So let's have a look at that. So we reload the page. Shazam, there we go. One live demo, that worked. So, yes. Why are you using two syntaxes and... Why am I using two syntaxes? Let's see what's going on with that. It's just two different, oh right. Why isn't my CSS not consistent? Yeah, well, I mean the 13. Okay, so you can, just like in CSS where you have say font, font size, font, whatever you got, line height, all that kind of stuff. It's very similar. So you can specify, for a single value, you can do it like this. So I've done that here, but for a longer set of values, you can use, I suppose, a standard CSS brace to do it like that. They're equal. There's a couple of things I suppose probably worth pointing out at this point. The order in which these constraints is placed is not important. So I can put these styles in any way and it doesn't really matter about the order. What matters is how the engine resolves them. So I can put these values in any order I want and it should not and will not make a difference as to how the engine resolves it. So that's, it's something slightly different to CSS where you're used to putting the rules at the bottom will trump the rules at the top, all other things being equal. This is not the same. It will just basically try and resolve all the constraints to the best of its ability. Now, with all constraint solvers, so you're trying to work out what the best way to deal with all these requirements is, sometimes it won't be able to do them all because they're all inherently, like it's a cyclical dependency. In other words, you can't have x equal to y equal to z equal to x as long as x and y are different. It just can't be done. So what it does is it tries its best to meet as many of the constraints as close as it can. So it does its best to try and resolve that. And the problem is that, and I haven't dug into the implementation engine. I imagine there's some serious JavaScript voodoo going on there. So I shall stay away, but it's got a resolver in there. So it's got to come up with some solution that will let it display stuff on the screen. Did that answer your question? Cool. Okay, let's see where we are. So that was our simple demo. All right, let's see. Have we got some styles, simple example. So this is just, I'm going back over some of the other syntax that was there. Probably should have shown this before the demo, but nonetheless, you specify one value to be as equal as you can to the other value. So it's setting constraints that the engine will resolve. If nothing else, take that away from today, because if you think of these as being defining values, they're not. They're setting constraints that you hope will be resolved. So we've done the demo already. Okay, so the background to grid style sheets, and the reason for the name grid style sheets, it comes from a company called grid.io. So for those of you who were in Munich last year, a guy called Henry Burgess presented a talk on decoupled CMS. So he's involved with this company as well. They've got some interesting stuff coming up, including the no flow. It's basically visual programming editor, I guess you call it. So they've got a couple of interesting things and they felt that the current implementation of CSS wasn't going to be sufficient what they were trying to do.  So that's the name, not to do with grids. But why would you bother with all this? Yeah, that's a good question. And I haven't got the perfect answer. All I can say is that a lot of this stuff seems extremely powerful and as soon as I work out how good it is, I'll be using it. But in some ways, there are some things you can definitely do with this that you can't do in CSS right now. Because it's a JavaScript implementation, you're not really relying on a browser implementation and you don't have to polyfill for particular browsers. You're essentially polyfilling every browser because this JavaScript's been sent down to every browser and they all behave the same. I haven't gone back and done tests on IE8 but it definitely does work in IE9. I'm sure that it probably, it should really work in IE8 as well. I don't think they've got any kind of, I guess advanced JavaScript stuff that isn't implemented in IE8. Okay, so I want to talk briefly about layout evolution in the beginning, there was tables. So that's how, well, at least some of us old codgers here. Yeah, speak for yourself, Morton. Use tables for layout and all was good and things worked all the time and it was great. And then we moved on to floats. And one of the things about floats is, they'll work to a certain degree until you start running into percentage rounding errors and other bits and pieces and collapsed divs and all sorts of stuff. But that's how layout was done for a long time and indeed it's still done like that for some of the older browsers. So the new kid on the block is Flexbox and that can do some nice layout, I believe in our new, we just launched our new site on Drupal 8 the other day and I'm reliably informed that we're using Flexbox for layout as much as we can in polyfilling older browsers. Some of the stuff that's coming down the tracks that is not fully implemented in all browsers, you got CSS grids. This looks pretty interesting. I saw a talk at CSS com from Berlin a few weeks back from Rachel Andrew and if you have any interest in CSS grids, I totally recommend that talk and she's got some really good examples up on our website as well. And other stuff that's coming down the track are CSS regions. So these are future CSS implementations that will be available for you to use. But the one thing about pretty much all of these layout tools for want of a better word is that you will use these as stuff to hang your divs on, okay? So you're reliant on other grids that you put your content into to a large degree. You don't have to do it quite like that but that's generally how they're expecting you to do it. So the order of things is very important. The hierarchy and the nesting of things is very important. Now when I talk about hierarchy here, I'm not talking about HTML hierarchy in terms of H1, H2, et cetera. That's fine. That doesn't go away. That's still valid no matter what system you're using. But the hierarchy of how you will put one item inside another item is very important to set for flex box and floats. Okay. Hopefully that won't be picked up too much on the video mic. Okay, so I've touched across some of these topics but the key principles to grasp when you're writing or using grid style cheats. How are we doing for time? Okay, good. Okay, so I've talked about this a lot and I really can't emphasize it enough because it's easily the biggest mind shift that you have to deal with when you're dealing with grid style cheats. As you're expressing relationships between variables that may or may not be true depending on the other variables that the engine is trying to resolve. Think of it as dealing with a browser that doesn't like your CSS. You just gotta be a bit more verbose in terms of what you're asking it to do and then it should do what you want it to do. Generally speaking, as we saw in the simple example, the simple stuff, you've gotta be sometimes a little bit more verbose of what you're trying to do. Constraints are two-way. They're not a value, sorry, a variable on the left assigned to a value on the right or rather the other way around, a value on the right assigned to a variable on the left. That's not how it works. You're basically saying that one element should be equal to the other element or one value should be equal to the other value as much as possible. So I should be able to do things like, no, not do any more live demos. We got enough of that going on. Anyway, the values on the right, you can swap them around with the values on the left that shouldn't make any effect on the constraint solver because they're two-way, okay? It takes a while to think about thinking constraints. You're more used to dealing with setting variables and expecting them to be true. This is a mind shift to go from setting variables to setting constraints that should get resolved. Okay, so there's three main constituent parts to grid style sheets. The first one is CCSS for cassowary CSS. Second was VFL for visual formatting language. And the last one is if else, which is conditional CSS. So we're gonna have some brief examples of the syntax followed by a more complex demo that shows a lot more of the features in the syntax. So we'll start off with CCSS. We've seen some of this already. We have relative property constraints with strength and weight. So here we're saying that the font size inside the article div, or sorry, the article element, I guess, should be the same as the height of the box divided by 12, and this has to be strong. So in other words, this is important but not required. So if we said this was something that absolutely had to hold true over other constraints, we could use required there. But you do not and should not and do not use require everywhere because you essentially end up with a situation that you will have constraints that cannot all be resolved because you're asking the engine to do too much. And if you start trying to do some layout stuff, you'll see some problems. So we start getting very verbose. So we've got three buttons inside the panel. So three button elements, let's say, and you wanna just line them all up. So we start saying that the 10 pixels, and all values are currently pixels within grid star sheets, 10 pixels from the left of the panel, we want the button left to appear. And we want 10 pixels onto the button of the left. Hold on, yeah, that's right. So it should be to the left of button two. So we set all these constraints and it can easily get verbose with any kind of complex layout with a lot of divs on the screen. So in order to combat that to write it in a nicer way, we can use visual format language. So this is one directional alignment, not super fancy with any kind of 3D or curves or anything like that, it's very much but setting things in a straight line either in the vertical or the horizontal axis. So what grid star sheets do is they modernize and webify visual formatting language. And this is what it looks like. So what we're saying is on the horizontal plane, we've got three buttons. I want them to be in a row on the horizontal plane inside the panel. So in, hold on now, let me try not like that. So these are the elements we wanna put in a single horizontal row. We want them to live inside this panel. I want the gap between them to equal to 10. So let's see some other different ways of writing that. You can be a bit more explicit and you can be a bit more custom about the gaps that you want between your elements. So we can see the hyphen followed by the 10 which is otherwise just assumed up here to take a value of 10 at the end. Things can get really meta when this 10 can also be another constraint. The actual 10 could be the value of border width of something else. You can have all sorts of constraints even within the values here. And another way to do that is assuming that all of the elements within this panel are all using a button tag, we can do something like this. So all the buttons inside the panel line them up with 10 pixels of a gap. You can even trim that down further by using at H for horizontal and at V for vertical. Okay, so, excuse me. So we do have another tool in our army within Grid.style.cheats and these are if-else statements. So the problem with media queries is that they're only allowing you to test values and even then only some values on the media that you're within. They don't allow you to test other values within CSS nor do they allow you to test on a per element basis. You want to do responsiveness on a per element basis that's not an option available to you. So this is how we can write some stuff in Grid.style.cheats and that's how it would look like in standard media queries. So let's look at some other examples that we could do with that. We could also respond to some element properties. So if a panel width is greater than, and this is the syntax for greater than, I'll admit that it took me a while to realize that wasn't greater than or equal to. It's just greater than.  Yeah, let's see how you get on. Anyway, there'll be an exercise afterwards. I've got loads of time. So we can have other, basically it's if-else statements week, so we can respond to other elements than just the media that we're constrained within. So this is really useful if you want to do per element responsiveness. I think if anything that I was going to use it for, this is the one thing that I might start using it for straight away. Okay, so a more advanced demo. So let's see how this goes. There'll be less live coding. Okay, so what we've got here is just a couple of divs that we're gonna style up. And you'll see that they're not inside any other, any other divs are just stacked up in a row like that. And just put out on the screen like that. So if we go back and just briefly, we're gonna disable the structure. Two live demos, what could go wrong? Well, that wasn't meant to work. Yeah, we get nothing, okay? Because we don't have any styles, or rather the grid style sheets itself is kicked in and taken over responsibility for the layout, but our own styles are not there. So let's load our styles. Yeah, there we go. So this is some hidden and subliminal advertising for an event on Thursday night. So I don't know if you'll spot it or not. Let's see how it goes. See, I'll just see who's there on Thursday night, see if it works. Okay, so let's look at the grid style sheet used to layout that on the page. So, right, so things get a bit messier. Okay, so this is a more complex example of a layout achieved using grid style sheets. So again, at the top, what we're doing is we're setting some variables or rather hard constraints might be a better way to describe these things. So we're setting some hard constraints that we're gonna reuse these constraints or these values throughout the rest of the grid style sheet. So we're saying that we want a gap of 20. We want a flex gap of double the ordinary gap, when a radius of 10 and outer radius of double the standard radius. So because these are described as virus here, but really again, they're just hard constraints with the require set against them. If that require wasn't there, then you really couldn't consider them as far as at all because they would be just standard constraints that would have to be matched just like all the other constraints. So little things we're doing. The outer element is the card div. And that we're setting some things you've seen before. We're setting its width. We want that to be always within 480 pixels of the width of the window 480 pixels less than the width of the window. We want the height to begin, hold on now. There we go. Less than 480 pixels of the height. So if we look at the example, we'll see that that's how that is laid out there on the page. Let's see if you can see the mouse there. It's back moving around at all. But that's what that's coming from. So as we move things around, we'll see that it's always trying to constrain that. It doesn't always achieve it because there's other rules in place as well, but that's what it's trying to do. And again, it's centered on the X and the Y axis. And this time we're using our variable or our hard constraint to set the border radius on the element there. So for the avatar, that's this element here. Oh, hold on now. Is that even visible? Can I even see the mouse there at all moving around? Okay, get some of that to grant. So that's the avatar element. We're setting a height of it because otherwise it'd just be collapsed. We're setting the width equal to the height and we're setting the border radius equal to the height over two. And again, that lets us achieve a nice circle. So again, the name is a standard H1 tag, but if we don't put in our height and width, then it doesn't actually get painted onto the screen in the way that we would want. So again, we have to be quite verbose about how we do layout more than, yeah, more than I'd like. I think that's probably one of the more awkward things, but I can see the value of it. If you're forced to be more verbose in the CSS that you write, you're more likely not to understand where things are coming from. So things that are assumed or automatic, they're the things you'll forget about and wonder, well, why is something acting in certain fashion? Okay, so let's, as we move down, setting the border radius, we're setting some values on the button. I'm trying to see if there's any sort of new stuff in here that we didn't really cover already. I don't think there is until we get to something like this. Right. Okay, so now we're into some layout. So what we're saying is on the horizontal axis, we're using a new feature here called cushions, which are like gaps, but not. Gaps are defined on equality, cushions defined on inequality, meaning I want to get stuff to be less than or more than something, not the same as. So yeah, that's not a great description, but my head hasn't quite parsed yet myself, to be honest with you. It'll have to do for now. So what we're saying is that the name element sits inside the cover element with the gap of standard gap times two, and that's a strong requirement. That's something we really want. So that's an example of the short form of the syntax on the horizontal. Now we're into the fun stuff. So this is where we start to use some of the power element responsiveness. So this is something that, off the top of my head, I'm not entirely sure how, if you could even do this in CSS. But basically what we're saying is, if the width of the card, the card being the outer element is, or it should be, or, see, it's not a hard requirement. So you have to be careful how you even say these things out loud. Anyway, if the card width is greater than the card height, then we're gonna use this layout. Otherwise, we're gonna use this layout. Okay, so we're not testing the width of the browser. So the browser width doesn't really matter here. All that matters is the width and the height of the card element. And that's what happens in terms of responsiveness. So again, we've got some layout on the vertical. So we're saying for the landscape card, which is this, we're gonna have the avatar, followed by the name, inside the cover element. So that's just the rule we want to achieve. The constraint solver solves it by laying them out in that order. There's other values being added on here that we haven't covered before. So we're setting a gap. So the gap between the elements. And we're setting an outer gap, which is something we didn't cover before. So the outer gap is the gap between the elements and the element that they're sitting inside. These are all things you can find. So this is all one, I guess, I won't call it, it's all one constraint. So even though it's spread out over two lines. So the next thing we're setting is a new value called chain. So what you can do is you can take, for the elements in your vertical layout in this case, you can take certain values and chain them together meaning they should be equal. In this case, we're saying that the center X value, there we go, this and this, that they should be equal. Okay, and again, we're taking that value from another value. So it's getting a bit weird at this stage, but it all works, thankfully, because I prepared it earlier. Okay, so we got a couple of other rules here. I'm trying to pick out the stuff that's kind of new that we haven't covered before. Most of this stuff in terms of setting horizontal and vertical layouts, we've kind of covered before. Okay, talked about the chain value. Okay, so now we have the portrait. So you can see the layout is quite different in terms of, let's look at the visual implementation. So if we go to portraits, do need to reload for it to kick in. So that's our portrait layout. Looks quite different from our vertical layout. Now, I didn't go over the top in terms of coming up on something crazy, but there's other little things you can, I don't know if we've got enough screen width to show this. Not really, no, because I wasn't smart enough to set up an auto reload thing on my browser. You can do that. You can't get it to reload all the time, but it's stuff that you don't necessarily need to have going on all the time. Sorry, the question was how come it did not reload? I like giving the answer. No, you can get them to be evaluated all the time, but it needs to do a bit more work because otherwise it's going to put a lot of load on the browser, just constantly checking how's the screen change with? How's the screen change with? So you try and avoid that to a degree, like deep pencil, I guess. I'll have to look at that another time. Yeah, have we even got a path through to the microphone? Probably not. Yeah, so the question was, why did I have to keep reloading the page? So that's why. Okay, so let's go back to some of the syntax. Okay, I think new there, not particularly. No, this time we're just being a bit more verbose about how we set the gaps between the elements. Right then. That might well be it, short and sweet. That's pretty much it. The one element that I didn't get to, it's kind of a, I was up in the area so whether I go ahead with it or not is because I felt there was enough news of here was to try and implement this in Drupal 8. To be honest with you, it's fairly straightforward. There's only one element that's a little bit tricky and that's how to get Drupal and the web server to cooperate and make sure that the grid style cheat file is served as GSS. So you can't just say it's another JavaScript file, it'd be served as text.js and it won't be parsed. So I didn't quite get around to working on how to do that. So if anyone's still awake and interested, happy to take questions, I'll do my best to answer them. Not a grid style cheat expert, there's probably a number of you in the room. But there you go. Actually, there you go. There's a question you should have asked to start. Who has heard of or used grid style cheats? Let's go with heard of and used in anger at all. Even for fun. Okay, okay, are there any questions? We'll happily take some questions there. If you can make your way. No, okay, just shout it out and I'll repeat it back. The first question was what's the performance impact of this? The examples that I have are, they're not super complex, but they've got enough layout there that you might have in a standard webpage. And there's a tiny amount of time it takes for the JavaScript to be parsed and loaded on the page. Not too dissimilar from my experience with say loading an external font, perhaps. So the same issue you have with flash of one style content, you have here, there is some tricky CSS that you can use. And there is a class that's added to the body tag. If I remember this correctly, let's see what we have if we have it here. Yeah, so we had this class GSS ready. So some of the examples have this thing where it basically hides everything until that class GSS ready is true or it's added to the body tag. And once that happens, then it displays the page. So it stops you having a situation where actually you saw it in the sample demo where it showed them slightly out of line and then quickly into line. So yeah, there is a performance impact. You know, the reality is Anthony that uses JavaScript for layout is gonna have that. But I don't think it's huge. And again, it's a case of trade-off. I think some of the stuff that you can do with this, if I can fully get my head around it are stuff that I couldn't do in CSS. So you have to decide, well, is it really worth it or is the flash of one style content a bit too much? Now take the follow-up question then. No, the fallback to CSS will be up to yourself. I mean, you can see the class GSS ready is there. So you could do a fallback in CSS by testing if that class has been set. So dot, I don't know, CSS ready. If the body tag doesn't have that class then you can do some other stuff with it. But no, not really out of the box. It'd be up to yourself to do that. Okay, next question. Lewis. Oh, sorry, sorry. So Lewis just said that you could use a Node.js class or something like that to test if JavaScript wasn't available and therefore you wouldn't get your layout and you could do it like that. Lewis' question. The question was. Yeah, so this isn't really pretty. So there you go. It basically applies all this stuff. What did you expect? Nice, clean CSS. Can you take the simple? Yeah, it's not much better. There you go. So I talked about the stuff that it's generating. It's generating JSON, sending it down to the browser and applying it to the browser. Yeah, there's a lot of voodoo going on there that I have no idea of what it's doing. But hey, I don't know how Gekko and WebKit work either. So I'm blank and things like that. Yeah, I'll leave that to the nerds to read there. Have fun there, Morten. Andrew at the back. The simpler, the more advanced one. Oh yeah, so I have it here in a CSS file. That's fine. There it is, some basic CSS. That's a good question. That I do not know. I wouldn't. I would try and keep the separation of concerns to some degree if I could. There's obviously a lot of, the question was kind of do color in GSS. The short answer is I don't know. The longer answer is I wouldn't. I try and keep my CSS doing layout style and presentation and try and keep grid style sheets for layout on the page. Any more? Okay, yeah. Mix switch. Oh, well, yeah. That's where I get, the question was is it possible to mix this with like other CSS layout things, is it? No, GSS tends to trump whatever's there. So anything that's even there in the browser already gets trumped. So it's basically the values that GSS looks at, like say height, width. There's a series of values that it basically determines and calculates. Yeah, they're going to get trumped by it. As far as I can tell in any case. Oh, no, for all elements, yeah, yeah, yeah. Fun, yeah. Next question. Yeah, yeah, that's fine. So basically the question was if you set a margin in CSS, what will happen with it? It goes away. It's basically the browser, GSS takes over layout everything. All elements on the page. So if you set a margin in CSS, it just goes to its browser default. Adding to. Sorry, I'm being a slightly facetious there. The shorter answer that I don't know for sure from what I can tell from the testing, it doesn't look as though those values get respected whatsoever. So in other words, anything that's going to affect the box model essentially. That's the stuff that gets overwritten and used by grid style sheets. I'd need to do a bit more, I suppose, test out and see which one or the other. The problem with not having a chance to do this in any kind of production site is that I haven't really got great answers to things like that. Like in particular, knowing exactly which stuff to put in a standard CSS file and which stuff to put into a grid style sheets. Because if Andy's going to get trumped by grid style sheets, well, you want it to live in a grid style sheet and keep it there and there only. But with a bit more practice, I guess we get there and work it out. Interestingly, the site itself does use GSS for layout itself. So the gridstylecheats.org, they do use gridstylecheats for its own layout. I'm not sure if that answers your question, but there you go. Can't win them all. Will the CSS be stripped out if we go back to its default state? The gridstylecheats, as far as I'm aware, it doesn't set it back to default state. It just basically sets it, it just clears it out completely. So even the browser, you know, I don't know, is there a browser standard height for H1 or something like that? Well, if there is, gridstylecheats doesn't seem to respect it from what I can see, from what I can see. Yeah, questions back there. Can you use transitions? So you mean, can you use transitions in your CSS and then not have them trumped by gridstylecheats? I don't think so, no, because like you can see that it's using transform there in the generated stuff. So that's probably the kind of stuff that I'd steer clear of. But yeah, yet another, I don't know for sure answer. I might stop these things now. Addie Moore, Morton, and then Jonathan. When is this ready for production? When is this ready for production? People are using it in production in fairness. So like the guys at NoFlow are using it in gridstylecheats on their own gridstylecheats site. They've got others. Yeah, I wouldn't think about it in terms of time. What's gonna happen is someone will manage to achieve some layout stuff that's just not really doable. Even with the new stuff that's coming on down the track would say gridstylecheats or CSS, sorry, CSS grids or CSS regions. And like everything else, when someone shows something that, hey, that's something that's really, really awkward to do. Therefore, this is technology that it's worth looking at. And that applies to everything. In the same way that whenever we first picked up Drupal and Huck, I was saying to me, write in handwritten CMSs now because someone's just done a better job and solved a problem for me. And I think that's, I haven't in fairness on it, but hold my hands up. I haven't come up with an example here that's gonna send you all scurrying back to your code editors to start using this. But give me a couple of months. I'm sure I'll come up with something. And I think more than likely we'll see implementations in the wild. I fully expect to see stuff in the wild where people go, here I did this and it could have taken me 600 lines of CSS and I managed it in, I don't know, 30, 40 of grid style sheets. So you present this at Frontend United in Bristol? Oh, that's, of course. I mean, I would love to attend this at Frontend United in Bristol on the 18th and 19th of April, 2015. Yes, Martin, I would love to. So yeah, Frontend United is a Drupal Frontend conference, although it has pretty much morphed into a general Frontend conference at this stage. And it will be on Bristol in the UK on the 18th and 19th of April. It will be a lot of fun. I will probably be there. And I might even be presenting a better version of this talk. Thanks, thanks, Martin. Jonathan. Oh, it is, yeah. Like, I haven't done any native Apple coding type stuff, but I'm told it's this kind of stuff as well. Interestingly, I was talking to Chris Van de Water this morning about this. He said he was doing very similar stuff in 2008 or so using OpenLaslo. And while they weren't using the exact same, say, syntax being flavored CSS, it was all XML, I think, if I remember correctly. But again, it outputted, and you had two choices of output. You could output it as Flash or output it as JavaScript. Now, most people tend to go for the Flash. It was a bit more powerful and probably a bit more performant. But yeah, it's not especially new. This is just a different way of doing it, I guess. And it's a bit, you know, it's closer. If you think about it, in terms of syntax is a lot more accessible to web developers than sort of defining layout and XML, I would wager. Any more, yeah, at the side there, or are you just? How big is the library? How big is the library? It's not very big. Let's have a look. See if I can work it out. Nothing like live stuff, eh? Resource is there. Okay, you've got me on the spot, I'm not gonna find this. Okay, well, this is the grid spreadsheet itself. Yeah, it's substantial enough when you look at it. Oh, here, 2,000 lines. Yeah, but how many people have read the source code for Blink? No hands here. And we have it, we're raising our hands. What about Gecko? Anyone know that one? Okay, the difference is you don't have to send it down to like Gecko and Blink, they're already in the browser. That's probably not a fair comparison. The only information on how it performs is it's generally okay. I think I covered this earlier on. It seems to me, for me, about the same as like loading external font, you have to deal with the flat-of-one style content one way or the other. So, you know, in terms of the processing time to load something like that, like an external resource, and then only then do you want to paint to the screen? It seems to be very similar. Again, that's a good feeling. That's not a scientific answer to your question, but that's how I looked at it. If you're willing to put up with having to deal with loading that external resource of an external font and hands up those who are not using external fonts or custom fonts in their designs these days, well, then this seems like a fair enough thing to do as well. It'd be quicker if you didn't, sure, but you may be willing to put up with the cost of it. Jonathan? Well, why would it not work? The question was, it seems jQuery won't work anymore. Oh, yeah, okay, sorry, I see what you mean. So, yeah, doc, I would steer down away from that path. In other words, if you're trying to use jQuery to manipulate your layout, much like I said, if you want to use 3D transforms or other things like that, choose your poison and stick with it. Don't make strings, it's the same thing. Can you communicate with CSS via JavaScript, or GSS via JavaScript? Maybe. I, probably, probably, I mean, ultimately, it's a JavaScript implementation. So, yeah, I think you could. I mean, there's a fair bit, you can see in the configuration, it is JavaScript. So, yeah, probably. I'm not sure what crazy things are coming up with there now, but I'll head to my bets. Okay, guys, there's five, so we'll leave it there. Thanks very much. See y'all pretty nice. Please give feedback, good, bad, or indifferent. Any feedback is welcome, better than silence.


Good morning evening and everything in between one of the things we've been doing so far is we've been talking about Doing data analysis inside of Python and you know, we've been looking at different libraries to do that So we've talked about numpy, scipy, matplotlib, and that's what we're going to be doing today with pandas So pandas is just another library out there that exists that is used for data analysis Now, why are there so many libraries? Well, if you think about it numpy Inside pi what they're doing is they're sort of just doing the mathematical calculations and matplotlib is just doing the plotting Now the reason why we also have pandas sort of also in our back pocket is There is a another programming language out there. It's known as R. It's not bad. It's not terrible It's it's just another language and one of the things that R does really well is data analysis specifically it uses some object that it refers to as a data frame That's a pretty great object that we'll see today. And so what We're doing is effectively saying well, I would like to do I would like to use sort of a data frame But inside of Python and that's obviously where we start with pandas To at least start even before we get to the data frame. We want to think about our data So to start we have something known in pandas known as the series data type Let's take a look at least How that would be implemented? So I've already imported my pandas and I'll just go ahead and call this x PD dot series Now the entire idea here is that I have Some values now the way I want you to think about these values for a second is Imagine each one of them is associated to a different quality or a different feature So let's say for example where we're gonna show my age. I'm old I'm 35. Okay, then we're going to show my weight. I don't want to deal with that But yes, I am 200 pounds. I don't know the KG for that, but I'm heavy And then we'll go ahead and do I guess one more my height my height I'm roughly speaking about 60 inches right 60, you know roughly speaking 510 Okay 510 5 times 2 I'm 70 inches. Ah, that makes me feel better Anyways, now the entire idea is each one of these values has an associated Kind of title to them and that's where we get into The index parameter now the entire idea to the index parameter is what it's doing is it's a source It's it's attaching a label to our numbers So in our case that first one is referring to my age That second one is referring to my weight and that last one is referring to my height Now if I come in and just do a print on X right Print on X and what we see is that's exactly what's going on my age or sorry that 35 For me is being associated to the age index My weight is being associated to the or sorry my 200 is being associated to the weight index and The 70 is being associated to my height index. I could go in even further and Look at each one of these almost as if we were treating it like a dictionary So I could come in and just put some square brackets on my X and say height Okay, this is great, right? You know, you can do some of the same things that we've done in dictionaries Object we've we've already done this. So where's the benefit? This is where we start to say well Hang on a minute. I'm dealing with multiple Records when I'm doing data analysis. I'm not just dealing with one person Who has all these things? I might be dealing with tons of different people And so I have tons of different records and that's where we get into the idea of the data frame now The entire idea to the data frame is exactly that I'm going to take these series seriesies Sarai the plural of series a series of series And I'm going to now Associate them into one giant almost think of it like its own little tiny spreadsheet I'm just not gonna see it visually Now I'm going to change this just a bit I am going to start by creating a dictionary mostly because This is going to be one of the easiest ways to convert it into the data frame So to start I am going to go ahead and start with that same thing Let's say I have a series of data of People I'm gonna say we have five people and I want to record at their different ages in this case So I was 35. We'll say that I'm dealing with some 21 year old a 25 year old a 45 year old And I don't know someone fresh out of high school and 18 year old. Okay, fair enough Well, that's one entry But we also had some different records that we were going through and the second one was our weight so the same kind of thing will come in I'll go ahead and Just make my height one as well for the sake of simplicity. So again, I was 200 the 22 year old is 35 pounds. I'm just kind of making numbers up as you can imagine the 25 year old. We'll say is 150 45 year old I'll 45 okay, I don't know we'll say is 180 and then the 18 year old fresh out is a hundred and 25 okay that different weights doesn't matter. I'm the fattest one Anyways, I will not at least be the shortest one. I will at least Maintain that there are some people that are shorter than me There are 75 and I don't know 58 how's that? Okay, so I've done a lot of data. I've just built out a dictionary whoop-de-doo But what I can do with this is because I've built a dictionary One of the things that pandas will allow us to do is convert this into a data frame So this is another very common variable name DF data frame And I'll pass it in so data frame and simply put I'm just going to give it D I'm gonna give it my dictionary now the entire idea here is that I could then take that and Don't print D print D F and So that's exactly what you're seeing. I see suddenly my entry for my zeroth person myself 35 year old age 200 pound weight 70 inches in height and Then I've got each one of my different people as well Now there are some things that we can do with this one of the things I'm going to introduce now is this idea of Doing exploratory data analysis in the repel so the repel all this is the repel the console Repels just sort of the acronym for how Python Processes its data, but the reason why we are doing that is because what I can do is Since I'm in here and you can see I've got a little blinking cursor going on here I can type things in here. Literally if I did DF. I'm gonna see the exact same result Okay, that's fine, but maybe I want to do some data analysis. Okay. Well, let's say for example DF age Okay, so I can extract out a specific Feature from each one of my people so suddenly I have all of the ages Well, okay, since I can do that Maybe I can do some different types of analyses and in fact, that's what Pandas will do for us I can come in for example and say let me extract out those ages and then What is the mean of my data? Oh? Okay, so roughly speaking the average age of our our data set is 28.8 you can already imagine I can do the exact same thing with weight and Height Now one of the ones that I like to use very commonly is That will come in and we can also go with describe so describe what it's going to do is it's going to Describe your data so quite literally if we take a look at this it's looking at each one of the features and Then it's just describing All of those basic What's the word I'm looking for all those basic statistics from each one so say for example we have Account of five. We have five entries for each one. What were the averaged? Values of each one. What were those standard deviations? What were the men's maxes and then roughly speaking if we were to divide this into I guess you could call it quarters Here are the quarter sort of ranges for our data So it's some fun ways that we can start using Pandas and we'll actually see in just a bit how we can go a little further


Hey folks, in recent episodes of Code Club, I've been doing some deep dives into creation of climate spirals. We started out by making some static versions, and then we moved into animated versions. We made two different versions. One was modeled after the versions made by Ed Hawkins at the University of Reading, and the second version was modeled after a version that was created by NASA, who is where we're getting our data from. So this has been fun, and we have done this using chord polar within ggplot2. Well, say you don't want to use chord polar for some reason, and you'd rather work in Cartesian coordinates. We'll actually see in some future episodes when we try to make some interactive climate spirals that those tools for interactivity, they don't give us a polar coordinate system, so we'll have to make our own, right? So how would you do that? So in a polar system, we think in terms of a circle, or at least that's the mental model that comes to me, where you can think of a circle and we have a radius to that circle, and then we have an angle or theta, sometimes it's expressed as phi. So we want to convert that circle into an x, y coordinate system, right? And so what you could think of is a point on that circle being represented as a line from that point on the outside of the circle to zero, zero in the middle. So if you then know the angle of that line relative to the x-axis, as well as the radius, you can then use trigonometry, sine and cosines to go ahead then and get the x and y coordinates of that point out on the circle. So that's exactly what we're going to do today. We're going to figure out the angle from the x-axis up to any point on our circle, again, that being the climate spiral, and then our radius will be the temperature difference. Along the way, we'll have some fun making some other spirals to kind of show you how this all works. So I'm going to start with a blank R script to demonstrate some things. We'll go ahead and do library, tidyverse. I'll start by making a tibble, and we'll then have a column in there called theta, and we'll then give that a vector of values. And so I'll do seek, zero to one, and let's do it in steps of, let's do 0.05. And so that's going to be a vector, like I said, from zero to one in steps of five hundredths, right? And so then we can multiply this by two pi to get the radians around a circle. So we could do two times pi times all of that. And so now we see that we've got that column for theta, right? And so then we can add a column radius. And let's make that one, right? And so now we have basically the polar coordinates, and we now need to convert that into Cartesian coordinates, right? And so if I were to go ahead and plot this using ggplotas, you know, what would we put on x, what would we put on y, right? That that gets a little bit challenging, right? So x, we might think of, well, let's put theta. And y, let's put radius. And then let's do a geom line. So of course, we get a straight line. And so what we've seen in the previous episodes is if we add to this chord, polar, we get a circle, right? And so that it basically converts these values into a circular format. But again, I want to make a circle without using chord polar. So I'm going to go ahead and remove that. So back up here, I'll go ahead and add a mutate function. And I'm going to make a new value for x, and a new value for y, right? And so we're going to create two columns, x and y, x, I will map to x, y, I'll map to y, right? And so the formula that we'll use will be radius times, and then we'll use, let's try sign of theta. And then y will be the radius times the cosine of theta. And we'll pipe that into ggplot. And so we can see a very jagged line plot. And so what's happening is that we're using geom line. And so geom line connects the dots between different points in the order of the x axis, right? If instead we looked at our table output, we would perhaps notice that again, if we're looking at x and y, that that as we increase our x values going down through our table, we are decreasing our y value from one down to basically zero, right? And so that's basically I think the top part of a circle starting from 12 o'clock down to three o'clock. And so again, what's happening is that we're not getting this in the order of the points, we're getting it in the order of the x axis. So instead of geom line, we'd want to do geom path that then gives us a pretty nice circle, right? And so you can see that it's I guess a 20 sided circle because we're using 0.05 steps, right? And so there's a little bit of jaggedness to this. And if you remember the version generated by Ed Hawkins, it also had some straight edges between the different months. So let's do something fun. Why don't we go ahead and increase this up to 10. And then my radius, let's go ahead and change the radius and see what we can do here. So for radius, I'll go ahead and then do seek zero to one. And I want my length out to be the same as the length of theta. And so again, this should give us a table that's got theta and the radius. And as you'll notice, as we increase theta, we also increase the radius. So what do you think we're going to get as output from this? Yeah, we get a spiral, right? Isn't that pretty cool? And so again, as you kind of go around the circle, it gets bigger and bigger, right? Cool. Now we want to apply this to our code for making the climate spiral. Over here in files, I've already made a file called climatespiraltrig.r, which is a copy of climatespiralnasa.r. If you want this, you can go down below in the description for this video.  Great. So again, this created the animated plot climate chart that was stylized after the NASA version. I'm going to go ahead and clean this up a bit. And maybe what I'll do is I'll go ahead and remove that geome rect, as well as the scale X continuous. And yeah, let's just clean out anything that's commented in here. And yeah, so I'm going to then save this as climate spiraltrig.png. And I'll leave that in. And I'm going to also turn off this transition stuff that was in here from Gigi animate. I'll probably bring that back in later. Before I forget, I'll train this NASA into trig as well, as well as this one down here for the MP4. But for now, for developing this out, I'm going to go ahead and comment all that out. So we don't have to worry about that. And also I have this assigned as a variable, a, and so I'll comment that out as well. And so what I've found is that when we're making these animations, it takes a long time to render the animations, it could take like half an hour. And so if I'm testing things out, I don't want to have to worry about the animation. All right, so let's go ahead and run this and see what things look like now. Great. So that looks exactly like we'd expect it to. Let's now go in and turn off the cord polar. So I'll go ahead and comment that out. And so now we can see what this looks like without things being in polar coordinates. Great. So let's go back through our code and recall what we have. So T diff then is a data frame that's got the year, the month, and the temperature difference relative to the temperatures, the global temperatures between 1951 and 1980 with for this particular data set. Okay, we then had this other data frame next Jan, which helped us to get a jump from December to January. And so if you think about these weather lines that we have here, again, they're drawn as lines. It's not a continuous line, right? And so basically it needs a way to get from the right side of the screen back to the left side of the screen to start things over again. I'm going to do it differently this time because I'm not going to be using cord polar. I want to make one long line like I saw showed you in that big spiral, let me make one long line and then show us how we can spiral it over itself. And so what we will do is go ahead and comment that out for now. And I'll think I'll go ahead and remove this bind rows for T diff and next Jan, right? And so now what we've got is T data, which gives us the month, the month number, and then sorts it and removes the year 1879. So again, if we kind of run each of these lines in turn, we start out with the month number. So this is one through 12 for each of the months. Again, if we looked at the tail of this, we would also see it ending in three because the data goes to March of 2022.  So then we have this filter year not equal to 1879. That's again, because we had the next January added. So if we look at the top of this, we know that we don't have an 1879. So I can go ahead and remove that and then there's a line in here for step number. And so this basically is going to number each line of our data frame. And I'm going to go ahead and leave this in. Because again, if I look at T data, I can then have my step number going all the way out to the end of the data frame. So if I then do tail on that, it goes out to 1707. And so what that will allow us to do is basically plot our T diff as a function of step number. And then we can also animate by each month. So one of the problems that we've had in the previous animations, so we have to animate by year rather than by month. And so step number will make it easier for us to step by each month, I think. So the next thing I need to do is to convert either the month number or the step number into a theta value, and then use T diff as the radius so that we can create our own polar coordinate system. I'm going to do that back here where we're creating T data. And so we'll use radius. And that is going to be T diff. And then we're going to have theta, which is going to be, let's go ahead and use month number. So again, that now gives me my radius and my theta. The theta though is the month number. So one for January and 12 for December, I need to convert that into an angle in radians. And so to do that, I'm going to go ahead and subtract one from the month number so that January starts at zero, December at 11. I'll go ahead and put that in parentheses. And I'm going to then want to divide that by 12. Looking at T data, then I see that my theta goes from zero, probably down to one. And so I'm pretty happy with that. But I need to convert it to radians. So I multiply that theta by two pi. So two times pi times all that. Looking at T data, let's see more of that first year, I'm going to go ahead then and slice head. And I'll do n equals 12. And T data, we then see we've got a full year's worth of data, right? And so then we go from zero to 5.76, which I suspect is 11 divided by 12 times two times pi is 5.76. So that should be good. Now we want to get our x and y positions for these this radius and the theta. So it's going to be radius times, and it's going to be the cosine, because it's adjacent divided by the hypotenuse, right? So cosine of theta, and then our y will be the radius times the sine of theta. So let's come down to the plotting code. And we're going to want to update our x to go to x, our y to y, we don't want a group variable. So I'll remove that. I'm also going to remove this GM label. That was the year that goes in the middle of the plot. And then let's go ahead and run GM label or GM line rather with the GG plot and our data. And what we see again, we saw this before, is that it's going from left to right along the x coordinates. And so we need to convert GM line to GM path, like we saw with the spiral and circle that we made a little bit ago. And so, yeah, so now it starts, I think, yeah, so why we saw it was here. So this was January, February, March, April, May, June, we could double check that by doing GM label. And we could do AES label month. And so yeah, we see if it goes January, February, March, April, May, June, goes counterclockwise. So let's go ahead and try to switch the sine and the cosine. So do sine and cosine. So that then gives us January down low, February, March, April, May, again going clockwise, but from bottom up and around. So I think what's happening is that if we look at t data, that the radius again is the amount of temperature difference. And I we need this to be positive, right, because right now our radius is negative, rather than positive. So what I'd like to do is let's add a factor to the radius so that we're sure that our radius is always greater than zero. So it doesn't make sense to have a negative radius, because that's going to put us in the opposite direction. So we'll come back up to our t data data frame here, right? And so I'm going to add to this, let's do 1.5. We never had temperatures get below negative 1.5. So we'll do that. And let's see what it looks like now. That looks better, right? Now we have January at the top going all the way around. And I'm pretty thrilled with that. All right. So I'm going to go ahead and remove the month labels. And let's also go ahead and add another year's worth of data. So instead of slice head, I guess we could do n equals 24. We now get two loops of the climate spiral. And we don't need that next jam data frame like we had before. Because again, we're doing a genome path in these Cartesian coordinates. Great. So I could also then come back up here and remove that slice head. So we've got all of the year's data. So there is our climate spiral, just like we've had before. One subtle difference, however, is that you'll notice again that the connections between the different months is a straight line rather than curved. When we use cord polar, it naturally curves that line for us. If you wanted to, you could interpolate between the months to get more time points there, right? And so then it could look a bit more curved. But I'm going to be happy with this. I'll let you play around with that if that's something you're interested in doing. Okay, now we need to build out the rest of the plot. So I'm going to go ahead and make sure I've got all of these other data frames loaded that we use to make the pot look pretty. And that and then I'll go ahead and bring back in the label. Again, this should be the year in the middle of the pot. So now we see that our label is centered where we had it before rather than at 00. So we see, of course, that our year is at one negative 1.7, rather than 00. So let's go ahead and turn that to 00. Good. So now we have our year in the middle, just where he wanted it. So now we'll come back to the next line, which is GM segment, which is reading in from grid lines. And so grid lines is a pretty simple tibble. As we can see, it's got three lines that we're generating for x, xn, y, yn. And so this would this goes into GM segment, but it's not in our polar coordinates, it's in Cartesian coordinates, right? So if we ran that, what would it look like? Right. So it draws them in Cartesian rather than polar, obviously, because we didn't tell it to turn it into polar coordinates. So we saw how to make grid lines like this before, when I was doing a brief demo of how to make a circle, right? So let's do that again. And so what we'll do is come up in here and we'll do tibble, and then I'll do theta equals two times pi times seek from zero to one. And let's do in steps of point 01. And then our radius, let's let's do one, that will give us a one degree radius. And then I'll say line equals one degree. And so again, we now have that data frame. So I'm going to modify this, and we'll do rep on this. This again is the theta. And I'm going to do each equals three. And so that should repeat each value in theta three times. And let's double check that. Yeah, so that's good. So then on the radius, we could do rep. And we could do C, one, zero, negative one. And then I think we could then do length dot out equals length on theta, theta. And so now we see we've got one zero negative one. Good. For our line, then we'll come back and I'm going to copy this code. And then I'm going to give them arbitrary names of A, B, and C. And so yeah, so now we have theta radius line, we're good. And I will call this grid lines. Right. And I'll go ahead and comment this out for now. Load grid lines. So now I'm reminded that I need to convert the theta and the radius into x and y. So again, we could do x equals radius times the cosine of theta and y to be the radius times the sine of theta. And again, if we look at our grid lines, we now see we've got our x and y positions. So again, I'm reminded that we've got negative radius, right? So we need to add back in our scaling factor, which up here I had as 1.5. So I'm going to add a variable called radius bump. And let's make that 1.5. And then I can use radius bump wherever I want to add that factor, because again, we might come back and change it to like one or 1.1. And I don't want to update that 1.5 everywhere. And so down here in grid lines, we'll go ahead and add to this our radius bump. Right. And so now if we look at grid lines, we see that our radii are all positive. And so now if we come down to geompath with grid lines, x, x, y, y, and we're going to add a group. So we'll do group equals line. And I don't want quotes around line because that does different things, right? So it's giving me an error that it doesn't like how I'm doing my colors. And I think that's because I've got three colors, but I've got a whole bunch, 303 different rows. I don't want to set the color manually, because I need the color for the gradient on the color of the actual data, not the grid lines. So I think what I'll do is I'll break this geompath up into two steps. And so we'll have grid lines. So I'll do a filter radius, not equal to radius bump, right? And so that will basically be the zero. So you'll notice I'm using a filter within all this. Isn't that crazy? And I think I've got an extra parenthesis there. All right, so that's my AES. Let's just double check everything looks good. And so for my outer ones, I want those to be yellow. So I'll do that. And then I've got that. So okay, so let's run this and make sure we get our two, our one and negative one degree lines that worked well, right? So now we have our yellow lines. We need to add our green line for zero degree, where it was radius was equal to radius bump. So again, I'm going to copy this down. And I'll say double equals radius bump, make this green. Again, the reason we're doing this is because I need a different color scheme for those grid lines than I have for the actual lines. I'll trust that that works. We now want to add the labels to these lines. And so again, we're going to have templates. So let's go back up to the top and double check their location. So again, we had templates here, these are the labels on those templates. And so x needs to be zero. And then y is going to be these values plus the radius bump on templates. So let's add that and see if that works again, I'm modifying the code. And instead of running the whole thing through and getting all sorts of craziness, I'm running each step in a dip, adding on to the previous step, right? Very good. So those labels are now on the lines that they're supposed to be at 12 o'clock, so to speak. The next thing we need to do is add the month labels around the perimeter, which is this next geome text, which is getting the x and y positions from our month labels data frame, that again was way back up here. And so again, we have x and y in Cartesian coordinates, and they need to be in Cartesian coordinates, but they first need to go through polar coordinates, right? So for x, again, that's our theta. And this is basically like what we had way back up here for our month number for calculating theta, right? And so here what we'll do is look at and put that in parentheses, I'm going to subtract one from that, and then divide it by 12. And then we'll multiply this by two times pi. This will be our theta. And then the 1.5 will be our radius plus our radius bump, right? Now we need to convert our theta and our radius to x and y positions. So we'll do x equals radius times a sine of theta. And then our y radius times cosine of theta. And we can now run all this code all the way through that second geome text. Very good. Got it right on the first try. Good. So now we can move down to some of the more styling aspects where I don't think we have to worry so much about things being in polar coordinates or not. The first thing we have here is our scale y continuous with our limits. And again, the outer limit was negative two, and the inner limit was 1.5. And so what I'm going to do is I'm going to make this, let's do negative 2.5 to 2.5. I think we need that expand, but I'm not totally sure. So I'll leave it there for now. But I'm going to copy this down and make the same thing for our x continuous. I'm also going to add then chord fixed. And what chord fixed will do is it'll make sure that we have a circle and not an ellipse, right? So basically it'll make the proportions of our x and y fixed. And again, we're getting the warning message that we removed, the month labels, we're really zoomed in close. So I'll go ahead and make these limits plus or minus 3.5. If that's too much, we'll adjust. If it's not enough, we'll adjust again. So I think we actually want to go out a little bit more. So let's do plus or minus four on these limits. And that should probably be good sufficient. So that's good. I think this expand may have been screwing things up. I'm going to leave it since I got limits that worked pretty well. But I suspect if you remove that expand, then that three and a half probably would have worked fine. But we'll leave it. All right. So now we want to add in our color scale or scale color gradient to so that we get our line to be the right color. That all looks pretty good. So I think we can run the rest of the pipeline with the labels getting set to null all the way across and all of our theming. Very good. So we can then of course, send this off to our PNG file, I'm going to make the file square. So it'll be four and a half by four and a half. Nice. One subtle thing I notice is that our labels on these lines are on the lines. Whereas previously we use geome segment to have it go right up to those numbers. So I'm going to go ahead in and adjust those lines that we use for the grid lines. So I'll use a filter function to remove those rows from the grid lines data frame that I don't want to be included in the actual plot. So we'll get go ahead and pipe this to filter, and I'll do something like line equals equals a. And then I'll do theta greater than say 0.03 times two times pi and theta less than 0.97 times two times pi. So I'll wrap this in parentheses. And I will copy it. And I will then add an or to that. And I'll do another or right. And so these are going to be and C. And I'm replicating this three times, because we're probably going to need different parameterization for our Thetas. And I think I switched my sine and cosine over here in grid line. So I'll switch that real quick. So sine and cosine. But I can also kind of tell that there may be a little bit too big for some of these. So maybe for a line a, which is the outer line, maybe you'll make that to one and 0.99. So that looks better. And then back up here, again, I think I adjusted these a little bit in the last episode, I could probably look back at what I did in the last episode and adjust accordingly. But let's go ahead and make the B line. So 0.025 and 0.090.975. And, and then here, let's open this up a little bit. So we'll do 0.035, 0.965. So it looks pretty good. Maybe that inner circle could be opened up a bit more. I'm going to open it up a little bit more and make it say 0.05 and 0.95. Great. So I'm pretty happy with how that looks. Now what I want to do is be able to animate this. So again, coming back to our code, I will reassign this back to our variable a, right? So we have that there, and I can bring this up a line just to make it all work. Look back through this code, we can go ahead and remove our cord polar. Some of you are probably wondering at this point, Pat, it's a lot of work to not get very far. And so I'm now going to bring back in our transition. And I will do transition reveal on step number. And then we can then bring in our animate and animate save. I did make that trig, and I'll make the height and the width the same. So 4.5 by 4.5. So we have our animation running. I'm pretty happy with how this came out. Again, the subtle difference between this version and what we did in the last episode was that the edges on our climate spiral are straight, rather than curved. Again, that's because of the transformation that you get with cord polar on all of the lines that we don't have here. And so if we wanted to get more curved lines, you could go ahead and interpolate between the different months to get a more rounded appearance to the figure. Again, you might be saying, Pat, this was a lot of work to not get very far and perhaps even to have a figure that looks worse. Well, in the next episode, what I want to be able to do is to make an interactive visual, right? And so we could imagine that we have this X and Y or polar coordinates. But then you could also imagine this being a stack, right? So where each year is a different layer in the figure. And so that could be a three dimensional figure. And so if we want to use interactive tools to build out those figures, unfortunately, it doesn't seem that we can use polar coordinates directly. And so that's why we have to go through this initial step of converting into Cartesian coordinates, what should be in polar coordinates. So again, I hope you found this interesting. If nothing else, you learned how I troubleshoot through different problems. And you'll see that, you know, trigonometry functions do have a use outside of high school trig classes. I hope you had fun with this. And if nothing else, I hope it was a little bit entertaining. Please tell your friends what we're doing here on Code Club. And we'll see you next time when we start talking more about interactivity.