Showing posts with label HTML. Show all posts
Showing posts with label HTML. Show all posts

Thursday, November 9, 2017

Character Viewer: How To Save User Input - part 1 - Fun With Forms

    In our last tutorial we looked at how to write JavaScript data to an HTML table. This lets us populate a table dynamically instead of having to hand-code it. Except it doesn't really, after all we had to hand-code the objects we used to populate the table. So we need a truly dynamic way to fill our table, by letting the user create the data. So for this tutorial we're going to add to our app the ability to read and save user input. Let's take another quick look at what we've got...

    So this is still what we want it to look like at the end, a table with information about our Pathfinder characters. We're just going to add a few things.

Collecting User Input- Form Controls
    HTML has several elements that are designed to gather input, they're called form controls. A <form> tag defines a group of controls that are all going to be collected together. So we'll to start our section with that. We don't have to, but it's convenient. I'm going to add a border to the form and a margin to make it stand out, plus an <h3> header and some padding since the header looked a little funny. Here's what it looks like and my code...




    Okay, so now that I've set aside the space for my form I need to put in the controls to actually collect all the data. There are a lot of form controls and I'm going to try to use a variety of them for this project so you can get to know them all (kinda like Pokemon :). The most basic control is the textbox, a box that the user can type text into. It's built from a core element <input> and given the attribute type="text" and should work great for our character's name...



     The default textbox is about 15 characters long, we could change that with CSS, but I'm leaving it for now since it works for me. If you've ever looked at the code for a form (or if you do later) you'll notice that most form controls have a name="something" attribute. The name attribute is used when sending the form's data (called "submitting" the form). I'm not going to be sending this form anywhere, I'm going to collect the data with JavaScript, so I'm using the typical id="" attribute to track everything instead.
    So we have a field that the user can type in general text, numbers or letters. Let's look at another form control. For the character's race let's say we want them to choose from a limited list. This is a tutorial and not a working program so we'll try some different things out, even if they might not be ideal for the finished (or "production") app. Let's put in a drop-down list, this will let the user select an option from a list that we provide. This has the advantage that you can prevent the user from entering invalid data (since they're limited to the list) or from mis-typing/spelling the data. The downside is that you're limiting the user to the options you provide, so you need something that is complete and unchanging, like a list of the USA's state abbrevations. So this is not the ideal control for a character's race, since there are way too many Pathfinder races to list here, but like I said we're just doing it to play with the control.
    What we need is a <select> tag that's going to wrap a bunch of <option> tags. Each option is going to have a value="" attribute that's going to be the data we save (for JavaScript to read), and the text inside the option is going to be what the user sees. Since these are going to be the same thing, we want the user to see exactly what we're going to save, it's going to look a little funny but it makes it easier for Javascript to read later.
    I'm going to add options for only a few races, and here's what my finished control looks like...



    Okay, we've got the first two things down, lets go ahead and use another new control. A character can have more than one class, so let's use a set of checkboxes. The <input type="checkbox"> creates an element with a name and a box the user can click on. This lets the user choose multiple options. So I'm going to make a checkbox for some of the basic classes, but I want to show that they all go together, so I'm going to wrap them in a <fieldset>. This element is just going to draw a border around all the checkboxes, to show they're related...



Note that in my HTML code I have each checkbox on a separate line, but I didn't put in any <br> tags so they are displaying in the page as being on a single line. That's for my sake, it's easier for me to read my own code if I put each element on a separate line - and I mention it as a reminder that how your code looks and how it displays are two different things. Use whatever look is easiest for you. Speaking of looks, I'm not a fan of how crowded this table is getting. Each element seems to be smashed against the others. I want to add some spacing. I'm going to do that by adding a some CSS to the <form> element, a line-height: 200% will space things out a bit. I'm also making the fieldset a little shorter...



That's a bit better. Good enough for now at least.
    Let's keep adding stuff to our form. Next is the character's level. So far I used the textbox, which allows the user to type in anything, numbers or letters. But a character's level is only a number, so let's use a new control that will prevent the user from accidently putting any letters in there. This is a new -input type="number"- that was added in HTML 5, so older browsers might not be able to show it, but my up-to-date Chrome will do fine. It doesn't look like much at first...


But put the mouse over it and you'll see the little up and down arrows to change the number...



    So let's put a starting value in there. I'm going to add the value="1" attribute, and levels don't go below 1, so let's also add a min="1" attribute to keep it in the right range. Also, the box is pretty long, so in CSS I'm going to set it's width to just a few characters. Here's the final look and code...




    Wow, so we finally finished the first cell of our table :)  We've done pretty good at going through all the different form elements.  So I'm going to use those same number fields for all of the attributes.  Now, I'm going to have the user input the value of the attribute, not the modifier.  The modifier is a formula, so I can have JavaScript calculate it.  This will help me avoid any mistakes or funny math from the user.  This is a general practice when you're making forms, called "validation."  You want to make sure that you're getting the right data from your form.  So you start by limiting the potential mistakes as much as you can, and then you validate your data to make sure it's what you expect.  Users make mistakes, not because people are bad and lie (though some few do) but because people are people and they make mistakes.  So you want to structure your forms in a way that minimizes those mistakes and keeps an eye out for them.
   Another thing is that my form is looking a little thin.  So far it's just one row of inputs on the left of the screen.  That means there's a lot of wasted whitespace.  I'm not going to worry about this being seen on a mobile device or other small screen - that could be a tutorial of it's own.  So I'm also going to make 3 columns, by using <div>s and setting them to float in CSS.  So with the attribute inputs and column layout here's what the form will look like and it's code...




To make columns you can set a <div> to position: relative and float: left but those need to be inside a container with position: absolute which I set the <form> to.  Take that out the absolute container and you get a mess...



    The absolute element is like a fixed reference for the relative ones to move around. And float: left was described to me like a balloon: that element will float to the top of it's container and then drift to the left. It makes the div's align at the top and sit side-by-side. So I've got 3 columns of content in the form. I had to remove the width attribute I had added to the fieldset, now that I've got the columns I don't need to artificially shorten the fieldset.
    We're almost there. For the next two cells of our table, the weapons and armor, let's go ahead and use one other type of form control: the radio button. A radio button is like a checkbox, but it is round instead of square and the user can only select one option out of the group. It's an <input type="radio"> but each one in the set needs the same name="" attribute so the browser knows they all go together. Again this would not be a great choice for a production app, but we're learning and playing. So here are a few weapons as radio button options...



    I set the "none" radio button to be checked by default, so that something would be selected. Pretty easy. I also centered the attributes since I thought they looked better that way. Let's finish the form and add the last few controls. I'm putting in a number field for the base attack bonus, I'll have JavaScript add the Str or Dex mod depending on the weapon. Then another set of radio buttons for armor. Lastly another number field for hit points. And that will give us everything that goes into our table...



    Not bad, just a final finishing touch and we'll be done with our form. First, we need some way to add the character, so I'm going to add another <input> element with the type="button" that will be used to launch a JavaScript function to read the form and add it to the table. Another thing to consider though is if the user wants to clear the whole form, say they change their mind about what they put in? Well, in that case let's add a button to reset the form, of course it's <input type="reset">...



    And that makes our form. Go team us! ;) You can download the code from my Google Drive here and play with it yourself. Now that we've created a form all we need to do is make it work. That's going to take some JavaScript to read our form, format it, and then add it to the table - all of which we'll get into next week. Until then!


Thursday, September 14, 2017

The Open2 Engine - part 6 - Twine-like Text



    Now I'm going to pull together some of the things I've been talking about in my whirlwind series. And, if I can get it to work, I'm going to do so in this very post.

    So my first sample project is going to show and hide text like Twine does. There's a thing called Lorem ipsum, it's placeholder text, and I found some cool alternate ones on-line that I'm going to use to fill in my example passages below.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis tincidunt dapibus posuere. Nam dapibus, ante eget fermentum accumsan, ex orci facilisis purus, dignissim pretium nisi quam at erat. In faucibus purus sit amet sodales lobortis. Ut ullamcorper mollis dolor, non dictum justo venenatis ac. Nulla eu rhoncus neque, vel finibus urna. Integer vitae est tortor. Vivamus pellentesque vel diam volutpat mattis. Quisque aliquet turpis vel lectus blandit, ut elementum risus laoreet. Aliquam erat volutpat. Nulla facilisi. Praesent gravida tellus in ligula hendrerit feugiat. Fusce sodales porta nisi, eget vulputate enim. Aenean at rutrum tellus. Phasellus tincidunt lacus a augue suscipit, et pharetra eros suscipit. Integer nulla enim, porttitor in luctus sed, vestibulum quis lorem.
Next Passage
You're all clear, kid. Let's blow this thing and go home!Ye-ha! I can't get involved! I've got work to do! It's not that I like the Empire, I hate it, but there's nothing I can do about it right now. It's such a long way from here. The Force is strong with this one. I have you now.Don't be too proud of this technological terror you've constructed. The ability to destroy a planet is insignificant next to the power of the Force. Hey, Luke! May the Force be with you. Look, I can take you as far as Anchorhead. You can get a transport there to Mos Eisley or wherever you're going. I want to come with you to Alderaan. There's nothing for me here now. I want to learn the ways of the Force and be a Jedi, like my father before me.Leave that to me. Send a distress signal, and inform the Senate that all on board were killed. Escape is not his plan. I must face him, alone. I care. So, what do you think of her, Han? I care. So, what do you think of her, Han? Dantooine. They're on Dantooine. I find your lack of faith disturbing.
Next Passage
Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time! Shut up! Will you shut up?! Oh, ow! Well, how'd you become king, then? Camelot! Shut up! But you are dressed as one… Burn her anyway! I dunno. Must be a king. And the hat. She's a witch! A newt? Found them? In Mercia?! The coconut's tropical! You don't vote for kings. I have to push the pram a lot.
Next Passage
Smooth as an android's bottom, eh, Data? Mr. Crusher, ready a collision course with the Borg ship. You did exactly what you had to do. You considered all your options, you tried every alternative and then you made the hard choice. Our neural pathways have become accustomed to your sensory input patterns. You're going to be an interesting companion, Mr. Data. They were just sucked into space. A lot of things can change in twelve years, Admiral. That might've been one of the shortest assignments in the history of Starfleet. Wait a minute - you've been declared dead. You can't give orders around here. I think you've let your personal feelings cloud your judgement. Captain, why are we out here chasing comets? Some days you get the bear, and some days the bear gets you. Is it my imagination, or have tempers become a little frayed on the ship lately? Maybe we better talk out here; the observation lounge has turned into a swamp. Well, that's certainly good to know. When has justice ever been as simple as a rule book? Talk about going nowhere fast. Fate. It protects fools, little children, and ships named "Enterprise." I'll be sure to note that in my log. Yesterday I did not know how to eat gagh. I'll alert the crew. Why don't we just give everybody a promotion and call it a night - 'Commander'? Travel time to the nearest starbase? Computer, lights up! Mr. Worf, you sound like a man who's asking his friend if he can start dating his sister.
Next Passage
Th’art nesh thee nay lad soft lad wacken thi sen up t’foot o’ our stairs. Nay lad where’s tha bin. Th’art nesh thee a pint ‘o mild any rooad t’foot o’ our stairs. Where there’s muck there’s brass t’foot o’ our stairs ah’ll gi’ thee a thick ear. Ah’ll learn thi tintintin tell thi summat for nowt soft lad mardy bum. Chuffin’ nora ah’ll box thi ears soft lad ee by gum tell thi summat for nowt ah’ll gi’ thee a thick ear. Bobbar nay lad. Breadcake soft southern pansy wacken thi sen up. Be reet where’s tha bin mardy bum mardy bum. Tell thi summat for nowt where there’s muck there’s brass shu’ thi gob. Dahn t’coil oil. That’s champion ey up will ‘e ‘eckerslike shurrup by ‘eck. Eeh. Shu’ thi gob face like a slapped arse god’s own county soft lad th’art nesh thee tha daft apeth.

The End




    Let's look at the code that makes this work...
    First, we need to set up the page.  In this case I'm using a bunch of HTML <div> tags to separate each passage.  I need to be able to pick out each one to show or hide, so I'm giving each an ID attribute.  They are all going to have some light blue text, for this example, so I'm giving them a class of "example" - and they are all going to start hidden, except for the first one, so I'm giving them another class of "passage" - which looks like this...

<div class="example" id="1"></div>
<div class="example passage" id="2"></div>
<div class="example passage" id="3"></div>

    The CSS to make the text color and hide the passages looks like this...

.example {color: LightSteelBlue;}
.passage {display: none;}

    Now I need the links, the way to change the passages.  I'm using a plain anchor link, with a target of "#" as a placeholder, and I'm adding a special attribute.  HTML 5 let's you make up your own attributes starting with "data-".  I'm going to add a "data-goto" attribute to each link, and the attribute's value is going to be the ID of the passage to show.  Adding some placeholder text and the links makes my HTML look like this:

<div class="example" id="1">
    Sample Text
    <a href="#" data-goto="2">Next Passage</a>
</div>

<div class="example passage" id="2">
    Sample Text
    <a href="#" data-goto="2">Next Passage</a> </div>

<div class="example passage" id="3">
    Sample Text
    <a href="#" data-goto="2">Next Passage</a> </div>

    Now, I need to use some JavaScript to make the links show and hide the passages.
    I'm going to use jQuery to get the anchor links.  Thing is, what if I didn't know how many links there were going to be?  And what if I wanted some regular links and some links that changed passages?  What if I wanted to use buttons or images along with anchor links?  Well, then I should set my code to look for anything that had the "data-goto" attribute, whatever element that is, and ignoring all others...

$('[data-goto]')

Okay, that will add this to just the elements I want.  Now, I need to set a "click handler" - a function to run when the user clicks on the link/whatever...

.on('click', function (event) {

Now for the function itself.  I want to do two things, hide the current passage and show the next one.  Hiding the current passage is easy, I'm going to get the parent <div> of the link (that's the <div></div> that's around the link), I'll get that in two steps.  First I need to select the link that's been clicked on.  The event handler passed along the event itself as a parameter, that set something called "this".  "This" is a context, a reference to the calling object (it's really complicated, which is why I didn't mention it before - just roll with it).  By selecting "this" I can then use the jQuery method of .parent() to get a parent of the link, in this case the <div>.  Lastly I can use another method .hide() to hide that div.  Yeah, it's complicated to describe it, but it's actually pretty simple - and it's just one line of code...

    $(this).parent('div').hide();

With the current passage hidden, I just need to show the next one.  I'm going to have to select the next passage, which I'm doing by using the same number in the "data-goto" attribute of the link and the "id" attribute of the passage.  To select an ID with jQuery you add a hash, "#", so I'm going to make a string with the hash and number.  Then, I'll make the selection with that string and use the method .show() to show the new passage...

    let sGoto = "#" + $(this).attr('data-goto');
    $(sGoto).show();

Finally, I'm using return false to stop the default behavior of the anchor link.  I didn't do this in a separate page I created, but when I copied the code onto Blogger I had the links do weird things, so this just tells Blogger to ignore my special links...

return false;
});

And there you go, you now have a way to show and hide passages just like Twine!

    I did want to add another little project, a tiny Parser game, but my code is not liking me today - so that'll be an upcoming update :)


Monday, September 11, 2017

The Open2 Engine - part 3 - Whirlwind HTML

    Okay, with all sorts of resources at my disposal, it's time to start actually writing something.  The Open2 Engine is going to use HTML, CSS and JavaScript to create Interactive Narratives (like Twine) - and maybe even someday actual games (I have plans...).  Since this whole thing is going to be built on three major technologies, I was thinking it might be good to provide a crash-course in those technologies for you, gentle reader, in case you didn't know them very well.  If that is the case, welcome to the club because I don't know them very well either :)

    Okay, so what is HTML?  Well, Hyper-Text Markup Language is what the web is built with.  It's a plain text file, formatted a special way, that the web browser reads and translates into the page you see.  HTML is about structure, about describing text.  Then CSS gets added to control the presentation (how the text looks).  Then JavaScript gets added to make the text act and react to events.  It's kind of what's called the Model-View-Controller pattern.  Of course, the lines get a little blurry, all three touch on the other's responsibilities, but it's a useful starting point.  So, since I'm going to be covering just HTML, these examples are going to be ugly.  That's okay.  Tomorrow I'll add some CSS and make them pretty, then the day after I'll add some JavaScript to make them dynamic.
    Starting up NetBeans (my editor of choice) and using it's plugin with Chrome, let's look at a basic, starting file...


    Not much to look at.  The first thing to point out is that HTML uses "tags," pairs of <element> </element> to define what a section of code is.  The <html> tag is the whole document (which the <!DOCTYPE html> says is, well, html).  The <head> tag holds some general information for the page, which isn't displayed in the browser.  The <title> tag puts the name of the webpage at the top of the window, and the <meta> tags have some information about the page that other computers or the browser use.
    The real magic is everything in the <body> tag, which is the main body of the document that gets shown to the user.  A <div> is a division or a "block" of text.  Related to it is a <span> which is "in-line" or it marks a section of text inside another container.  Let me throw a bit of styling in here and show you...


    While I'm going to end up using a whole lot of <div>s and <spans>s, there are lots of other other block-level tags.
    Headings <h1> through <h6> denote a, well, heading, from largest <h1> to smallest <h6>...


    Typically, you'll have some paragraphs <p> after your headings...


    Plain text is boring, so let's add an image with the <img> tag...


The <img> tag bring us something else to note.  So far we'd been using the tags themselves, called "elements," but an element can also have "attributes" that have a ' name="value" ' format.  In this case, the <img> or image element has 2 attributes, "src" (or 'source') and "alt" (or 'alternate,' what to show if the image itself can't be shown).
    Two attributes we're going to use a lot are "Class" and "ID".  Adding one of these attributes (to any element) let's us pick them out specifically to add some kind of styling or events.  A quick example, I'm going to make 2 classes, 'yellow' and 'bold', plus one ID of 'redbox'...


    Wow, that didn't look like anything at all.  Of course not, just defining the classes and IDs doesn't do anything, we have to tie something else to those "selectors." Let's add a little CSS to make them pop...


   As you can see, you can add multiple classes to one element, and multiple elements can have the same class - but IDs must be unique, only 1 to the page.
    Besides just printing out text, we can format it into lists.  The <ul> tag creates an "unordered list" (of bullet points) while the <ol> tag creates an "ordered list" (which is numbered).  For both, each specific line of the list is created with a <li> tag...


    We can also make tables.  This gets a little complicated- we start with a <table> tag.  Under (or "nested in") that we put a <tr> for each table row and in each row we put either a <th> for the table header (which has it's own tag since often we'll mess around with the data in the table but leave the header alone) or a <td> for each table data (or "cell").  Here, take a look...


    And we can make forms, which allow us to get input from the user (like when they're making a character).  Again we'll start off with a <form> element to hold everything.  The individual parts are mostly <input> elements that have a special attribute "type" that says what kind of input they are...


<input type="text"> gives us a textbox, something fairly small for the user to type in.  <input type="radio"> gives a radio button, where only one of the group can be clicked on, while <input type="checkbox"> let's any number of boxes be checked.  <textarea> gives us an ever bigger, multi-line place to type things.

    Okay, so we've covered some basic ways we can layout the page.  I've added some styling to point out things above, but tomorrow we'll go into more depth with CSS and controlling how things look.
    This was meant to be a fast, whirlwind introduction, so of course there is a whole lot more to HTML than what I've shown here.  A great place to learn more is at w3schools.com.