Sei sulla pagina 1di 148

_ 2

Table of Contents
Introduction
About

Foreword

Part I - Frontend
Programming?
Web Development?

HTML
Web pages - as we, users, see them

Web pages - as a browser sees them


Code Editors

HTML Attributes
Adding Unique Style (CSS)

Adding custom styles to html page


CSS Rules
CSS Selectors

CSS properties
More examples. Font properties

Specifying selectors. Search for nested elements


DRY Principle. Cascade principle of CSS
User Agent Stylesheet. Browser's Inspector

Styling list element


Border
_ 3

Margin, padding and CSS Box Model

Inspecting box model in the Inspector


Setting margin and padding

Grouping HTML elements with a "div" element


Separating "window" through background colors

Adjusing the box model's content dimensions

Aligning and centering elements

margin over margin-*

Working with shadows


Final code

HTML, CSS and Interactivity

Adding Functionality (JavaScript)


Preface

JavaScript code files


First JavaScript sub-program

Binding sub-programs to events


Binding JavaScript code to HTML code
Testing and fixing our implementation

Summary
Illiteracy elimination (JavaScript Terminology)

Preface
JavaScript Standards
Objects and their properties

Object methods
Calling a method

Passing arguments when calling methods with parameters


Method's return value
Named objects
_ 4

Everything is an object in JavaScript


The "window" root object

Creating object-functions

Naming objects
Event handlers

Understanding the code. Summary

Naming code for readability and remembering DRY principle

A few words about Readability and Obviousness


Variable definition

DOM

JavaScript statements and semicolons


Completing Implementation (JavaScript)

Reviewing last implementation


Pressed keys and their numeric codes

The "if" statement


The "and" logical operator ("&&")
Using variables for DRY and Readability

Planning real "adding task" implementation


Creating new elements

Changing new element text


Adding created element to the actual DOM
Clearing text field

Something special about the "value" property


Testing

Fixing the "extra spaces" handling


Final acceptance testing

Conclusion
_ 5

Intro to Software Development


Iakiv Kramarenko
This book is an early access to an "Intro to Software Development" course. It gives an
introduction to programming by examples in Web Development using HTML, CSS, and
JavaScript. The book should be on strength for all — from kids to their parents, with the
only prerequisite to be a confident computer user. It should help to taste the development of
a small but real product and determine your desired role in IT - developer, tester, or maybe
somebody else;)

Thе book is available for free download and for donation based sale at
http://leanpub.com/intro-to-software-development.

Cover photo by Rafael Zamora.

This version was published on 2018-08-07.

© 2016-2018 Iakiv Kramarenko


_ 6

Foreword
In 2015, I started to give paid offline and online IT courses (programming, test automation,
etc). I noticed a few things. Firstly, the majority of available courses on the market,
especially free ones, were too technical and complicated for students who start their way in
IT from the very beginning. Secondly, it was hard to decide which way to choose in IT -
management, business analysis, design, development, testing, etc. That was the time I started
to think on some course to give an introduction to the whole Software Development process,
be free, and be on strength for almost anybody - from kids to their parents without prior
deep knowledge in Information Technologies, with the only prerequisite - to be just a
confident computer user.

The idea was to create a course through each a student can build a real application from
scratch. Where each course lesson would represent one stage of the complete Software
Development process. As defined by en.wikipedia.org, Software Development —

is the process of conceiving, specifying, designing, programming, documenting,


testing, and bug fixing involved in creating and maintaining applications, frameworks,
or other software components.

I started to work on this course in 2016. The following lessons were thought to be included
in the course:

Process
Business Analysis
Design
Frontend Development
Backend Development
Test Automation
Testing
Deployment

A student was supposed to be introduced to each stage of the process by examples of


building a real web application from scratch - a tasks manager. Where each lesson shows
how to plan, analyze, design, develop and test basic features of the tasks manager, and then
_ 7

through available exercises per lesson, a student would practice in extending the
functionality of the tasks manager by his own, with the help of available tips and tricks,
frequent questions and answers.

With the time I understood that the scope of the work to be done is tremendous. Especially
taking into account my load on other projects. Till now I have written a draft of the
"Process" lesson and completed the Frontend lesson without exercises. Probably I will
publish the draft of the "Process" lesson as a blog post. And this book, at least in the
begininng, is supposed to be a home for the "more programming-like" materials of the
course in the book-like format (the contents can change):

Frontend Development (HTML, CSS, JavaSript)


Quality Assurance Practices. Automation
Deployment
Backend Development
Testing

The Frontend part is already available (without exercise). I plan to keep the book available
for free access and download at all times. But the progress of developing the next lessons,
and finally creating a complete course based on the book will depend on donations. The
more donations I collect, the less time I will have to spend on my other commercial projects,
and so have more time to work on this book and the course. Feel free to donate through the
book page at leanpub (http://leanpub.com/intro-to-software-development) or by sending
coins to my wallets:

Bitcoin - 1EyDGuW64YkJbZ8FW1yAkz6iLP8c6tCjn
_ 8

Bitcoin Cash - qqp2g49z0eskfv5kyv53q4rf2huz8lqssqe47ysmyr

Ether - 0x7f2cAa79D1f1966d3CDd8295f8aF6028D66de00e
_ 9

Programming?
"Programming" - a word we should all be familiar with. We all use home appliances, which
we program to perform needed actions in needed order. For example, we build a washing
program for washing machine: set timing, intensity, extra rinse, etc. Such different
configurations are the simplest forms of algorithms but we already can call ourselves -
"programmers". We even program our children, when educating them.

Computer programmers - do the same but on a much lower level.

Back to the washing machine. Who created that customizable washing profiles? That was
the programmers' job on the stage of building machine. For example, thanks to them we do
not think about how long it takes to heat the water. "Internal program" itself enable the
heater and turn it off when the specified temperature is reached. The program will also
change the water when needed, stop washing, and so on ...

So, in short, Programming - is the process of writing programs that describe predefined flow
of events in time and order of rules that must be satisfied to perform a specific task. The
final set of such "flows and rules" that defines a specific task or sub-task is also called an
algorithm.

And COMPUTER program can be defined as a collection of instructions or commands) for


a computer, that record algorithms with one of programming languages.

In our life we use different languages to communicate with citizens of different countries.
Also we use different language subsets like slangs to communicate on jurisprudence,
medicine or economics. We use different commands to home appliances, mobile devices,
etc. In the same way programmers use different programming languages and their
"additional subsets" - libraries - to communicate with a computer.

In modern computer programming, there are many areas defined by the type of programs:

Game Development
Mobile Application Development
Desktop Application Development
Development of "Embedded Systems" - remember the washing machine?;)
_ 10

Web Development
etc.

In the following chapters we are going to get familiar with programming on the the example
of "Web Development" ;)

Web Development?
Perhaps you know how to work with the standard program. Typically, you download it from
the Internet, install on your computer, open, and use it. What is a website? For us, it is
primárily a special program that does not require an installation. It's enough just to "open" it
in Browser by its "address", or in other words - "load" it in Browser. It can be opened
simultaneously by many users on different computers and browsers. For example, thousands
of people can use Facebook site simultaneously. It can give users the same or different
information depending on context, let users interact both with the program and with other
users which use the site. The website may consist of one or many "web pages", each of
which has its own "address". This program, that various users can "load" through Browser -
is called a web-client and, in fact, is only a "part" of a website. But there is the other part of
the "website" that we do not see, but that serves as the "brain" of the site that controls the
simultaneous operation of all user-downloaded web-clients, sends them by request the right
information, stores their data and lets them interact with each other. This "brain" is called a
web server.

This "intelligent" web site that consists of a client and a server - is called a "web
application".

Accordingly, there are two sub-areas in the development of web applications:

Frontend Web Development (of client)


Backend Web Development (of server)

Developers who do both (backend and frontend) are called "full stack" web developers.
However, due to the complexity of many of today's projects often backend and frontend
developers are two separate branches of specialists.
_ 11

Let's start with a simpler and "closer" to the end user part – Frontend. We will create a small
web-client through which a user can create tasks. Later we will develop a web-server in
order to implement functionality that does not belong to Frontend. Such as saving tasks
between web site reloads and the ability to see created tasks from different computers.

It should be also noticed that we will not touch all the nuances of web development in this
course. We will not always follow the accurate terminology and will not use all the most
recent innovations. But we will use something from the "new world" if this simplifies the
explanation. Our goal - is not to study all programming for a limited time but get familiar
with the process of web development, learn how to program something real, and realize in
practice - how interesting it may be.
_ 12

HTML
Web pages - as we, users, see them
At the beginning of developing our own web applications, we need to understand at a basic
level how "web pages" are implemented.

We are used to calling a "web page" everything that appears in Browser once a website is
loaded.

TodoMVC web application


_ 13

But for all these cute elements - edit fields, labels with text, buttons, checkboxes, links – we
have to thank browsers (Firefox, Chrome, Opera, Edge, Safari ...), which can represent the
inner implementation of pages in a clear to people form. In other words, browsers are
translators from "web application programming language" to "users language". Such
"translation" process may also be called "interpretation".

Web pages - as a browser sees them


And here is how a web page looks like for the browser:

Selecting "View page source" from the page context menu


_ 14

TodoMVC page source

This "abracadabra" is written in Hyper Text Markup Language also known as HTML.

The word "hyper" means that we deal not just with the "linear" text, but with the text that
may contain links (called "hyperlinks") to other resources. Links may direct us to the same
page or to other pages with other addresses as well.

In order to understand the secret of this language, let's take a look on a simple example.

Probably, you've already paid attention that the web page, we loaded earlier, was related to
tasks. It is the task manager that allows us to create tasks, edit or delete them, mark tasks as
"done", filter them or clear. In fact, we get a full application in the browser, not just a web
page with information without the possibility to dynamically change it here and now.

One of the main goals of this tutorial is to practice in creation of similar web applications by
yourself.
_ 15

And now we are going to start implementing our task manager main functionality - creating
new tasks by entering their text in a text field and after pressing Enter - display them in a list
below.

That's how a basic HTML code of our application might look like:

<html>
<head>
<title>Todos</title>
</head>
<body>
<input></input>
<ul>
<li>watch lesson</li>
<li>do homework</li>
</ul>
</body>
</html>

Look carefully at this structure. It is like a large cupboard that starts from <html> and ends
with </html> . As we see - identifiers of the beginning and the end of the "cupboard" - are
framed by special symbols - "less than" ( < ) and "greater than" ( > ). And in order to
distinguish the "end" from the "beginning" - the </ symbols are used instead of < in the
"end" case.

In the middle, "cupboard" has two main sections - head and body, which start with <head> ,
<body> and end with </head> , </body> correspondingly.

head - acts as an "ID card" of our web page. In the sense that identifies the page with a set of
information about it. It has currently only one "shelf" - the name of our web page -
<title>Todos</ title> .

Body stores the content of our website with all its elements-boxes.

Such elements-boxes can be nested.

In our case, list items

<li>watch lesson</li>
<li>do homework</li>
_ 16

that reflect tasks,

are nested in a single big box - <ul> ... </ul> - which displays a list of tasks.

By the way, ul is deciphered as "unordered list".

And li - as "list item"

As we can see, the "box" may contain only text - such as list item <li>watch lesson</li>

And may contain nothing, as the input field: <input> </input>

In such cases, when the box contain nothing, we can just write <input /> .

All these "boxes" are officially called elements. Beginning identifier is called an opening
tag (e.g. <li> ), and the ending identifier - closing tag (e.g. </li> )

As you can see, all that makes HTML – are rules of placing information about our website
in nested "boxes" in order to organise it and reflect the corresponding structure of a page.

Let's take a look how the web page with the code will look like in a browser. To do this, let's
keep this code in a file with the extension html: index.html and open it in the browser:
_ 17

Saving html example in common text editor

Opened html-file in the browser

That's it.

Perhaps you're thinking - why exactly "index"? Let it be one of your homework - reveal this
secret by yourself... Google will help you;)
_ 18

Code Editors
Before we continue, let's find out what is the code editor.

Any code is essentially a text that can be edited in a word processor. But the code has its
own specifics in comparison with ordinary text. And as text editors have additional features
such as tips on grammar, rulers, etc. - so editors specialized in editing code have its own
special features to help in work with the code.

Here is the code of index.html opened in one of such code editors - Atom:

index.html in the Atom editor

As you can see, reading of code is better because of the specific syntax highlighting. Now
eyes are not blurred due to "plain text" mixed with "tagged elements".

Another interesting thing about atom. There are many additional packages that can be
installed and that can make our life easier by extending basic functionality of the editor with
additional features. For example, it would be great to have a continuous "browser live view"
_ 19

of our code - the ability to enable browser emulator that reflect, in response to any change,
how our code will look in the browser. Do we have such package for Atom? Don't know,
let's search.

Cmd-shit-p for macs or ctrl-shift-p for windows will open the "Command Palette" dialog
where we can search for and trigger any Atom feature.

Command Palette
_ 20

Let's look for "install package".

Search for "install package"

Great, seems like "Settings View: Install Packages And Themes" is the place where we can
check available packages for Atom.
_ 21

Settings>Install

Now let’s go to "Search packages" and search for "browser live view".
_ 22

Search for "browser live view"

Oh! Second item in the list is "browser-plus". If we click on its name, we get its public page
with more details about the package:
_ 23

Browser-plus details

"Real Browser in ATOM"! And its first feature is "1. Live Preview". I think that it is what
we need. Let's install this package.
_ 24

Installing "browser-plus" package


_ 25

Installed "browser-plus" package

Now the "browser-plus" package is installed and we can toggle it using already known to us
"Command Palette" (pay attention that we can search the needed command just by first
letters of words from its name):
_ 26

Toggling "browser plus"

Toggled "browser plus"


_ 27

In order to enable the "live preview" feature, we need to press the corresponding "lightning"
button:

Toggling "live preview"

Now once saved any new change to the file (via cmd+s on the mac or ctrl+s on the
windows) the changes should be reflected in the browser emulator.

Let's, for example, add another task to the list. Here we can get familiar with one more
feature of Atom - autocomplete. Let's start adding new li element just by entering l and
i symbols (without tag symbols - < and > ):
_ 28

Trigger autocomplete hints

Now press Tab or Enter keyboard key to finalize "autocomplete":

Finalize autocomplete
_ 29

The editor will add opening tag's symbols ( < and > ) and also will add the closing tag
automatically.

Now, on added text to the new task and hitted cmd+s on the Mac or ctrl+s on the Windows
(saving changes) we will see them reflected in the browser emulator too:

Change before save


_ 30

Reflected change after save

Awesome! isn’t it? :)


_ 31

HTML Attributes
Specific HTML tags exist not for all known to us elements.

For example, most elements that involve "feedback from a user" - like entered text, selected
checkbox or radiobutton, pressed button - they all can be implemented through the element
with the tag input .

We have already used the input element previously to represent text field where user can
enter text for a new task.

<html>
<head>
<title>Todos</title>
</head>
<body>
<input />
<ul>
<li>watch lesson</li>
<li>do homework</li>
</ul>
</body>
</html>

Default input as edit field


_ 32

Just for example, let's now also add checkboxes for each task to give an ability to complete
them or mark as "done":

<html>
<head>
<title>Todos</title>
</head>
<body>
<input />
<ul>
<li><input />watch lesson</li>
<li><input />do homework</li>
</ul>
</body>
</html>

More `input` elements to complete tasks

But how do we indicate now that "input" elements for tasks should be checkboxes?

In such situations when we need to provide more information about an element, or in other
words - add some "identity" to our elements - then html attributes are used.

Attributes can be "general" that you can add to any element, and they can be "specific to
certain elements", i.e. it makes sense to add them only to elements of certain tags. The latter
regards, for example, the attribute type for the input element. In our case the type
attribute allows us to precisely identify our input element as exactly checkbox:

<html>
<head>
_ 33

<title>Todos</title>
</head>
<body>
<input />
<ul>
<li><input type="checkbox" />watch lesson</li>
<li><input type="checkbox" />do homework</li>
</ul>
</body>
</html>

inputs as checkboxes

For better structure of our html markup and to identify more accurately each piece of task
functionality - let's put our tasks' text into its own elements - labels:

<html>
<head>
<title>Todos</title>
</head>
<body>
<input/>
<ul>
<li>
<input type="checkbox" />
<label>watch lesson</label>
</li>
<li>
<input type="checkbox" />
<label>do homework</label>
</li>
_ 34

</ul>
</body>
</html>

Labels

Now functionality "to complete a task" and functionality "to display the task text" are
reflected in the markup by separate elements. In the future this will allow us to find the
"needed functionality" in the code more conveniently and accurately. It is the same idea as
to put things in order in the cupboard - each in its proper place.

Let's now get familiar with some other attributes of "functional" type, which add important
"features" to our elements.

How do you like the idea to add some text to the text field to serve as a hint for a user?

Here's how we can do this using the attribute value of the input element:

<html>
<head>
<title>Todos</title>
</head>
<body>
<input value="to do ... ?" />
<ul>
<li>
<input type="checkbox" />
<label>watch lesson</label>
</li>
<li>
_ 35

<input type="checkbox" />


<label>do homework</label>
</li>
</ul>
</body>
</html>

Input with value

An "inverse relationship" works as well - if we enter a text into an edit box in the browser,
then this text will be stored in the value attribute. Although, yet we do not know how to
test this. But we'll return to this later — when we will use this feature in order to "spy" the
value of value attribute of the text field after user pressed Enter , and then add a new
task with the spied text to the list ;)

But wait, have written some text in the text field, now we are forcing the users to remove it
each time before entering their own...

There is an easy way to fix this. It turns out that there is another attribute - placeholder -
which is used exactly as a "user tip" that does not obstruct entering a new text:

<html>
<head>
<title>Todos</title>
</head>
<body>
<input placeholder="what needs to be done?" />
<ul>
_ 36

<li>
<input type="checkbox" />
<label>watch lesson</label>
</li>
<li>
<input type="checkbox" />
<label>do homework</label>
</li>
</ul>
</body>
</html>

Input with placeholder

So, with help of attributes we can provide the Browser with additional information about
some element. Browser is able to interpret a specific set of attributes and their values and is
able to change how an element is displayed on the page correspondingly. For example, if the
input element has the attribute type="checkbox" , then the Browser will display it as the
checkbox. But not for all our wishes about style of element representation or some
behaviour connected to it the predefined attributes with predefined set of valid values exist.
For example, it would be useful сhange the style of the input element for the "entering
new task text", so it is displayed in the center of the page. Even more useful would be to
teach it to react to the pressing Enter key creating the new task with entered text earlier.
For that we will have to write an additional code in additional files using another
"languages". This code will find proper elements and change their style and behaviour. We
_ 37

will write this code later, and now let's think about the following. How such code can
quickly find the proper input element among other input elements? How to distinguish the
"text field" input element from the "checkbox" input element?

We could teach the program to seek "element input that is not a checkbox", but what if we
have another text field that displays the user's name who is assigned to this task?

<html>
<head>
<title>Todos</title>
</head>
<body>
<input placeholder="what needs to be done?" />
by
<input />
<ul>
<li>
<input type="checkbox" />
<label>watch lesson</label>
</li>
<li>
<input type="checkbox" />
<label>do homework</label>
</li>
</ul>
</body>
</html>

Two text inputs


_ 38

How to distinguish two text fields now? Not a bad idea would be to use search of the style -
"find the element input with attribute placeholder of the value What needs to be done".

But what if our webpage supports 10 languages? Won't it be hard to list all options?

"Find the element input with attribute placeholder of the value 'What needs to be
done?' or 'O que precisa ser feito?', or 'Що потрібно зробити?' or '需要做什麼呢'
or ... "

And we should notice that in the future our webpage can become more complicated and
probably more new input elements will be added. All this will more complicate finding
right element by our program "add a task by pressing Enter ".

To sum up - since we may have elements of the same type (i.e. with the same tag), but for
different purposes, we need a clear way of marking elements to distinguish them.

There are special attributes that exist specifically for such purpose:

Attribute id that is given to unique elements within a web page


Attribute class that is given to elements belonging to a certain group

Thanks to such attributes we are able to tie needed functionality to relevant elements within
the additional program, mentioned earlier.

So let's mark our input elements according to their roles:

<html>
<head>
<title>Todos</title>
</head>
<body>
<input id="new-todo" placeholder="what needs to be done?" />
by
<input id="assignee" />
<ul id="todo-list">
<li>
<input class="toggle" type="checkbox" />
<label>watch lesson</label>
</li>
<li>
_ 39

<input class="toggle" type="checkbox" />


<label>do homework</label>
</li>
</ul>
</body>
</html>

Now we always have a clear way to distinguish one text field from another. And even
collect a "sample" of checkboxes which are corresponded to class "toggle". This may be
useful to give them specific unique style.

Exactly with tuning our web-application style we will be busy in next chapter;)
_ 40

Adding unique style (CSS)


Adding custom styles to html page
HTML allows us to structure the content of the page - to mark up it's data reflecting their
hierarchical nested structure.

<html>
<head>
<title>Todos</title>
</head>
<body>
<input id="new-todo" placeholder="what needs to be done?" />
by
<input id="assignee" />
<ul id="todo-list">
<li>
<input class="toggle" type="checkbox" />
<label>watch lesson</label>
</li>
<li>
<input class="toggle" type="checkbox" />
<label>do homework</label>
</li>
</ul>
</body>
</html>

The browser is able to visually represent this "structured data" with "default styles".
_ 41

Browser renders default styles

Of course, it would be great to customize the style of visual representation of web pages data
to our taste.

This can be achieved using another web development tool - Cascading Style Sheets or
shortly CSS.

It is a special language that allows us to set css rules describing stylistic properties of the
elements.

Usually styles are described in separate files with extensions .css .

Before we write styles for our web application, let's simplify our HTML code... to the only
structure that is actually needed to implement functionality of "adding tasks", not more. This
will also make it easier to understand the overall process.

<html>
<head>
<title>Todos</title>
</head>
<body>
<input id="new-todo" placeholder="what needs to be done?" />
<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
</ul>
</body>
</html>
_ 42

Simplified code in browser

Now, within our project (we can toggle projects' tree view by "cmnd+\" for mac or "ctrl+\"
for windows) let's create a new file - style.css

Creating new file through context menu from project's tree view
_ 43

Setting new file name

New file created

For convenience let's close project's tree view (by "cmnd+\" for mac or "ctrl+\" for
windows) and move opened new file tab to a separate section within the code editor... by
"splitting the window down":
_ 44

closing the "duplicate":

and finally adjusting tabs-size accroding to our taste:

We have not written any "style rules" yet but let's just link our "css" file to html page, so our
editor built-in browser can "apply" them continuously while writing and saving new code.

"Linking" is implemented via adding a special "register entry"

<link rel="stylesheet" href="style.css" />


_ 45

in "our page passport" - the head section:

<html>
<head>
<title>Todos</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<input id="new-todo" placeholder="what needs to be done?" />
<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
</ul>
</body>
</html>

CSS Rules
Well, let's start “decorating” our website :)

Let's start from a text field, don't you think it's too short?

Let's "stretch" it to the entire width of the page.

First, we are going to construct a style rule in an ordinary English language:

The element with id="new-todo" should have a width of all available space

Or in more precise "technical" language:

The element with id="new-todo" must have the width of 100% of available space

And here is the translation to the "CSS language":

[id = "new-todo"] {
width: 100%;
}
_ 46

Input with default length

Input with css 100% width

As we can see, the translation is quite clear:

The element with id="new-todo" ...

[id = "new-todo"] {
width: 100%;
}
_ 47

... must have ...

[id = "new-todo"] {
width: 100%;
}

... the width of 100% of available space

[id = "new-todo"] {
width: 100%;
}

CSS Selectors
The rule begins with a selector that determines the selection of elements to which the rule
will be applied:

[id="new-todo"] {
width: 100%;
}

In this case - the elements that have attribute id="new-todo" (we have only one of such
kind - especially for that we used the attribute for the unique identification of an element -
id ).

Square brackets syntax ...

[id="new-todo"] {
width: 100%;
}

is a universal way of saying - "element or elements that have an attribute of the specific
value". For example, we could "find our element" also through selection by two attributes:

[id="new-todo"][placeholder="What needs to be done?"] {


width: 100%;
}
_ 48

Also, selector let us distinguish "search by attributes" from "search by element tag":

input[id="new-todo"][placeholder="What needs to be done?"] {


width: 100%;
}

Now our selector says:

"find the item(s) with tag input , with the attribute id="new-todo" , and attribute
placeholder="What needs to be done?"

In any case, because id is a special attribute that is unique for the element on the page -
we can limit the search to be based only on selector by id attribute:

[id="new-todo"] {
width: 100%;
}

Moreover, it turns out that people so often search elements by the id attribute, that in CSS
a shortcut exists:

instead of

[id="new-todo"] {
width: 100%;
}

we can write

#new-todo {
width: 100%;
}
_ 49

CSS properties
Let's continue analysing the syntax of CSS-rules...

The element with id="new-todo" must have the width of 100% of available space

#new-todo {
width: 100%;
}

After the selector - in the curved brackets - follows the block of rule definition:

#new-todo {
width: 100%;
}

that lists "stylistic" properties that should be "set" for found element or elements:

#new-todo {
width: 100%;
}

Properties in the list are defined according to the following syntax:

property's name

#new-todo {
width: 100%;
}

colon

#new-todo {
width: 100%;
}

value
_ 50

#new-todo {
width: 100%;
}

semicolon

#new-todo {
width: 100%;
}

More examples. Font properties


Let's add more properties to the list;)

Increase font size to 24 pixels:

#new-todo {
width: 100%;
font-size: 24px;
}

Make font italic:

#new-todo {
width: 100%;
font-size: 24px;
font-style: italic;
}
_ 51

And choose "Arial font-family" as one of the easiest and most comfortable for reading from
a screen:

#new-todo {
width: 100%;
font-size: 24px;
font-style: italic;
font-family: Arial;
}

Let's also perform some "code fu" on fonts of tasks - the li elements:

#new-todo {
width: 100%;
font-size: 24px;
font-style: italic;
font-family: Arial;
}

li {
font-size: 24px;
font-family: Arial;
_ 52

Specifying selectors. Search for nested elements


We used the simplest version of selector - searching for items by tag li :

li {
font-size: 24px;
font-family: Arial;
}

In the future our web page may become more complicated and more li elements may
appear on the page for different purposes. This may lead to that our selector stops to find
proper elements. So it's worthy to predict this and specify the search only to:

li elements ...

#todo-list li

... inside the element with id="todo-list"

#todo-list li

"Space" in CSS selectors means that we are looking:

for what is to the right of the space

#todo-list li
_ 53

inside of what is to the left of space

#todo-list li

DRY Principle. Cascade principle of CSS


Now let me introduce one fairly important principle in programming (and not only) - Don't
Repeat Yourself (DRY).

Let's pay attention to our code:

#new-todo {
width: 100%;
font-size: 24px;
font-style: italic;
font-family: Arial;
}

#todo-list li {
font-size: 24px;
font-family: Arial;
}

Properties: font-size , font-family and their values:

font-size: 24px;
font-family: Arial;

Are repeated in both rules:

#new-todo {
width: 100%;
font-size: 24px;
font-style: italic;
font-family: Arial;
}

#todo-list li {
_ 54

font-size: 24px;
font-family: Arial;
}

And likely, in the future with such habit we may duplicate other properties.

And now imagine that at some point we decided to replace the font size from 24 to 20
pixels.

We then will have to change it as many times as we duplicated the value. And the more
"times" we duplicated, the more likely we can make a mistake and forget to replace
everywhere. Hence, have the code with a defect and so working differently from our
expectations.

In such situations a preventive technique would be to make a definition in one place, and
elsewhere - reuse it.

We can describe the "common" font properties in one of the "ancestor" elements, such as
body, and then all nested elements - will use the same property values by default. However,
if we explicitly override these properties for nested elements with new values - then exactly
these new values will be used. It is called "overriding css properties".

Thus, the cascade principle is used. When we define only that styles for elements, that are
not defined for their ancestor elements. That's why stylesheets are called cascading.

Let's try to use this principle in our code:

body {
font-size: 24px;
font-family: Arial;
}

#new-todo {
width: 100%;
font-style: italic;
}

#todo-list li {
}
_ 55

Applying cascading principle to list items and input (didn't work for font-size in the input,
see next section for an answer)
_ 56

User Agent Stylesheet. Browser's Inspector


Oops, but "cascading" seems to not work for the text field style.

This is due to the following. We did not override the ancestor style. But browser did it.
Because it has its own default styles for specific elements, like edit field.

We can test this by using a special tool that is built into all browsers - the Inspector.

The Inspector can be found in browser's "Developer Tools":


_ 57

under "Elements" tab:


_ 58

Here we can "inspect" the element we are interested in - the text field:

Toggle inspection
_ 59

Inspecting element
_ 60

Once clicked on the element under inspection - the Inspector will show us then all current
element styles:
_ 61

It clearly shows that original text field styles:

including inherited styles from the body :


_ 62

were overriden by corresponding browser built-in styles:

These styles are marked as "user agent stylesheet" styles:

Therefore, for the #new-todo element we still have to specify needed font values
explicitly. But we still can follow the DRY principle and "don't repeat values". We are able
to tell explicitly that the values of these properties must still be taken from the ancestor
element ( body in our case):

body {
font-size: 24px;
font-family: Arial;
}
_ 63

#new-todo {
width: 100%;
font-style: italic;
font-size: inherit;
font-family: inherit;
}

#todo-list li {
}
_ 64

Styling list element


Now let's work on the style of our tasks representation. Add a bit of minimalism and
harmony;)

First, don't list item identifiers, those fatty blobs, look awkward?

let's remove them:

#todo-list {
list-style: none;
}
_ 65

Border
Let's also remove the frame around the input field:

#new-todo {
width: 100%;
border: none;
font-style: italic;
font-size: inherit;
font-family: inherit;
}

And to visually separate the tasks from each other and from the input field, let's add an
upper border to the li elements:

#todo-list li {
border-top: 1px dotted silver;
}
_ 66

The format of the "border-top" property value is quite obvious:

width

border-top: 1px dotted silver;

style

border-top: 1px dotted silver;

color

border-top: 1px dotted silver;


_ 67

Margin, padding and CSS Box Model


Now let's align elements a bit.

We have already faced the properties - border and border-top - responsible for
representing the borders around elements.

Except the border itself, there is an ability to customize the dimensions of space surrounding
the border - margin, and space between the border and element content - padding:

Box model

(image taken from commons.wikimedia.org)


_ 68

The collection of all these properties defines the so called CSS Box Model.

We can control either:

dimensions for all corresponding sides at once through properties:

margin
padding

or for each side separately:

margin-top, margin-right, margin-bottom, margin-left


padding-top, padding-right, padding-bottom, padding-left

Thanks to the selection of appropriate values of these properties, we can align markup of our
elements according to the already mentioned CSS Box Model.

Inspecting box model in the Inspector


Currently we see that the content of the "todo-list" element - is indented relatively to the
"input" element:

To be completely accurate, it has the following "indentations": margin-top, margin-bottom,


and padding-left - they are set in the default browser styles.
_ 69

We can see this in the Inspector:


_ 70

Just a hover on the ul element at the main inspector's area

will highlight all corresponding "spaces" around element on the page:

And after click on our ul element:

we will see the complete box model with all numbers for the clicked element, with same
colors used for corresponding "spaces":

Go ahead and hover corresponding areas at visualized box model, and it will highlight
corresponding areas on the rendered page too;)
_ 71
_ 72

Setting margin and padding


So, let's clear all these indentations

Inspected `ul` element


_ 73

in our custom css styles:

#todo-list {
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
list-style: none;
}

Cleared `ul` "surrounding spaces"


_ 74

In addition, for simplicity we can "miss" suffixes - "-top", "-bottom", "-left" - in our case the
effect will be the same:

#todo-list {
margin: 0;
padding: 0;
list-style: none;
}

Cleared `ul` "surrounding spaces" (concise version)


_ 75

Now let's set "internal indentation between the border and element" along the whole
perimeter to 15 pixels - for the input element:

#new-todo {
width: 100%;
border: none;
padding: 15px;
font-style: italic;
font-size: inherit;
font-family: inherit;
}

And the same for the "task" elements:

#todo-list li {
border-top: 1px dotted silver;
padding: 15px;
}
_ 76

Grouping HTML elements with a <div> element


Now let's move to the next level of our page design. To make it look more like a real
application in the browser, let's highlight our main elements by putting them into a separate
"window".

We will implement the window as a separate "container" element. The <div> tag is used in
HTML to group elements in such cases:

<html>
...
<body>
<div id="todo-app">
<input id="new-todo" placeholder="what needs to be done?" />
<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
</ul>
</div>
</body>
</html>

We "named" it through adding the id="todo-app" attribute. Hence it will be easier to "deal
with all elements inside container" when searching them by a unique selector #todo-app .
For example we can adjust the style of all "todo-app" elements by adjusting the css styles of
their parent element - #todo-app .

But so far nothing changed in the representation of our page layout:


_ 77

Separating "window" through background colors


Let's now separate our container from the "rest of the page" by setting the background color
of the body element to "light grey":

body {
font-size: 24px;
font-family: Arial;
background-color: lightgray;
}

And the background color of the #todo-app container - to white:

#todo-app {
background-color: white;
}
_ 78

Adjusing the box model's content dimensions


Also, let's limit the width of the container:

#todo-app {
background-color: white;
width: 500px;
}
_ 79

Aligning and centering elements


Set only the top margin:

#todo-app {
background-color: white;
width: 500px;
margin-top: 130px;
margin-bottom: 0;
}

and center the container horizontally through the "magic value" - auto - for the both
properties - margin-right and margin-left :

#todo-app {
background-color: white;
width: 500px;
_ 80

margin-top: 130px;
margin-right: auto;
margin-bottom: 0;
margin-left: auto;
}

Such "four-lines" code

margin-top: 130px;
margin-right: auto;
margin-bottom: 0;
margin-left: auto;

can be cut down to one line. For this let's list all relevant values for margin property in
clockwise order, starting with the margin-top value:

margin: 130px auto 0 auto;


_ 81

Working with shadows


Finally, lets make our application even more natural through adding a shade:

#todo-app {
background-color: white;
width: 500px;
margin: 130px auto 0 auto;
box-shadow: 0 25px 50px 0 darkgray;
}

Shadow is a rectangle that is drawn "behind an element" - with the size and coordinates
relative to the element.

Shadow settings are defined by the appropriate values of the box-shadow property:

box-shadow: 0 25px 50px 0 darkgray;


_ 82

The first value defines offset along horizontal axis X. Positive values shift to the right,
negative – to the left.
The second - the shift along the vertical axis Y. Positive values shift down and negative
- up.
Third - the shadow blur distance
Fourth - the relative size (Setting to Zero will make the size of the shadow same as the
element size; positive values will increase the size, negative - reduce)
Fifth - the color.
_ 83

Final code
So here it is, our final CSS styles:

body {
font-size: 24px;
font-family: Arial;
background-color: lightgray;
}

#todo-app {
background-color: white;
width: 500px;
margin: 130px auto 0 auto;
box-shadow: 0 25px 50px 0 darkgray;
}

#new-todo {
width: 100%;
border: none;
padding: 15px;
font-style: italic;
font-size: inherit;
font-family: inherit;
}

#todo-list {
margin: 0;
padding: 0;
list-style: none;
}

#todo-list li {
border-top: 1px dotted silver;
padding: 15px;
}

Hope, now all this code will not sound as complete magic for you ;)
_ 84

HTML, CSS and Interactivity


HTML and CSS let us create easy-to-understand web pages with a unique style. In real
projects webpage are built with HTML and CSS according to the layout designed by web
designers. This process is called "webpage markup".

Marked up web-pages are placed on the server. In the simplest case, when a user enters a
website address in a browser and presses Enter, web server receives request from the
browser and sends the content of this page back to the browser, which renders HTML and
CSS and displays the page to the user.

Such web pages are called static because they are just static documents stored on a server
and given "as is" to the client. In fact many sites are built with such static pages - like
landing pages or blogs.

They may look like real applications in a browser. But "to look like" is not "to be". Usually
the real application gives to a user more than just "information to read". It lets a user to
interact with it, "exchange information". By request from application a user may enter some
information about him or about things he is interested in - and application gives something
useful back.

HTML defines a mechanism that can give a certain level of interactivity - html forms. You
should be familiar with them. For example we often use html forms during registration on
many sites. However, html form only collects data from the user and for their processing -
sent them to a server. In such implementation of "interactivity" - interaction is delayed due
to transferring large amount of data between client and server. More over "the page" is
reloaded or you get completely other page loaded. This does not feel like "interactive
application". It looks more like "hanged and reopened application". All this does not give
the same effect as working with real mobile or desktop applications.

But the situation can be significantly improved by using a special language that is supported
by all browsers - JavaScript. It allows to add the true "fast and interactive functionality" to
web pages. Such pages change their content as a result of user interaction, without being
fully reloaded. That is why they are called "dynamic".
_ 85

Nowadays most serious programming work is related to building dynamic sites. And static
sites can be usually generated with special programs - static site generators. In this course
we are concentrating on building dynamic web applications as most powerful ones. So let's
continue our journey by learning JavaScript in next lessons;)
_ 86

Adding Functionality (JavaScript)


Preface
HTML code is not the only technology used to create real web applications. We do not just
see marked up elements on a page, we also interact with them. These "interactions" can be
implemented as "extra functionality" for html elements in the form of separate programs
written in the JavaScript programming language. This is possible because the Browser has
the built in JavaScript interpreter.

The Browser finds such programs and interprets them while downloading web pages. Such
programs usually consist of additional sub-programs that are planned to be "tied up" with
specific user's actions. The result of browser's interpretation - is exactly this "tying up". So
when a user performs an action, for example, clicks on any element, the browser launches
the appropriate sub-program, which, for instance, opens an additional dialog box, and so
on... In this way we make static web pages more dynamic.

It is time now to implement additional functionality in our webpage - "add new task to the
tasks list, with the text entered into the edit field, and submitted with Enter".

During previous lessons we have written the following code:

index.html:

<html>
<head>
<title>Todos</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="todo-app">
<input id="new-todo" placeholder="what needs to be done?" />
<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
</ul>
_ 87

</div>
</body>
</html>

style.css:

body {
font-size: 24px;
font-family: Arial;
background-color: lightgray;
}

#todo-app {
background-color: white;
width: 500px;
margin: 130px auto 0 auto;
box-shadow: 0 25px 50px 0 darkgray;
}

#new-todo {
width: 100%;
border: none;
padding: 15px;
font-style: italic;
font-size: inherit;
font-family: inherit;
}

#todo-list {
margin: 0;
padding: 0;
list-style: none;
}

#todo-list li {
border-top: 1px dotted silver;
padding: 15px;
}
_ 88

index.html in browser

Our elements, including <input id="new-todo" .../> , have already received their unique
identifiers and classes. This allows to easily find them and add to them a "new behavior".
_ 89

JavaScript code files


Here we go, let's create a new file in JavaScript programming language, which will contain
our "extra functionality" code. Let's do this in a bit different way, than previously, just to
learn more.

With a focus on bottom tab with opened style.css file

Focused style.css
_ 90

let's open the new file in the same bottom section by "cmnd+n" on Mac or "ctrl+n" on
Windows

and save it with name app.js by "cmnd+s" on Mac or "ctrl+s" on Windows:

Notice that all JavaScript code files should have the .js extension.
_ 91

Saved file

First JavaScript sub-program


Now let's create a small "sub-program" that will be responsible for the functionality of
adding task on pressing the Enter key.

Programming is like communicating with a computer using its language :) In this case, we
are communicating with the browser using the language it understands and knows "how to
interpret" - JavaScript. The process of our work is essentially confined to translating from
our native language into JavaScript language.

Imagine that we tell the browser:

let there be a sub-program 'add a todo on pressing Enter' that ...

Here's how it is translated into JavaScript:

let addTodoOnEnter = function() {...}

You can notice that the translation is quite clear, but the sentence is constructed in a slightly
different order:
_ 92

"let there be a sub-program 'add todo' that ..."

let addTodoOnEnter = function() {...}

It is not surprising that the sentence order is diferent :) After that story with the Tower of
Babel ...;)

Well, let's continue our dialogue with the browser:

let there be a sub-program 'add todo' that,


based on the event that occurred with an element, ...

let addTodo = function(event) { ... }

Are your eyes flickering? Don't worry, you'll get used to it :) In programming you may need
to keep even bigger data loads in your head simultaneously;)

In this case, under the "element" we may simply mean the text field.

And the event may mean a certain set of data that describes the event that happened to the
element (in our case - "pressing enter to submit text in the text field").

What if we dig deeper:

let there be a sub-program 'add todo' that,


based on the event that occurred with the element,
will display in a dialog box the value of this element of this event

Wait, which dialog box do you mean? - You might ask. - We planned to add the task to the
list! :)

No worries, let's not rush, "the sun will shine on our side of the fence too";). Meanwhile, to
make it easier for understanding, let's consider a simpler example first. Actually, you have
probably noticed yourself that the complexity increases. In real life programmers themselves
often simplify tasks first, in order to make sure that "it works" at least to some extent. Then
they make it more complex... This method of "decomposition into simpler tasks" is highly
effective not only in programming. Mind that;)
_ 93

So...

let there be a sub-program "Adding a task" that,


based on the event that occurred with the element,
will display in a dialog box the value of this element of this event

let addTodo = function(event) { alert(event.target.value) }

Now you really need to press "pause" and try to sort it all out in order to see the whole
picture.

Note, also, that we have described the code

event.target.value

quite stiffly and too technically:

the value of this element of this event

We have used such a style to make the translation easy to be traced. The following "human-
friendly" version would've been clearer in a normal context:

Text value of the element on which the relevant event has occurred

Now then, we haven't described any JavaScript programming language term yet. We haven't
explained what all those words and symbols technically mean. But, in fact, you may now
find analogies yourself and come up with your own terms, because their meaning is
described by a regular sentence in simple English:

let there be a sub-program 'add todo' that,


based on the event that occurred with the element,
will display in a dialog box the value of this element of this event

let addTodo = function(event) { alert(event.target.value) }


_ 94

If you currently have a more or less clear understanding of what this code means and you are
able to explain it without looking at the "English version" - then you have passed the first
test "to become a programmer." If the process of sorting out information, finding analogies,
building abstract code models of some real behaviors and processes gives you a pleasure"-
then programming may be the path for you ;) Or one of the pathways that you may use to go
into IT.
_ 95

Binding sub-programs to events


Now, let's continue using the same "analogy style" to make this code work :)

First line of js code

We already have the sub-program for "adding a task" - it's called addTodo

Now, let's...

"bind it to the event of pressing any keyboard key in the new task text field"

Why is it "any key" instead of "Enter"? - Just because we are "moving from simpler to more
complex";)

First, we should specify the original in order to make the translation more apparent:

let's bind the sub-program addTodo to the event of pressing any key
on the page's element with the id 'new-todo'

Here is the translation:


_ 96

let's bind the sub-program addTodo to the event of pressing any key
...

document.getElementById('new-todo').addEventListener('keydown', addTodo)

...
on the page's element with the id 'new-todo'

document.getElementById('new-todo').addEventListener('keydown', addTodo)

Here, an "event" means "an event that can happen". Recall that earlier let addTodo =
function(event) { alert(event.target.value) } — there under the event we meant "a
set of data that describes an event that has happened to a specific element."

Let's move on.

Now we have the “sub-program for adding a task” and the code of its binding to a page
element…

But how do we tell the browser that the code should be launched at the moment when the
page is loaded? For sure, we can't bind anything to the element before the page loads...

First, to somehow handle "this binding code" and tell the browser something about it - for
instance, "when this code has to be loaded", let's make it a "named sub-program" just as we
have done with addTodo :

let addTodo = function(event) { alert(event.target.value) }

let teachNewTodoFieldToAddTodos = function() { document.getElementById('new-


todo').addEventListener('keydown', addTodo) }

We may also divide this code into several lines for better readability:

let addTodo = function(event) {


alert(event.target.value)
_ 97

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keydown', addTodo)
}

Now, let's tell the browser to call the sub-program with the "code that binds the functionality
of adding a task" at the moment when the page has loaded...

I mean:

Bind the sub-program teachNewTodoFieldToAddTodos to the event of page content


loading

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

;-)

Binding JavaScript code to HTML code


A final touch is needed to "tie all of this together"... We constantly mention a "page," but
how does our JavaScript code

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keydown', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

know which page is meant by "document"?

To do this we need to bind the whole code app.js


_ 98

Full js code

to the page index.html via a special "registry" in "the html page passport" - the section
<head> ... </head> :

<html>
<head>
<title>Todos</title>
<link rel="stylesheet" href="style.css" />
<script src = "app.js"></script>
</head>
...
</html>
_ 99

Testing and fixing our implementation


Now we can test how our implementation works.

On pressed 'd' keyboard key we will get:

On clicked 'Ok' dialog button:

On pressed 'o' keyboard key:


_ 100

On clicked 'Ok' dialog button:

As you can see, there is one problem - the dialog box appears earlier than the letter which
key we have pressed. This is because JavaScript sees the keystroke event and appearance of
the letter in the text field in the following order:

keydown -> 'letter appears in the field' -> keyup

For us this means that if we want to "intercept" the entire text with the letter just entered -
we have to "bind" to 'keyup', meaning to "the event of the key release":

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

Now let's check out our "simplified implementation of task adding" again...
_ 101

On pressed 'd' keyboard key

On clicked 'Ok' dialog button

On pressed 'o' keyboard key

It works! :)
_ 102

Summary
Before taking a break, let's summarize the whole "work chain".

Initially, having a simple "non-interactive" text field:

<input id="new-todo" placeholder="what needs to be done?" />

We have created the sub-program

let addTodo = function(event) {


alert(event.target.value)
}

addTodo

let addTodo = function(event) {


alert(event.target.value)
}

with the code of "simplified task addding"

let addTodo = function(event) {


alert(event.target.value)
}

We have bound

document.getElementById('new-todo').addEventListener('keyup', addTodo)

this sub-program

document.getElementById('new-todo').addEventListener('keyup', addTodo)

to the event of the "entered letter appearance"

document.getElementById('new-todo').addEventListener('keyup', addTodo)
_ 103

...in the text field

document.getElementById('new-todo').addEventListener('keyup', addTodo)

And created an additional named sub-program with this code:

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

In order to be able to bind

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

it

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

to the completion of page content loading in the browser

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

and thus make our text field "interactive" by teaching it "simplified task adding".

The whole code we have written:

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

represents the program app.js


_ 104

<html>
<head>
<title>Todos</title>
<link rel="stylesheet" href="style.css" />
<script src = "app.js"></script>
</head>

that we have "bound" to our webpage through a special entry

<html>
<head>
<title>Todos</title>
<link rel="stylesheet" href="style.css" />
<script src = "app.js"></script>
</head>

in its "passport":

<html>
<head>
<title>Todos</title>
<link rel="stylesheet" href="style.css" />
<script src = "app.js"></script>
</head>

Now it's time to relax;)


_ 105

Illiteracy Elimination (JavaScript


Terminology)
Preface
In the previous lesson we got acquainted with JavaScript programming language and wrote
the following code using just "translation analogies":

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

that should add the task to the list with the text submitted to the text field by pressing Enter.
So far, the code doesn’t add a real task, but "emulates adding" through intercepting the text
entered and submitted by pressing Enter and then "displaying it in the dialog box" using a
"sub-program" alert .

Now, before we move further and provide a more realistic implementation, let's get familiar
with a formal terminology of JavaScript programming language. (Watch carefully for further
explanations, we will distinguish specific JavaScript terminology from simple analogies in a
special way - by highlighting terms in bold and putting "anologies" in double quotes)
_ 106

JavaScript standards
It should be noted that there are several JavaScript language standards, that exist for the
purpose of standardizing JavaScript interpreters implementation in different browsers. This
way all programs written in JavaScript can work the same in all browsers. Currently, the
most popular standard is already quite an "old" one - ECMAScript 5, which is fully
supported by all browsers. ECMAScript 6 is a new and modern standard, adopted in 2015.
And since 2015, each year the new version of standard has been released. Not all features
from these modern standards are supported by all commonn browsers (Edge, Firefox,
Chrome, Safari ), see compatibility table for more details. Though, the general trend among
frontend developers is to use the new versions of JavaScript as they brings many important
improvements into the language. In fact, some developers write their programs in
ECMAScript 6 or higher and then use special tools to translate the code into ECMAScript
version 5. Thus, they are able to use the features of a new modern standard and still get the
output code that works across all browsers.

The code we have written:

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

uses some syntax elements typical to Ecmascript 5 standard:

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}
_ 107

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

as well as innovations of the standard Ecmascript 6

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

In real life it's usually good to stick to one standard. We go this "mixed" way to get a more
clear and obvious code for the newcomers to the world of Programming. And in order to
simplify explanation of such a complex topic, we will no longer go into the nuances of
different standards. So far, it's enough for us that our code will work in the majority of
modern browsers.

Now let's continue analyzing more interesting things :)


_ 108

Objects and their properties


I think, no one will be surprised to find out that when people create the means for achieving
their goals, they try to make them "usual" and "natural", to repeat and reflect the principles
which they are used to in real life.

We live in the world filled with animate and inanimate beings that have their own specific
properties. Some properties are "passive" - they simply reflect a "characteristic of that
being", while others are "active" - they allow some beings to "act", thus affecting themselves
and their surroundings.

Many programming languages try to reflect this nature. And JavaScript is not exception. In
it, "beings with properties" are reflected as objects.

JavaScript objects help us to model the area that we want to "program".

Good examples of "our area objects" are:

Page
Element
Sub-program
Event (Event data)
Input text

Now, let's find these objects in our code.

Here...

document.getElementById

document is an object that represents a "page" of our "subject domain", and


getElementById is the object's property.

As we see, we are able to "access" the object's properties through a special dot syntax:

document.getElementById
_ 109

Object methods
The property getElementById reflects "the ability of the object-page document to find
the element by the value of its ID attribute". It is exactly that "active property", which we
have mentioned earlier. It provides to an object not just a "passive characteristic" but a
"behavior" and makes an object "alive" and able to "act".

These special "active properties" of objects are called object methods. In fact, they
represent additional "sub-programs" in the object's arsenal - an additional named code that
provides "special features" to objects. For example, the named property getElementById
implies a separate code-sub-program, that actually performs a "search for the element based
on its ID".

Calling a method
There is a special "parentheses" syntax in JavaScript used to make an object method perform
an appropriate action that it represents:

document.getElementById(...)

Now this code calls the method getElementById of the document object. Or, in other
words, it "executes the code that stays behind the property getElementById of the object
document ".

Passing arguments when calling methods with parameters


The getElementById method's unique feature is that in order to perform a relevant act of
the search, it requires us to specify the id - the value of the corresponding element’s
attribute:

document.getElementById('new-todo')

Such additional information needed by method to perform its action - is called a method
parameter. Some methods do not have parameters, while the others may have more than
one parameter - then when calling such method with values for corresponding parameters -
_ 110

they are separated with commas, for example:

addEventListener('keyup', addTodo)

A specific value passed at the time of the method call (for example, 'new-todo' ) is called
an argument.

Our argument 'new-todo' that represents a textual value of the id attribute, by which
the search will be performed - is also an object.

Single quotes around new-todo

document.getElementById('new-todo')

tell's JavaScript that this is exactly the "object representing textual value". If we missed the
quotes, then the JavaScript interpreter would have thought that we are trying to subtract the
object todo from new :) (actually, it would have thought of something more complicated,
but let's not dramatize even more for now).

Method's return value


In real life, all actions have their results. The same applies to our method getElementById ,
that will perform the search and then return the found element back to the place of calling
the method. This returned found element is also the object. You can imagine that instead of
this entry:

document.getElementById('new-todo')

you see, in fact, the following:

<element with id="new-todo"> .. </element>


_ 111

Named objects
Objects, as well as everything we are familiar with in the real world, may and may not have
names.

Among the objects we have mentioned recently, the unnamed ones are:

'new-todo'
<element with id="new-todo"> ... </element> that is returned by
document.getElementById('new-todo')

And the named objects are:

document
getElementById

Everything is an object in JavaScript


You may say: "Wait! but getElementById is a method of the object document !?"

That's true... But as everything is an "entity" in real life, in JavaScript - everything is an


object.

The document is an object, as well as all of its properties are objects, which have their own
properties, and they have their own ones... And so on down to the level needed to describe
our domain area;)

The window root object


By the way, the object document that represents the page – is also a property of the "root"
object - window , that represents the browser window;)

The same principle applies to the code:

alert(event.target.value)
_ 112

alert - (though it is not explicitly specified by the dot syntax) - is also a property of the
object window - namely - its method.

We could even write it "as it is":

window.document. ...
window.alert(...)

But it would not hurt to use a more "concise" version, which is available in JavaScript:

document. ...
alert(...)

Creating object-functions
Also, you can create objects on your own.

For example, you can create an "object-subprogram" using a keyword function

function(event) {
alert(event.target.value)
}

and the corresponding syntax that includes round

function(event) {
alert(event.target.value)
}

and curly brackets

function(event) {
alert(event.target.value)
}

Where the curly brackets contain written code


_ 113

function(event) {
alert(event.target.value)
}

that displays the "action" of our subprogram.

And round brackets contain the parameters:

function(event) {
alert(event.target.value)
}

required for the subprogram to perform its action:

function(event) {
alert(event.target.value)
}

This subprogram is called a function. Such functions are not quite the same as the methods,
which we discussed earlier. Formally, a method is "a function that belongs to an object".

And our function

function(event) {
alert(event.target.value)
}

belongs to no one yet ;)

The parameter of this function is special.

function(event) {
alert(event.target.value)
}

It should be an object

function(event) {
_ 114

alert(event.target.value)
}

that should have

function(event) {
alert(event.target.value)
}

the "target" property

function(event) {
alert(event.target.value)
}

that has the "value" property:

function(event) {
alert(event.target.value)
}

When someone calls our function with an argument that is going to be an object with such
properties - this argument will be used in the code of a method as a parameter named as
event .

Naming objects
In fact, the function parameters are named arguments

function(event) {
alert(event.target.value)
}

that we are going to pass into the method at the time of the call.

Here we had an introduction to one of the ways of "naming objects" - through passing the
objects via arguments when calling functions that expect corresponding parameters.
_ 115

This is not the only way.

Here we created an object-function:

function(event) {
alert(event.target.value)
}

But it has no name yet. And we will not be able to call it by its name elsewhere, where we
would need it, and do something interesting and useful ;-)

It is very easy to fix this using let syntax:

let addTodo = function(event) {


alert(event.target.value)
}

Now our created object-function has the name - addTodo .

And theoretically we can сall it through parentheses syntax:

addTodo(...)

But we will do what we earlier mentioned as "something interesting" ;-)

Event handlers
Recall, we do need this addTodo method to be called automatically on released Enter for
"intercepted value of the input field."

In our code:

let addTodo = function(event) {


alert(event.target.value)
}

the "input field" corresponds to the target property of event object


_ 116

let addTodo = function(event) {


alert(event.target.value)
}

Exactly this object-property target represents the element to which the event happened...

let addTodo = function(event) {


alert(event.target.value)
}

And the input field value corresponds to the value property:

let addTodo = function(event) {


alert(event.target.value)
}

And event in our code –

let addTodo = function(event) {


alert(event.target.value)
}

as we already know – is that object that describes a "real event" that happened with the
element. Heh) Well, not yet happened) But that's the whole point of programming that we
"program the future" and our function

let addTodo = function(event) {


alert(event.target.value)
}

plays a role of a "time machine" for us.

Such "functions-time-machines", designed for "interception" – "automatic calling" at the


time of the event occurrence – are called event handlers.

The moment of interception is defined through binding

document.getElementById('new-todo').addEventListener('keyup', addTodo)
_ 117

a handler

document.getElementById('new-todo').addEventListener('keyup', addTodo)

to a corresponding event

document.getElementById('new-todo').addEventListener('keyup', addTodo)

that can happen with a certain element

document.getElementById('new-todo').addEventListener('keyup', addTodo)

of a page

document.getElementById('new-todo').addEventListener('keyup', addTodo)

In our case, the event is "released keyboard keys" displayed in the code as the textual
identifier of such event:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

Understanding the code. Summary


The code ended up being quite long and complicated, but we should already understand it.
Again...

The document object has a property getElementById :

document.getElementById('new-todo').addEventListener('keyup', addTodo)

that is a method and represents an "element search action". And we execute this "search"
through the parentheses syntax:

document.getElementById('new-todo').addEventListener('keyup', addTodo)
_ 118

by passing corresponding argument:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

needed as a search parameter...

The result of the method execution is an object that represents a found element:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

This object has the addEventListener property:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

Which is a method and represents the action of binding an event handler function

document.getElementById('new-todo').addEventListener('keyup', addTodo)

to an event:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

We perform this "binding" action by calling the method with the corresponding arguments
through parentheses syntax:

document.getElementById('new-todo').addEventListener('keyup', addTodo)
_ 119

Naming code for readability and remembering DRY


principle
We could name the object for a found element:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

and it would definitely become more clear and readable for us:

let newTodo = document.getElementById('new-todo')


newTodo.addEventListener('keyup', addTodo)

But if we use newTodo only once (recall the DRY principle), in this case there is not much
sense to make two lines out of one, especially taking into account that at some point such
"long" code becomes a part of the "mother tongue" for a programmer ;)

document.getElementById('new-todo').addEventListener('keyup', addTodo)

A few words about Readability and Obviousness

You should be careful here and follow common sense. It often happens that a code of the
same length may be actually more complex or less obvious. Then it may be worthy to be
divided into "smaller" named pieces for easier understanding, even if this pieces will not be
repieted in the code further (that is the main signal for applying the DRY principle)

For example, although most of programmers consider the following code completely
obvious if you think on it a bit:

document.addEventListener('DOMContentLoaded', function() {
document.getElementById('new-todo').addEventListener('keyup', addTodo)
})

It is actually worth using a "broken" version for better clearness:

let teachNewTodoFieldToAddTodos = function() {


_ 120

document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

Variable definition
Now we have enough knowledge of terminology to "read" our code in JavaScript terms:

let addTodo = function(event) {


alert(event.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

Only a few nuances are left.

What we used to call "naming object", is also known in programming languages by a term -
variable definition:

let addTodo = function(data) {


alert(data.target.value)
}

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

And the symbol = represents the operation of assigning

let addTodo = function(event) {


alert(event.target.value)
_ 121

value (or object) that is located on the right:

let addTodo = function(event) {


alert(event.target.value)
}

to a variable that is on the left:

let addTodo = function(event) {


alert(event.target.value)
}

Also, an assignment can be used outside of variable definition. For example it is possible to
assign a value to already named object, like a property. We will see such examples later on.

DOM
You may as well have long been interested in the abbreviation DOM from the textual value
representing the event to which we bound the handler teachNewTodoFieldToAddTodos :

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

So, DOM stands for Document Object Model and represents what actually the document
object implements – an object that reflects the nested tree structure of page elements by
corresponding object properties.
_ 122

DOM model

(image "The Document Object Model used to access objects in web pages with eg.
javascript", taken from wikipedia, author: Birger Eriksson)
_ 123

JavaScript statements and semicolons


And one more finishing touch...

All we use punctuation (or at least try to:)) when writing real text. Something similar usually
exists in programming languages too. And JavaScript is not an exception. As we use dots to
terminate a sentence and separate it from other sentences, in JavaScript we use semicolons
to separate JavaScript statements.

JavaScript statements - are those "phrases" or in more technical language - "instructions"


that we told the browser to execute. Here they are in our code:

instruction to make an alert (show an "alert" dialog):

alert(event.target.value)

nested in other instruction that remembers it as named function addTodo (assignment


statement):

let addTodo = function(event) {


alert(event.target.value)
}

to be bound as event-listener to the corresponding event in the the insctruction of finding


#new-todo element and performing the binding:

document.getElementById('new-todo').addEventListener('keyup', addTodo)

and nested in the corresponding "assignment statement-instruction":

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo)
}

providing a final named function to be bound to DOMContentLoaded event in our last


instruction:
_ 124

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos)

But, as you see, we did not use semicolons previously, and it still worked. That's because the
JavaScript has so called ASI (Automatic Semicolon Insertion) feature, that smartly inserts
semicolons instead of us. Unfortunately ASI has some quirks, and better would be not count
on it. Still, some JS programmers does not insert semicolons manually counting on other
tools like "transpilers" to do that for them. Ususally just knowing some rules and using such
tools will be efficient enough comparing to counting only on ASI. But the "mainstream"
way in current JavaScript community is to insert semicolons manually, that's why we will
learn to do it too;)

let addTodo = function(event) {


alert(event.target.value);
};

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo);
};

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos);

Now we are ready to complete the implementation of our program. After a short break ;-)
_ 125

Completing Implementation (JavaScript)


Reviewing last implementation
After a brief review of JavaScript terminology, now we can continue implementation of
"adding task by pressing Enter ".

Currently we have the code that only "emulates" adding task:

let addTodo = function(event) {


alert(event.target.value);
};

let teachNewTodoFieldToAddTodos = function() {


document.getElementById('new-todo').addEventListener('keyup', addTodo);
};

document.addEventListener('DOMContentLoaded', teachNewTodoFieldToAddTodos);

In fact, it captures pressing of each letter and displays "the current text input field value" in
the dialog box.

Essentially the implementation of our "handler"

let addTodo = function(event) {


alert(event.target.value);
};

does not distinguish pressing between letters and the Enter keboard key.

So let's fix it and write the code that will still continue to "output the current text in the
dialog box" but only if you have pressed Enter .
_ 126

Pressed keys and their numeric codes


The first question - where can we take the information about which key was pressed?

It turns out that this information is available as the property of our event-object (the object
that describes the event that happened):

event.which

The value that is stored in this property is a numeric code of the key that was pressed or
released.

The Enter key corresponds to the numeric code - 13 .

The if statement
Now we only need to translate the following JavaScript "algorithmic phrase":

If the event was caused by pressing or releasing the key with the code 13, then display
the current value of the text field

Translation is quite clear:

let addTodo = function(event) {


if (event.which === 13) {
alert(event.target.value);
}
};

The bizarre character, that contains three "equals" signs

let addTodo = function(event) {


if (event.which === 13) {
alert(event.target.value);
}
};
_ 127

— is responsible for "comparison" of what is to the left from symbol with what is to the
right.

The whole construction, that begins from a keyword if :

let addTodo = function(event) {


if (event.which === 13) {
alert(event.target.value);
}
};

– is called the if conditional statement, and will execute the code inside the braces:

let addTodo = function(event) {


if (event.which === 13) {
alert(event.target.value);
}
};

only when the condition in parentheses is true:

let addTodo = function(event) {


if (event.which === 13) {
alert(event.target.value);
}
};

Let's check out how it works...


_ 128

After entering the first letter, we no longer see the alert dialog appeared:

and the same is true for all next symbols entered:

unless we press Enter

and see the dialog window with all previously entered text.

Perfect! :)
_ 129

The "and" logical operator ( && )


However, in real life it's more difficult :)

Let's press Enter when the field is still empty:

Not much informative, right? :)

And later we need to add task in the list instead of showing the intercepted text in the dialog
box. There is no sense to add "empty task", right? :)

Let's fix this through specifying our condition:

If the event was caused by releasing key with code 13

let addTodo = function(event) {


if (event.which === 13) {
alert(event.target.value);
}
};

and

let addTodo = function(event) {


if (event.which === 13 &&) {
alert(event.target.value);
}
};
_ 130

text in the input field

let addTodo = function(event) {


if (event.which === 13 && event.target.value) {
alert(event.target.value);
}
};

is not

let addTodo = function(event) {


if (event.which === 13 && event.target.value !==) {
alert(event.target.value);
}
};

empty

let addTodo = function(event) {


if (event.which === 13 && event.target.value !== '') {
alert(event.target.value);
}
};

then output the current text of input field

let addTodo = function(event) {


if (event.which === 13 && event.target.value !== '') {
alert(event.target.value);
}
};

The && operator we used in the code is an example of one of logical operators and is used
as "logical and" in JavaScription conditional expressions, as we have already seen in our
example.
_ 131

Let's finally ascertain that by pressing Enter on the blank input field, the dialog window is
not shown:

Using variables for DRY and Readability


Let's move on.

Pay attention that we have a duplication in our code:

let addTodo = function(event) {


if (event.which === 13 && event.target.value !== '') {
alert(event.target.value);
}
};

Recall the already known rule from previous lessons - the DRY (Don't Repat Yourself)
principle)

Duplicating the code complicates the support of such code in the future... If we want to
change something being duplicated, we have to change it in more than one place.

We can fix this problem very easily - we just need "to put" the event.target.value object
into a variable, hence naming this object and then, in the code, refer to the object through
simpler and more readable name:

let addTodo = function(event) {


let text = event.target.value;

if (event.which === 13 && text !== '') {


_ 132

alert(text);
}
};

Also it's worthy to name our numerical code 13 to make it more readable:

let enterCode = 13;

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


alert(text);
}
};

Remember these two important cases of using variables

For reusing duplicated code (to make it "DRY")


For naming the code to make it more readable

They will help you to write the code that is easier to use and maintain in the future.

Planning real "adding task" implementation


Now let's replace our "temporary" implementation based on the dialog window alert with an
implementation, that will really add a task to the list.

Let's recall, how looks the html code of our tasks list:

<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
</ul>

The ul element already has its personal "ID" for unique identification:

<ul id="todo-list">
<li>watch lesson</li>
_ 133

<li>do homework</li>
</ul>

so we are kind of already "prepared" to easyly find the element in our JavaScript code.

So now, we need to add a new element li at the end of our ul list:

<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
<li>{HERE}</li>
</ul>

And moreover - with the appropriate "intercepted text":

<input id="new-todo" placeholder="What needs to be done?" />


<ul id="todo-list">
<li>watch lesson</li>
<li>do homework</li>
<li>{With the text of the input field with id="new-todo"}</li>
</ul>

Well, go ahead! :)

Creating new elements


Firstly, we will

create a new element ...

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement(...);
}
};
_ 134

with tag <li>

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
}
};

Changing new element text


Now, let's...

"write into" it

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent =
}
};

or in more technical language...

assign

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent =
}
};

the input field text (that we "saved" in the text variable)


_ 135

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;
}
};

to the property textContent of the created element (that reflects actual element text
in DOM)

let addTodo = function(event) {


let text = event.target.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;
}
};

Adding created element to the actual DOM


Now,

once found the tasks list ul with id="todo-list"

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;

document.getElementById('todo-list')
}

let's

add at the end of the list ...


_ 136

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;

document.getElementById('todo-list').appendChild(...);
}

the earlier created element li

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;

document.getElementById('todo-list').appendChild(newli);
}

Clearing text field


Well, let's

clear the input field text

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;

document.getElementById('todo-list').appendChild(newli);
event.target.value = '';
}

So user doesn't need to do this manually by himself when creates other tasks after.
_ 137

Something special about the value property


Unfortunately, we can not write:

text = '';

Because the text is a "normal" variable. You can imagine it as a "box" in which we put
what is to the right of the = symbol in the assignment statement.

Before, we put into it the text, that we "pulled" from the input text field.

let addTodo = function(event) {


let text = event.target.value;
...
}

And when we put a new value into this "box-variable" text , we will not affect the real
attribute 'value' of the #new-todo element on the page.

But the value property of input field object that "lives" in the target property - is not
the "normal variable". It was created in the way that during operation of giving it a new
value it records it also in the value attribute of the real #new-todo element on the page.

For now, we should just remember this nuance about the "value" property, because
"understanding of how this not normal variables work and how to create them by yourself" -
is beyond of this demo lesson.

Though, we still can do the following "code-fu":

let addTodo = function(event) {


let inputField = event.target;
let text = inputField.value;

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;

document.getElementById('todo-list').appendChild(newli);
_ 138

inputField.value = '';
}
};

For reducing a bit of duplication and making the code, though slightly longer, but more
"readable".
_ 139

Testing
Let's finally test how it works:

Entered text

Pressed enter
_ 140

Looks not bad:) But let's turn a "tester mode" on and type a task text with spaces at the
beginning and at the end

and press Enter :


_ 141

Very interesting... They are not "seen" once task is added to the list - and that's good,
because these spaces are not important if we are talking about information about the task
that user has to do.

But let's go deeper and see what happens in the html code "dynamically created" by our
javascript code:

Inspected added task's li element

As we see the spaces were actually saved...

Just the Browser does not show them to us ... If we google it for a little bit, we will know
that by default the browser does not show "extra spaces". So we could leave it as it is, but
being "testers with a good imagination", we can foresee that, probably, when we are able to
edit tasks, for example through double-clicking on the task, we will start to edit the same
text with a lot of "extra spaces"... that is, in fact, quite not handy...

It would be nice if not only the browser hid 'extra spaces', but our web application "cleaned
the garbage" after inattentive user too :)
_ 142

Fixing the "extra spaces" handling


We can implement this very easy thanks to the special method trim of the text object that
"lives" in the value property:

let addTodo = function(event) {


let inputField = event.target;
let text = inputField.value.trim();

if (event.which === enterCode && text !== '') {


let newli = document.createElement('li');
newli.textContent = text;

document.getElementById('todo-list').appendChild(newli);
inputField.value = '';
}
};

Check it out:

New task with leading and trailing spaces to be added


_ 143

Added task's li element - inspected

Great, it works!

Now we can remove from the html code our temporary "stub" tasks:

<li>watch lesson</li>
<li>do homework</li>

Since now web application gives a user the ability to create his own tasks.
_ 144

Final acceptance testing


We can also open our web application in a real browser and check that everything works the
same.

Opened "index.html" in Browser (Chrome)

Clicked on input field


_ 145

Pressed space

Entered some text with more leading and trailing spaces

Pressed Enter
_ 146

Triggering inspector for the added task

Verifying that spaces were trimed


_ 147

Entering one more task

Submitted by Enter

Now our web page is up and running on the local machine - like a real application in the
browser.

Well done! :)
_ 148

Conclusion
So we have jumped into the process of the programmer's work and learned how to add
interactive features to "static web pages", turning them into full applications in the browser.
We have learned the so-called "Frontend" part of web application development.

Well, frontend - is not "full-stack" or, in other words, is not fully "completed" development
of web application. The feature of the web is that the user can work with web applications in
a browser on any device connected to the Internet, and even not one user, but hundreds and
thousands of users at the same time! So, let’s fix this in next lesson by developing a
"backend part" of our web application;-)

Potrebbero piacerti anche