Skip to main content
Metaist

1 hour to make a visual schedule (Design Lab #1)

How I designed and built a visual schedule maker in a little over an hour.

This is the pilot episode of Design Lab which I recorded with my sister-in-law, Victoria Lupia.

References #

Introduction #

Lev Novikov: All right. Welcome to the first episode of what I'm calling Design Lab, where I invite guests to come tell me about their problems, and then we try to design something in an hour to see what we can do. Today's guest is Victoria Lupia, who is a mother of two and art conservator from Oklahoma. Hi, Victoria.

Victoria Lupia: Hi, Lev.

Lev Novikov: Victoria, fun fact, is also my sister-in-law. Thanks for agreeing to be the inaugural guinea pig for this program.

Victoria Lupia: Well, thanks for helping me with my problem.

Lev Novikov: Glad to help. So the way we're going to do this is we're going to start with talking about what the problem is. You had sent me some photos of your current solution. And then we'll do a little bit of design. And then we'll try to build something in an hour. I've done very minimal prep. So a lot of this is going to be kind of on the fly. And you'll get to see a little bit of the process. But I'm hoping that you'll be able to constrain the problem to exactly what you need. So why don't we start with the problem?

Problem #

Victoria Lupia: Well, one of my children has special needs and does very well with a visual schedule. So a strip of paper with a series of pictures that explain what she's going to do that day or that morning or, um, for most of the day. And it helps her feel better, uh, more in control and have some, you know, sense of time in a way that young children generally don't. Um, what I have been doing is going online and finding clip art pictures, um, or, you know, free images of whatever I need, either an activity or a place. you know, dragging it onto my computer, saving it onto my desktop, and then dragging it into a Word document, and resizing it, and lining them up, and it just takes forever. And I was thinking there's just got to be an easier way, you know, where I could create my own bank of images. and just drag and drop and something would automatically convert everything to the right size so I don't have to spend, you know, 30 minutes clicking and resizing everything and printing and formatting. And I thought, surely there's an easier way to do this. So I said, hey, Lev, can you help? Because I'm not a programmer.

Lev Novikov: Yeah, that all sounds right. Is it okay to share those three examples that you shared with me last week?

Examples #

Victoria Lupia: Absolutely. Are you going to share them or do you want... Okay, yeah.

Lev Novikov: I'm sharing them right here. So this is an example you've had of like a process to go to the toilet.

Victoria Lupia: Yeah, this is a very short visual schedule that says all the steps you need to complete a single task.

Lev Novikov: Right. And then here's another one you sent me, which was just like a series of what the day was going to look like.

Victoria Lupia: Yeah, this is a morning schedule. So you wake up, you go to the bathroom, you wash your hands, brush your teeth, brush your hair, and get dressed.

Lev Novikov: And then this is a more complex multi-part one.

Victoria Lupia: Yeah, that's an entire day schedule where we're going to have breakfast. You're going to do some work at a table, going to watch some TV. We're going to go clothes shopping. We're going to go food shopping. We're going to eat lunch. We're going to go to the playground. We're going to a speech therapist, have a little break to watch TV again while I unload the groceries. We're going to get in the car, go pick up big brother, go to a playground again, and then end the day with a Slurpee from 7-Eleven.

Lev Novikov: Sounds amazing. All right, cool. So, the thing that I'm getting from these is, right, it's like a panel, and each of these is, I don't know, roughly an inch, right? It's like four inches by, right? What's the height of this?

Victoria Lupia: Well, it's an 8 1⁄2 by 11 sheet of paper, and it's cut into three, so that's probably about 2 1⁄2 inches, but the pictures are probably only about 1 to 1 1⁄2 inches high.

Lev Novikov: Perfect. Let me just write some of this stuff down, right? Okay, so we've got like one to 1.5 inch high images. Well, the padding is gonna be important also in the way that we set it up. I'll show you what-

Victoria Lupia: What do you mean by padding?

Lev Novikov: The white space around and between images is important.

Victoria Lupia: I think you want to minimize that at the edges, like just at a standard border. And then just enough space in between that they're kind of discrete time units or whatever.

Lev Novikov: We'll get into that as we get into the design more closely. I see that you've cut these into strips. Is that just an artifact of printing, or you mix and match them?

Victoria Lupia: Well, that's an artifact of the way my child reads them. I want to go left to right. And I'm not necessarily sure right now if she knows to drop to the next line.

Lev Novikov: I see. I see. So you present them one at a time.

Victoria Lupia: So, yeah, exactly.

Lev Novikov: Got it. And then, OK, so this one had one, two, three, four, five, six. How important are the captions part of the thing or is that a thing that you know,

Victoria Lupia: I think in an ideal world, I would like to be able to add the caption and perhaps change a caption as needed, for example. You know, Let's see from the picture. I mean, that's fine.

Lev Novikov: Okay, so there's a picture and then the caption and is the height of this significant or that just how it turned out?

Victoria Lupia: No, well, I think that says like how to go to the toilet in that one. That was something that I didn't make. I only changed, I changed one picture as you can see with some scotch tape.

Lev Novikov: Yeah.

Victoria Lupia: That just tells what task, you know.

Lev Novikov: Got it. OK. All right. I see. So most of them don't have any kind of title or any kind of text. Here, we've got the heading.

Victoria Lupia: But I think it would be good to help with some sight words.

Design #

Lev Novikov: For sure. All right. We'll focus on the core problem first, and then we'll expand out. So why don't I, here's what I'm going to do. I'm going to create a little place for us to design. And we're going to use this super complicated tool called Slides. I didn't do anything crazy fancy. This is going to be just a brand new Google slide. And I'm just going to drop all this. I'm just going to drop a picture of what we're going to build. OK, so ideal world, there's some heading thing here. But that's going to be secondary to the main bit. Then I think what we'll do is we'll make a little box. And this box will have a little plus sign in it. And that plus sign will be like, hey, you can add images by clicking the plus, or you can just drag and drop a bunch of images into this area. And then what we'll do is, oh, here's an idea. This may be a little out there. This is not gonna be the first thing I'm gonna build, but an idea that I just had was maybe we let you just like add a row. Right, so yes, and then that way I don't have to say like what the format is. It's just sort of you drag your you add an image at another image at more images. Drag a bunch of images. They'll just upload into one row, but you can also say add another row. And that will. sort of create another one of these boxes that you can drag and drop images into. And then once you have some images, this kind of symbol. It's not super pretty, but close enough. Those pretend that that's an image, right? So every time you add an image, you'll always have that little plus this little plus box where you can just drag and drop more stuff. Yeah, you could do one at a time or you could do them all at once. And the idea would be that. I guess afterwards I'll need to add some kind of way to delete stuff too, so maybe some kind of little button. Little delete button over here. That's just kind of like an X. And this isn't super fancy. This is just kind of helping me plan out my thoughts about what features we need to build. And we said maybe a little caption, maybe a little place to add a caption. Okay. Right. So once you add them, you can add a caption. Oh, and then we also want to be able to drag these things around.

Victoria Lupia: Yeah. Can you, yeah. So which position and have to maintain their little formatting row.

Lev Novikov: Yep. Yep.

Victoria Lupia: alignment, I guess is the word.

Lev Novikov: Exactly, exactly. So we're going to do that. So we'll add a little handle here or some, it's gonna be some some way that I'm denoting with this little double bar at the moment, but it's probably could just grab the whole thing as long as you don't click on the X to just sort of grab it and drag it and drop it. Okay, so, so far, so the features we have are Add a heading, drag and drop images. Actually, that's two different things. That's like rearrange images. And before that, there's drag and drop images from the computer, right, to display them. And we also have a way of removing an image. add a row and probably I guess we'll have to add some kind of if you want to delete the whole row.

Victoria Lupia: Okay, anything that's obviously... Can you link the caption and the image once you've...

Lev Novikov: Yeah, we're assuming this is like one... This is like one item, so when you drag it, you're dragging the image and the caption. This is going to be one unit. Is there any obvious thing that's missing?

Victoria Lupia: Nope.

Lev Novikov: OK, cool. All right, this is going to be the first thing we're going to work on, dragging and dropping images. That's the hardest and probably the most important thing. Everything else, rearranging is probably going to be the next thing, just to get it to have some kind of basic functionality. Headings and captions I'll work on last. Removing them is, we have add and remove, we have add and remove for an individual item, then adding another row is going to be not too bad. And then, oh, actually, one thing we really need that's not Not something that's here, but we need to lay out. We actually need to be able to print these things.

Drag & drop images #

Lev Novikov: OK. All right. Let's start with dragging and dropping the images. OK. So I'm going to move this out of the way. I'm going to start by making a new file. I'm going to make an HTML file. For those who are watching, you might be surprised that I'm not using any kind of framework or any kind of anything. I'm going to try to do this as light as possible so that we can just get started. And later on, maybe this becomes a much more complicated thing. But now, how do you write that thing? Doesn't it start with a? All right, whatever. Why is everything so weird? Nunjucks, this is not Nunjucks? There we go. All right. All right, so in order to do this, I think what we're going to do is... And we're going to need... We're going to need some kind of area. Let's make the main area the area where we're dragging stuff around. This has got to be. OK. All right. And in here, we're going to start with something where we can drag and drop images. Now, I actually did do a little bit of prep. It's one of the two things that I actually looked into, which was, There's a nice little, there's a couple of things. First one is, there's this nice guide and all the links will be in the show notes, which I'll have to make, but which is, this is like a much more complicated guide of like, let's say we were uploading something to a website and right, so this is like dragging a bunch of images and uploading them. We're going to just yank out all the stuff that has to do with uploading stuff places, and we're just going to do the very basic drag and drop images just locally sourced. So that way, you don't have to worry about setting up a server or anything like that. OK, so let's take a look.

Victoria Lupia: Thank you.

Lev Novikov: Yeah, yeah, yeah. Well, you or anyone else who wants to make something like this. OK. What they do is they make a fake input, which is where you're going to drop things and then make a drop region, open the file selection, clicked. Okay. This all sounds good. Let's take that too. So what do they actually have here? Some body thing. Then they have this drop region. Then they have a message that says like drop images. Okay, good. Right. So let me get this going here. I'm going to run a little local server just so that I can look at my beautiful page, which is currently empty. Excellent. And now I'm going to start adding little things. And actually, I also have to make a quick file. So this file is going to be where we're going to put all style information. I'm just directly linking LESS over here like this, so that way we can write our style sheet over here on the right and the HTML on the left. And this will let us do a little bit of styling. OK, so in the main, we're going to start with a row, which I'll just call a row. And in the row, there will always be, at the very end of the row, there's going to be a box. And I'm going to call the drop images. and the drop target will say nice make it look like a background color so a little bit of gray background color and maybe the border is like pixels, dashed, or something like that. Okay, yep. A little gross at the moment, but it's fine. Around it. and maybe let's make the border radius five. Okay, a little better. We'll work on fonts and things later. Okay, so that's gonna be the place where we're gonna drop the images onto. Okay, fine. And oh, right, let's start making this fake input thing. So what they're doing is image preview. All right. Right, OK, so we don't care. We just want any kind of image that you have. While this is going, Victoria, can you email me a few of your clip arts that you use? And that way I can try practice using them. OK, so what happens is there's eight things that can happen. You can drag a thing in, you can drag it out, and then you can drop it. Fine. This all sounds pretty simple. Add event listener, drop region. Then we handle the drop event. Fine. We don't actually have to transfer the files because we're not sending them anywhere. This only works if the files are derived from local filesystem. Perfect. That's all we ever care about. Although, it's nice that they have a handle. Like, if you drop an image from a different tab onto here, it will also work. All right. That's fine. We can keep that. Preview, preview. This all looks good. and they don't actually care about the uploading. There's the complete thing, additional improvements. This isn't so important. Fine, let's grab all their photos. I'm just gonna grab all of this. And let's stick it in.

Victoria Lupia: How many pictures do you want?

Lev Novikov: Like three. Yeah, nothing too crazy. All right, let's take a look at all that stuff. Okay, we don't actually have to do any of the upload stuff. We'll grab all that, make all that go away. But drop region, we do have a drop region. And image preview, that wasn't in their thing. What's that? Oh, image preview is this. And an image preview also. And a target, oh, the drop region. That's the whole thing. I'm just gonna try to get, you know, get it to work in a very basic way. If I can get it to work in a very basic way, then we can focus on trying to get this to work better. Okay, so this actually is not super necessary. Preview, progress, read, waveform data, upload location's not really important. And we're gonna do none of this. None of this. Okay. And we don't even have to read that image. No, that's not true. We do have to read the image because we have to get the source. Everything else is going to be.... All right. Let's see. Did you send me those things? Yep. Okay, cool. Let me just check my email. Got it? Cool. I see the problem that you're having, because these images are all kinds of different sizes. Let's download these to this folder. Let's make a quick folder. Hopefully, this is not too boring. You know, it's just me moving stuff around. All right. What is this? This is like... And then washing hands. And washing hands, let's do one more. This is the speech pathologist, speech therapist. Great, as now we have a PNG, a JPEG, and we have a couple of different types, so that's great. All right, let's see if we can get this to work. So if I refresh this, I should be able to, let's see, maybe that doesn't work from this context. Maybe it will work from here. Nope, that did not work. Oh, well, that would be a problem. Let's resolve that problem. So what's the problem? Line 11. Line 11, dropRegion, getElementById dropRegion. I made a new element called dropRegion. Oh, that would be a problem. Hard refresh. Nope, that also didn't help. Okay, let's sanity check this. What am I missing? Oh, well, I know what's wrong. The script is running before anything else has loaded. Nothing missed at the time.

Victoria Lupia: Over here.

Lev Novikov: All right, now everybody's happy. Good. So now let's take a kids table picture. Okay, cool. And if I add a speech therapy picture, great. Okay. I mean, obviously this looks terrible, but the point is the basic concept is, right? The basic premise is somewhat justified. Okay, cool. All right. So it was able, and if I refresh, all those pictures go away. All right, fine.

Flexbox layout #

Lev Novikov: Now let's move on to, so that was great. That's super helpful. That's how we add images. Fine. Let me just add another image and see what kind of CSS does it add around this. Does it do anything to this? Oh, I see. Image preview, image view, and then that's the drop target. OK. OK. So what I want to do is I want to switch these around. And I'm going to say, let me use Flexbox for this.

Victoria Lupia: Alexa has just come in to join us.

Lev Novikov: Hi, Alexa.

Alexa: Cash?

Victoria Lupia: Who is that? Who do you hear?

Alexa: Uncle?

Victoria Lupia: Almost.

Alexa: Uncle Lev.

Lev Novikov: That's right, Uncle Lev. Exactly. OK, so now if I take this in here.

Victoria Lupia: No, we're just listening right now. He's helping me make your schedule.

Lev Novikov: All right, this is what we want. So we want to display flex and a flex direction is going to be in the row direction. So display flex and help this row, but just in case it isn't, we'll make it flex direction, the row direction, because we're making a little row. And what we'll do is we will not do any wrap. Although wrapping is not terrible, right? You could just keep adding images.

Victoria Lupia: I think wrapping is good, yeah.

Lev Novikov: So why don't we just do, you know, just keep adding pictures.

Victoria Lupia: If you have too many pictures.

Lev Novikov: Yeah, yeah, just keep going. We don't even need the concept of rows at that point. You just, yeah. Okay, that kind of keeps things simple.

Alexa: Okay, mom.

Lev Novikov: Okay, and I think we'll do space evenly for justified content. Oh, it's kind of just really spaced thing.

Victoria Lupia: I think, can I...

Lev Novikov: Yeah, please.

Victoria Lupia: So then I think if you have fewer than fit in a row, you'd want them all.

Lev Novikov: Oh, you want them kind of like ...

Victoria Lupia: the top the top line. Yeah.

Lev Novikov: flex-start. Okay. Yeah, no problem.

Alexa: I'll make a hat.

Lev Novikov: All right. And then do you care about top alignment? Um, central line.

Victoria Lupia: Oh, I want them all the same size. Does that make sense?

Lev Novikov: Yeah, I know you do. And we'll try it. We'll try it as well. Let's see. We could just say, well, why don't we wait and see how it goes? We'll come back. We don't have to pick all of these things now.

Victoria Lupia: Probably bottom alignment is if you want the words all, the captions in a row.

Lev Novikov: Ah, that's a good idea. Although the captions are going to be... Underneath. Yeah, they're going to be slightly different. We'll deal with that later. I mean, just if there's anything else that's particularly painful, we'll deal with all these gaps. Not worried about that.

Victoria Lupia: We're tying it in with, like, how to read from left to right.

Lev Novikov: Yes, yes. That makes sense. All right. So let's see if I grab three pictures all at once. That work? No, that didn't work. Oh, because I didn't drop it in the drop area. If I drop it in the drop area? Yes. OK, cool. Now I need to do something for the individual items. So the individual items in here are gonna be with, let's look at how this, what does this actually do? Image view. Okay, so each image view, it's actually not the drop region, it's the, Image preview is got the flex and going. Preview and inside that there's an image view and that image view we're going to say its max height. See OK, so the images are different sizes and what we could do is we could say that we control their like you could either control their width and then have their height be automatic or you could control their height and make their width automatic. Right?

Victoria Lupia: Yeah.

Lev Novikov: So which is the thing that matters more visually? My gut is that if you made the heights the same and one takes up more space width wise, that's okay. Right? But if you had them all the same width and then the heights are all kind of weird.

Victoria Lupia: Yes, I think that's correct. My one caveat is that sometimes I, or yeah, let's go with this.

Lev Novikov: Okay, so what's the width that we're going to force on all of the images?

Victoria Lupia: Let's go with one and a half inches. Is that reasonable?

Lev Novikov: Yep, that's fine. And we'll say the height is auto. And let's make a little border. just so we can see. We'll pick solid black. We'll be able to see where the border of them is. And we have to make the image that's inside this image view have a height of 100% and a width of 100%. Let's just do width as 100% and the height as auto. This is for the image that's inside the little thing that contains the image. I know it's confusing. All right, let's refresh this and try that. That didn't happen at all. What's going on? Okay, so it's got the image. It's got little image views. These are all great. How come they don't have any styles? Oh, I know why. Because the LESS they get reloaded. No, now I'm really confused. Image view.

Victoria Lupia: Yeah, that's a picture of Janet.

Lev Novikov: Drop region is not this drop region. This is called this. Okay. Let's just do this for the preview part. Let's try those images again. Okay.

Victoria Lupia: Oh, that looks good.

Lev Novikov: All right. We're getting there. We're getting there. Okay. So we've got the, got a little bit of, We've got some basic thing going here, which is great. Now, let's grab one of these images. OK, so one of the things we could do with this image view is we could add a little padding to the right. Actually, let's make that margin and not padding. We can make that a little smaller, let's put five. I can turn off this border. So it's just the, you know, it's just the pictures as you want them, but I'm keeping the border so I can see that the images are happening the way that we want. Okay. And what I might do is if I refresh this and then drop one image. So if I do the first image, okay, that's the kids, the kids table and then speech therapy. Okay, it adds it right after. Cool. All right, so did you want a little, do you think that little padding is good or?

Victoria Lupia: I think, yeah, I think we need a little padding in between. Yep.

Lev Novikov: Cool. All right. So let's just do that. So we'll say that, um, yeah. All right, cool. All right, so now little things show up. Excellent.

Victoria Lupia: And- Do they have a box around them?

Lev Novikov: I am putting that little box around me.

Victoria Lupia: Okay, yeah.

Lev Novikov: I can remove that box. I'm putting it, I'm just having it there for now so we can see where the boundaries are.

Victoria Lupia: Okay, cool.

Lev Novikov: All right. All right, so then let's make this drop target thing. I could deal with this later. Drop target is not, Like, ideally, what I would like is the entire page to be a drop target, right? You can just drop the images anywhere on the page. And I might do that, but not at this second. Right now, we're just, we got the first, got the first little thing done, right? Which was, we can drop images in here and they automatically get sized to the right, to the right size. Okay. The next thing that we want to do is,

Rearrange images #

Lev Novikov: So we got drag and drop images from the computer. All right, let's do rearrange, rearrange images. It's okay, so you've got them, but now you could just, you could drag them, drop them back onto itself multiple times because, right, you can take an image from anywhere, right? You could take, Let's just find an image. Here's an image. If I drag it onto here, well, guess what? Now it's, right, you could take an image from anywhere and just drag it onto this page, onto this box, and it will show up. So that's all great. Now let's do step three, or item three, drag and drop images, but rearrange them. Okay, so to rearrange images, we're gonna use this little tool. Shopify had a long time ago put out a tool called Draggable. What this lets you do is swap images. I don't know if I need them to be swapped or if it's just sortable. Let's see. Yeah, that might work. I don't care about this particular thing. I just want this behavior. Zebra. Yeah, that's fine. Multiple containers. I don't really need multiple containers. I just want it to work. Oh my goodness. What? Surely there is a simpler way to get started on this. No longer maintained. Beautiful. All right. Yep. Let's just take their entire bundle. I don't care. We'll figure out all, which if we need fewer pieces, we'll use fewer pieces and won't make it so big. But at the moment, it's important to just get it to work. So step one, make it work. Step two, make it clean. All right, fine. So now I have all the things. What was this sortable? Okay, sortable. There we go, that's a little more understandable. Sortable is a new draggable sortable, and then you say which thing can be sortable and what's draggable inside that thing. Okay, that's trivially straightforward. Oh, I wonder if this will work if I add more things or if I have to do some kind of refresh when I add more stuff. Let's try it. Let's see what happens. So somewhere at the top, I'm going to say, great, a new selector, query selector all. So that's the unordered list. And these are the list items inside that unordered list. So we're going to say, In the image preview, the draggable is the image view is draggable inside that thing. And there's going to have to be some kind of way to update this when you drag new images in. So this is likely to not work the very first time I try it. What happened? 404. Oh, shucks. OK, OK. I just get a version of. Whatever you give me, I'm not going to complain. and stuff. NPM. Oh, it's a different version. Okay. That's fine. That's fine. Let's just do that. And at this point, I'm not worried about like, Oh, do I have the latest version of that thing? I just want something that works. It's not a constructor. Oh, boy. The URL was guess and it it might not be correct. Okay. Let's try. It's weird that this... Okay, that works fine. So now I drop this in here and I drop speech therapy in here. Boom. Look at that. See that?

Victoria Lupia: I see it.

Lev Novikov: Okay. All right, so now you can rearrange and add as many. Oh, I see, but now you can't drop.

Victoria Lupia: Can you copy and paste?

Lev Novikov: Can you copy? I mean, you could just update. You could just drag the image from your computer again.

Victoria Lupia: OK, again. That's fine.

Lev Novikov: Yeah, you could do that as many times as you want, right? So I could take all these things and just drop them a bunch of times.

Victoria Lupia: Perfect.

Lev Novikov: and then I can rearrange them however I want. Okay, so that takes care of that item.

Lev Novikov: Okay, so now let's just quickly jump down to print layout. Let's make sure that when this prints, that it actually looks reasonable. It's gonna look terrible, right? Okay, that's what I thought. Okay, so to make this print properly, Well, first of all, we want to hide this drag and drop images thing. So what I'm going to do is maybe now's a good time to make the drop region could be the entire page could be the drop region. There's really no reason why you couldn't do that to everything. I'm just going to do really simple. Let the images go. I'm actually gonna drop target. Do I even need the drop target? So let's just get rid of it. Super simple. That's number one. First thing is, it's really simple. I'll add a little thing. Nope. What's the problem? Ah, the body is not that big. Okay. Having something inside of it. I see. Okay, fine. So. This is fine. Why is it that big? I don't know. Alright I'll clean that up later but I think now is the body the right size? No it isn't. Why isn't it display:block? Why is the body not the right size? Oh. Yeah, OK. I don't think that's what I'm saying. Could help in many cases. That sounds pretty scary. Nope. Hmm. I feel like there's a way that I do this normally that takes care of this problem, but okay, I'm not gonna deal with that right now. Because I think as long as I drop it somewhere in the vicinity of this thing, okay, that's fine. I will fix that, but not this second. Okay, let's make a print layout. How do you say this? How do you say this? blah, blah, blah, blah, blah. No, it is how you say it, media print. Great. So empty... That thing will get hidden. What else do we need? We don't need that much else. Actually, let's make this just for testing. Drop the images there. It's a little bit of Okay, I see the problem. I need to add like two pixels of padding inside the image so that all around the border of the box is visible. There we go. All right, so that's our print layout. What else? Captions.

Victoria Lupia: Do we need space between rows?

Lev Novikov: Space between rows. Yes. Here's what's going to happen. Let me just add this a bunch of times. So if we do this, yeah. So I don't need this anymore. This could help. So this has to do with how you Align the content. Space around looks like the right thing. Just go space around. Items evenly distributed with equal space around each line. Yeah. So align content. space around. That's for this thing. And do this and this now, and it gave me a thing that I wanted. Hmm. I could just add, that's not enough to wrap, okay. Okay, I will add the same padding that we have here on the right. I'm just gonna add that to the bottom. And that'll take care of that. So. We have a margin right. I'm going to do this. I'm going to say, add. Like that. Does that work? Victoria?

Victoria Lupia: Sorry, you didn't hear that. I think that works unless we're adding a caption and you lose some space from that.

Lev Novikov: It's okay. It's okay. We'll add the caption and move the padding to the bottom. Yeah. Alright, so

Add a caption #

Lev Novikov: We'll deal with that alignment thing in a second. So I think captions are probably more important than heading of the entire thing, right? Okay, so let's start with that. That's our next item. And we're getting close to the hour, but if you're okay to keep going, I'm okay to keep going. Let's add captions. Oh, I didn't make a way to remove images. And I guess this is no longer necessary. Adding rows and removing rows is not necessary, but removing an image will be necessary. We'll deal with that later. Let's add a caption. So how can we add a caption? Well, what we could do is we could have a little bit of space from here to here that always has just like a blank caption, just a blank, you know, outside the box.

Victoria Lupia: Yeah, space, just typable.

Lev Novikov: That's typable, yeah. So what could we do for that? All right. So the easiest thing to do there is that we wrap the image. Let's see. So I'm just reading their code. OK, so what they're doing right here, this is where it actually happens. So they create an image, and they create a div, and then they read the file. And then when it's done, they create this little source thing, which then goes in to this image preview. They append that to image view, which is image preview, append the child of the image view. So what we're going to do is we're also going to append, let's make the border be around the image. And we'll add some padding for this thing too. And then we'll have another thing that we're going to add to the image view, that's going to be a little text box. And it's going to look horrible at first, but we'll make it better very quickly. So we'll say, let inputBox equal document.createElement input. And we're going to say, imageView.appendChild inputBox. This is gonna be a place where you could put the caption. So let's see how that looks. Okay, so there's a little spot right there. Cool, okay. Couple of things that we need to fix, but that's okay for here. So this is gonna be the caption. Mm-hmm. All right. So first thing we need to do is make that caption fit within the bounds of the box so that we don't have this kind of thing going. That's number one. So inside the image view, there's an image and there's an input. And the max width of this thing is going to be 99% of its container. And. And when you print...

Victoria Lupia: We don't want to border on the yeah, very good.

Lev Novikov: So. Yeah, yeah, yeah. I think that should make sense. And we'll have to deal with the vertical alignment to the second, but let's just see if we can get this. Okay. So, okay. So they're all the same width, but then we want to do that thing with the vertical alignment being on the bottom. So this was what we were talking about. This align-items, flex-end. So that's over here, align-items, flex-end. That will give us...

Victoria Lupia: Looks great.

Lev Novikov: Now the border around the image though feels a little weird.

Victoria Lupia: Okay. Right. You notice that they're somewhere smaller.

Lev Novikov: It would probably look better if- Right, exactly. So if we just kind of cut that out for a second. And I think we're getting pretty close. So here, okay, so then you drop your images here. Great, you got all your pictures. You say what they are. I have to turn off this thing. Okay, so the way it's set up right now, it's if you click anywhere, it will automatically try to say like upload an image. So you could do this like on a mobile browser. I'm gonna turn that off. But, like, totally unnecessary. That's not the situation. That's, like, not really the situation you're going to be dealing with. So, I think it's only. OK. Right. I don't want you to do anything. Let's upload images. OK. And then, oh, let's just. Oh, cool. I managed to crash it. Give me a second. Technical difficulties. Bam. All right. So now, if I bring this in here and I say, one, two, three. print.

Victoria Lupia: Can we center those?

Lev Novikov: Yeah, we can. Let me do that right now. I think this should work. Okay.

Victoria Lupia: Yeah.

Lev Novikov: All right. Obviously you can leave these blank. There's nothing. Oh, right. You wanted to know if, right. So I told you that the caption would move with the thing.

Victoria Lupia: Yes. Looks good, right?

Lev Novikov: It looks great. One problem is it's very hard to like since the. I need to. I need to tell draggable to not like I can't select the text in here.

Victoria Lupia: OK.

Lev Novikov: You can click in there and you can type, but it's very hard to select because it's using that as a drag handle. So let's quickly see if there's a. a little option of like a thing, like don't drag on this thing, you know, disable the drag handle. There's probably like thousands of options that are, yeah, draggable options, right? There's tons of stuff. Handle. Specify CSS selector for a handle element if you don't want to allow drag on the entire element. There we go. So the handle is going to be the image, you could drag the image, but not the text box. So let's see if that works. Um, is image. That probably would work even if I did, even if I specified it incorrectly. Right. That lets you think, but here you could type and you perfect. Okay. So the images lets you rearrange them to fancy, but the caption is here. All right, what else do we have?

Remove an image #

Oh yeah, we should make it, you should be able to remove the image. Let's see, what can I do? I can add a little tiny little button like in the upper right-hand corner of the image that lets you remove the image. that's only visible when you hover over the image or something like that. So what we should do is over here, we should remove button, a little button, and removeButton.click. It's gonna be a function that when you click on that button, it will remove this image view. Image view removed. That's a hilarious way of doing this, but that's okay. And then you're gonna, image view removed. We should probably put something on that image. It should have some sort of... This should be... Okay. Oh, look, again, terrible. Okay, so there's the X. If you click the X, nothing happens, okay? All right, why? Why does nothing happen? This button. Click. No. Click. Okay, maybe a bit more traditional way. addEventListener, fine. Let's add addEventListener. Click. Function. If that doesn't work. I can't refer to this. Okay, that looks fine. So now let's make this look less horrible. One way to do that would be to sort of... And... Absolute right of zero. Oh, no, no, no. Position relative? Position fixed? Nope. Fine, forget position. We'll do it by saying that it's flat'd to the right. And like red, some kind of light red. Let's do it. What if I put it after the image? Let me see. Alright. Okay, that looks less terrible. Okay, so that's gonna be for our button.

Victoria Lupia: Will that disappear during printing?

Lev Novikov: Yes. So what we're gonna do over here in the print thing is we're gonna say, well, it's actually by default, is what we're gonna do. By default, it's gonna need to know this. But when you, Hover over the image. What will happen now is. When you. It jumps a little bit because, but so now by default you can't see it. You hover over it. Okay, so you know what, let's make it so that for printing no matter what, the display is none. Input border is none. And the button. Now, even if you had hovered over an image and you hit print, one. Oh, I know why. This is very, very specific. So in the image view, a button is going to be not visible, absolutely super important, override, override. OK, now, OK. Perfect. All right. All right, so that's done.

Add a heading #

Lev Novikov: And now we just have a heading, which we could do pretty similar. It's a little bit easier, because it could be something like that. And let's see. that this font size. I don't know, what's the font size? Should we use 16 point?

Victoria Lupia: Sure.

Lev Novikov: And the width is 100%. Or, yeah, I'm sure. 100%. Center. We can make it. Where is it? Where'd it go? Did I not save that? Oh, I didn't save it. Okay, my fault. That's not width of 100%. That's more what I was expecting. Oh, header heading, whoops. Like. Okay, so, well, no, that's gonna look terrible. This has to be, this has to be. Why is it? Oh, because I have the width. There we go. I'll put width, and then it makes sense. OK. So Today's Schedule. It should be supported. Great. And oh. What happened to the... Oh, well, it's not on. Okay. Okay, now I probably don't need to write, yeah. Okay, so I need to add a margin. I think there, and then this would be my main content. And I definitely don't need this anymore. Well. Okay, so. Let's make it. It's going to be. I think. Okay.

Victoria Lupia: That's better.

Lev Novikov: So then this is the schedule. A, B, C.

Victoria Lupia: Yeah, looks great.

Lev Novikov: And let's just try out putting lots more pictures. How's that?

Victoria Lupia: That looks great.

Thank you #

Lev Novikov: All right. All right, so we'll be open sourcing all this code and you'll see the links will all be in the show notes. Thank you to all of you who've been joining. Thank you, Victoria.

Victoria Lupia: Thank you. I can't wait to use it.

Lev Novikov: Excellent.

Victoria Lupia: You just gave me a whole bunch of time back.

Lev Novikov: I'm very glad to help. All right. Take care. Thank you.

Victoria Lupia: Bye bye.

Lev Novikov: Bye bye.