I used
SCCS,
RCS,
CVS,
SVN,
and all these version control systems (VCS) were getting better and better over the years,
especially SVN was nearly perfect in the end.
Now a tool with the beautiful name
Git
has come into vogue, created in 2005 by Linus Torvalds.
End of 2018 it made up 61% of all VCS installations.
Some say this is a big step forward, some say it is two steps back.
Using Git definitely requires more time than the old VCS,
because it is much more complex.
It was made to provide access to the LINUX source code for thousands of developers,
not for small companies that have ten developers and never would open their source for public work.
Long-termed collaboration of many people also requires a strategy, something like
Vincent Driessen's Git-Flow,
because it is based on branches.
In this Blog I will list some basic command sequences that may be useful for all who need to use git.
For simulation of multiple user collaboration
I could not find a compound try-out site on the Internet, so you would have to (patiently) install a
git server
on your machine when you'd like to test this.
Basics
For all commands shown here (except clone) you need to stand in the root directory of your local git-project.
Participate in a Project
git clone projectUrl
Somewhere on the web-page of the git project of your choice you will find the projectUrl
you need to check-out (sorry, clone).
Commit to Remote
After cloning, your current branch is the master branch.
This is something like a holy grail, and most likely you won't be able to commit to it.
But assumed you can, do the following to save your changes to the project:
The commit command just saves into you local git store.
The -am option is an abbreviation for -a -m,
whereby the -a ("add") will cause all newly created files to be added
(staged), and
the -m ("message") is the opener for a comment text.
If you dropped the -a, you'd have to launch a
"git add ." before the commit, standing in the project's root directory.
What was commit in old VCS is now push.
The parameter origin is a git-convention designating the remote repository (URL) where the project came from.
The name of the branch that will be updated is master.
After this, your colleagues will be able to see your changes as soon as they update their project-clone (that is also on branch master).
Update from Remote
git fetch
This updates your local git (not your source code!) with knowledge about e.g. new branches on the repository.
This is not always needed, but sometimes you should do it.
git pull origin master
You "pull" changes from the remote project's master branch and merge them into your (possibly modified) sources.
Conflicts can occur.
→ Mind that it is very recommendable to update (sorry, pull) your sources before you commit (sorry, push) your changes!
What is a Pull Request?
As you mostly can not push to master branch, you ask someone having permission to do it.
Launch a browser and go to the web-page of the remote repository.
Choose your branch.
Find the button to open a pull request.
Fill out the form and submit.
Frequent Commands
git status # displays local changes
git branch # lists all branches known locally
git checkout branch-name# changes from current to named branch
git checkout -b new-branch-name# creates a new branch and makes it the current one
git merge branch-to-merge # merge another branch into current branch
# delete a branch from local and remote
git branch -d branch-name
git push origin --delete branch-name
git reset --hard HEAD # dismiss all local changes and commits and replace everything with remote sources, use any hash-id from 'git log' instead of HEAD
Two immortal branches exist: master and develop, from which master is the best, you can always branch and release from master, and develop is more advanced, but may be unstable, anyway it is the release-candidate
Two kinds of temporary mortal branches exist: feature-xxx, hotfix-xxx,
the first for long-lasting work, the second for small corrections
More and more from time to time created immortal branches will exist:
release-X.X.X.
During release, bugfixes are done directly on the release-X.X.X branch, without further branching.
Finally it is merged into master and develop.
Release-branches are immortal because they could be deployed at customers that don't want to upgrade, but are reporting bugs.
This is the flow for hotfixes:
branched from master
get merged into master via pull request (to enable quality assurance)
every fix increases the 3rd version number (semantic versioning)
must be merged into develop when pull request was accepted
in case a release is running, fixes also must be merged into the release branch
fix branches get deleted after all
And this is the flow for features and releases:
features are branched from develop
get merged back into develop
release is branched from develop when features need to be deployed
features not being in develop at that time won't be released
release gets fixed, without branching, until quality assurance agrees
fully tested release branch gets merged into master and develop
every feature release increases the 2nd version number (semantic versioning)
all released feature branches and their release branch get deleted after merge
In following, please replace branch-name with a human-readable identifier that designates the issue you are solving with this branch.
For collaborative work inside a protected domain, where everybody frequently updates and commits sources,
SVN would be the better system, because it is much simpler than git.
For development that is done across the world in long-lasting tasks, git would prevail.
So make you choice. There won't come anything any more after git.
I spent an afternoon staring at LINUX forums to get my scanner working.
There was a bug introduced in Ubuntu 18.04 that hit Canon scanners, mine is a CanoScan LIDE 200.
Symptom was that there was a
thick vertical bar
in the middle of the image, being black when scanning grey, else being randomly coloured.
It is a known bug, nevertheless a system-update did not fix it,
because the fix might open a bug for another type of scanner
(at least this is what I understood from the forums).
I use the graphical xsane scanner tool,
which is a frontend for the
sane-genesys
backend drivers. The bug was reported to be in the backend,
which is called "libsane1".
To fix it I followed the advices given on a
launchpad web page,
it was the entry of date
2018-12-01,
written by gary17, that helped.
But of course not without problems.
Commands to fix libsane1 on Ubuntu 18.04
Following were the commands I launched, in a terminal window, to get my scanner working.
sudo apt-get install dpkg-dev fakeroot
This installs two needed libraries, unless they are already installed.
They serve for compiling and building Debian packages (Ubuntu is a Debian derivate).
cd $HOME/programs/
mkdir sanebackend-1.0.27-fix
cd sanebackend-1.0.27-fix
apt-get source libsane1
We need to get the current source code of the genesys drivers,
here I create a directory where to put these sources, and change into it.
Then I download the sources by apt-get,
not as super-user because this is not needed to compile them,
and I don't want files in my user-directory that belong to root.
A decent developer already found the problem and published the solution.
So we just need to patch the source, here is the diff-text:
2075c2075,2079
< if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK && dev->model->cmd_set->rewind)
---
> if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK && dev->model->cmd_set->slow_back_home)
> {
> status = dev->model->cmd_set->slow_back_home (dev, dev->model->flags);
> }
> else if (dev->model->flags & GENESYS_FLAG_SHADING_REPARK && dev->model->cmd_set->rewind)
Save this into file genesys.c.diff, or store the contents of
this link into it.
This command fixes the source code using the diff-file. Now we need to build and install.
sudo apt-get build-dep libsane1
This prepares all system-dependencies for package libsane1 so that we can build it.
build-dep is an apt-get command just like install and remove.
cd sane-backends-1.0.27
./configure
dpkg-buildpackage -rfakeroot -uc -b
Here I change into the source-directory of libsane1 and "configure" it,
which is a platfom-preparation of the "build". Makefiles get generated. This takes a while.
The final dpkg-buildpackage command starts the compilation.
This again will take some time, and output a lot of compiler messages.
echo $?
This command outputs the exit-code of the latest command, in this case the compilation.
If it is NOT zero (0 is positive!), something went wrong.
I got 2 as exit code, and saw following error message:
This happened on generating "manpages", i.e. the UNIX documentation for the library.
As I did not know how I could bypass this, and the new driver was not built due to this failing sub-build,
I tried to find hints about this error message.
I found out that it originates from
TeX statements like the following:
\usepackage{times,mathptmx,courier}
And I found out that the times font is obsolete.
So a missing font for the documentation made the build of a scanner driver fail!
Was it called dependency-hell :-?
I searched where the font was used, and found it just once in file
doc/sane.tex in line 3:
So I searched for another font that I could apply there, and I found it on a
TeX forum.
I edited the doc/sane.tex file and replaced "times" by "helvet".
Then I ran again the compilation:
dpkg-buildpackage -rfakeroot -uc -b
Yes, it failed again. This time because of a missing m4/libtool.m4 file.
I tried to run ./configure again, but there was no such script any more.
Instead of starting all over I found a workaround by copying an existing libtool.m4:
The exit code 0 reports a successful build.
The resulting Debian-package was in ../libsane-dev_1.0.27-1~experimental3ubuntu2_amd64.deb.
I installed this package into the operating-system by following command:
cd ..
sudo dpkg -i libsane1_1.0.27-1~experimental3ubuntu2_amd64.deb
It finished successfully.
Now I started xsane and tried to scan a page, without rebooting the system:
No vertical bar showed any more!
To protect my fix against system-updates I launched this command:
sudo apt-mark hold libsane1
Response was: libsane1 set on hold.
Hope this will be respected by the Ubuntu updater!
Else I will have to come back here and do the same again,
until they find out how to fix this bug for all types of scanners.
Resume
Using an open-source operating system may cause lost afternoons :-)
But why did I "stare" at the LINUX forums?
Because these entries are missing quality, they ...
talk too much jargon, slang, lingo, gobbledygook
don't mention the risks, e.g. when downgrading a library
don't explain the command lines, and what they are for
don't tell the expected outcome, i.e. how to check whether a command worked or not
are incomplete sometimes
I spent 90% of that afternoon trying to understand instructions and considering risks,
only 10% with real editing work. So, does quality of communication count?
The HTML form element does nothing to arrange its subordinates in an appropriate layout.
We must do it ourselves.
Such layout expectations could be specified as:
Fields and Sets:
A form can contain a mix of fields and field-sets,
where a field-set is a titled vertically arranged group of fields.
Horizontal Layout:
Portrait-format (mobile): one-column table, label on top, input field below, both in same table-cell.
Exception checkbox: label right, box left.
Landscape-format (desktop): two columns, label in left column, input field in right.
Label is right aligned, so that it is near to the field it describes.
Exception checkbox: label right, box left.
Newspaper layout:
to exploit width, distribute fields across several horizontally ordered boxes.
Vertical Layout:
A left-side label should be on same height as its right-side input field, vertically aligned "middle".
In case the field or field-set is much higher than its left-side label,
the label should be aligned to the upper edge of the field or field-set.
Nested Layouts:
A field can be organized as several fields with its own layout, examples are
"Date of Birth" with "Age" output,
or "Year", "Month" and "Day" input fields in a row.
In this article I will introduce CSS implementing this.
I won't yet cover the checkbox case,
and also I won't think about "newspaper layout"
(distributing label/field pairs across several columns when having a restricted height).
You can visit the current state of this project on my
homepage.
Form Sample
Here is a HTML form example that contains all fields available from HTML-5 browsers,
so that we can examine whether the layout works for all types of fields.
This is also to try out the field-features your browser provides.
E.g. Firefox doesn't support datetime-local, week, month fields by now.
Chrome supports all, but paints box-shadow for radio-buttons badly, and the default shape of fields is ugly.
Use the ☞
button to toggle the layout from desktop ("left-label") to mobile ("top-label").
Use the ↔ button to stretch the form to full width.
Notice that required field labels are also bold for field-sets, in case the set contains at least one required field.
Example is the "More Text" group.
On the other hand there is no required field in the "Date / Time" group, thus its label is not bold.
Core Form Layout CSS
I will present this in small doses.
You can find the entire source code of the example on bottom of the article.
Most important to know is that I used line-height to get rid of vertical alignment problems
(still open problems!),
and box-sizing: border-box; to stop fields hanging out at right side.
About CSS coding:
I recommend to write comments on any CSS line, at least one per rule-set.
Only this keeps CSS code maintainable!
Remember that a rule like position: relative; can serve several purposes,
so we need to make explicit why we apply it.
Basic Label Styling
/* Smaller sans-serif font. */formlabel
{
font-size:76%;
font-family:sans-serif;
}
/* Add colon after any label. */formlabel::after
{
content:":";
}
/* But not on label after radio. */forminput[type='radio']+label::after
{
content:"";
}
The label should have a smaller font than the field.
This also will uncover vertical alignment problems in the layout.
Further this CSS sets a colon after the label,
and avoids it for radio buttons where the label is right of the button.
Labels of Required Fields
The JavaScript I introduced in my
recent Blog
copies the attribute required from field to label,
the CSS below relies on that.
/* Set asterisk before required fields. */formlabel[required]::before
{
content:"* ";
}
/* Make labels for required fields better visible. */formlabel[required]
{
font-weight:bold;
}
This is for setting an asterisk (*) before any label of a required field, and displaying it in a bold font.
DIV Table Layout
form.table
{
display: table;
width:100%; /* if parent is 100%, go with it */
}
form.table>div
{
display:table-row;
line-height:2em; /* needed for vertical line-alignment */
}
This defines the table-layout inside the form, not including the "Submit" and "Reset" buttons.
It will always fill its parent's width fully, so you should wrap it into either a
display: inline-block; (natural width) or a display: block; (full width) DIV container.
The table-row receives its line-height here, important to avoid vertical alignment problems.
The table-cell is not yet defined, it will be set specifically later for either mobile or desktop.
Layout of Fields Inside Tables
/* Stretch fields to full cell width, except checkboxes and radios. */form.table>div>input:not([type='radio']):not([type='checkbox']),form.table>div>textarea,form.table>div>select
{
width:100%;
}
/* Avoid text fields hanging out at right due to content-box sizing. */form.tableinput,form.tabletextarea,form.tableselect
{
box-sizing:border-box;
}
/* Let the user resize big fields vertically. */form.tableselect[multiple],form.tabletextarea
{
resize: vertical;
}
Fields should fill their cell's full width, not keep their "natural" width which is browser-specific.
Force the browser to calculate their border-box, not content-box, else they will hang out at right side.
Optionally we should allow the user to resize choosers that may contain lots of rows,
like <textarea> and <select multiple>.
Left Label for Desktop
form.left-label>div>label,form.left-label>div>input,form.left-label>div>select,form.left-label>div>textarea,form.left-label>div>div,form.left-label>div>fieldset
{
display:table-cell; /* display elements horizontally */vertical-align:middle; /* avoid vertical alignment problems */margin-top:0.2em; /* vertical line distance */margin-bottom:0.2em;
}
form.table.left-label>divlabel
{
text-align:right;
padding-right:0.2em; /* distance to right field */vertical-align:top; /* necessary for labels of nested fieldsets */
}
So here is a list of element names that can be inside a table-cell.
For a desktop-suited table with two columns, all these elements should behave as table-cell.
We allow beside input, select and textarea also fieldset and div elements.
Their vertical alignment should be "middle" by default.
To create a little space between layout rows there is margin at bottom.
Labels should be aligned right in left-label variant, to be as near as possible to the field,
but nevertheless keep a little padding-distance.
For labels we overwrite the default vertical alignment with "top" here, because
in case a whole fieldset (high) is on right side, we want the label to stay in a visible range.
Mind that there are no further rules for the top-label layout variant.
As any input field has been stretched to 100%, its preceding label will automatically go to top.
As a side-effect top-label will be the default, unless you put a
CSS class="left-label" onto the DIV table root-element.
Optional Additions
Following introduces useful code to style initial validation,
button bars and nested right-side containers (horizontal bars).
Visible Initial Validation
form:not(output):not(fieldset):invalid/* fieldset would also be red */
{
box-shadow:1px1px1pxred;
}
If you want to make the validation markers already visible on document-load, add this rule-set.
By default HTML forms would be validated by the browser only on a submit-event,
and only then you would see the browser-made validation markers and tips.
Buttons and Toolbar
forminput[type='submit'],forminput[type='reset']
{
margin-top:0.4em; /* space to form above */font-size:140%; /* using Unicode character as icon */width:33%; /* take a third of available space */
}
forminput[type='submit']
{
color:green;
}
forminput[type='reset']
{
color:red;
}
/* Variant label-top: put "Ok" to very right, "Cancel" will be at very left. */form:not(.left-label)+.button-containerinput[type='submit']
{
float:right;
}
/* Variant label-left: align "Cancel" and "Ok" to middle. */form.left-label+.button-container
{
text-align:center;
}
Try out of you like this appearance of buttons and their bar.
It is different for top-label and left-label variants.
Such things depend on ergonomics, current fashion, company-rules, and last not least customer wishes.
The "Submit" button right now establishes slowly, but still buttons top or bottom is undecided.
Horizontal Layout
.horizontal-bar/* flex-direction row */
{
display: flex !important; /* else overwritten by table-cell! */
align-items:center; /* do not stretch vertically */
}
.horizontal-bar-natural/* natural size */
{
flex: initial;
}
.horizontal-bar-stretch/* takes all available space */
{
flex:auto;
}
This is a general purpose layout done through
flexbox.
Look at the "Date" - "Years Since" fields above for an example.
It is a frequent case that you have several fields in a line, and one of them should take the most available space.
Put a CSS class="horizontal-bar" onto the container DIV,
and one of class="horizontal-bar-natural" (just once!)
or class="horizontal-bar-stretch" onto the elements in row.
General Purpose CSS
/* Enable a fluid responsive display of forms and fieldsets. */div.responsive
{
display:inline-block; /* take just the space needed */vertical-align:top; /* align to top if any peer DIV is present */
}
/* Keep label and radio-button always on same layout row. */.sameline
{
white-space:nowrap;
}
/** Round border for fieldset. */fieldset
{
border-radius:0.5em;
}
If you want DIV containers to arrange themselves responsively side-by-side,
you can set a CSS class="responsive" into it.
The CSS class="sameline" is necessary to tie radio buttons to their label
in a way that never the label is in a different layout row than the button. This could be quite misleading!
Look at this example:
The same when <span class="sameline"> was wrapped around label and input:
Entire Source Code
Press the arrow-button to see HTML and CSS source code of this example.
<!DOCTYPE HTML><html><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1"/><title>HTML Form Test</title><!-- Core form layout --><style>/** Style labels of fields. *//* Smaller sans-serif font. */formlabel
{
font-size:76%;
font-family:sans-serif;
}
/* Add colon after any label. */formlabel::after
{
content:":";
}
/* But not on label after radio. */forminput[type='radio']+label::after
{
content:"";
}
</style><style>/** Style labels of required fields. *//* Set asterisk before required fields. */formlabel[required]::before
{
content:"* ";
}
/* Make labels for required fields better visible. */formlabel[required]
{
font-weight:bold;
}
</style><style>/** DIV table layout. */form.table
{
display: table;
width:100%; /* if parent is 100%, go with it */
}
form.table>div
{
display:table-row;
line-height:2em; /* needed for vertical line-alignment */
}
</style><style>/** Layout fields inside tables. *//* Stretch fields to full cell width, except checkboxes and radios. */form.table>div>input:not([type='radio']):not([type='checkbox']),form.table>div>textarea,form.table>div>select
{
width:100%;
}
/* Avoid text fields hanging out at right due to content-box sizing. */form.tableinput,form.tabletextarea,form.tableselect
{
box-sizing:border-box;
}
/* Let the user resize big fields vertically. */form.tableselect[multiple],form.tabletextarea
{
resize: vertical;
}
</style><style>/** Layout for left-label variant */form.left-label>div>label,form.left-label>div>input,form.left-label>div>select,form.left-label>div>textarea,form.left-label>div>div,form.left-label>div>fieldset
{
display:table-cell; /* display elements horizontally */vertical-align:middle; /* avoid vertical alignment problems */margin-top:0.2em; margin-bottom:0.2em; /* vertical line distance */
}
form.table.left-label>divlabel
{
text-align:right;
padding-right:0.2em; /* distance to right field */vertical-align:top; /* necessary for labels of nested fieldsets */
}
</style><style>/* Layout for label-above variant. *//* * Because any input field has been stretched to 100%, the * preceding label will automatically go to top. Nothing to do! */</style><!-- Optional additions --><style>/** Make validation visible initially. */form:not(output):not(fieldset):invalid/* fieldset would also be red */
{
box-shadow:1px1px1pxred;
}
</style><style>/* Button and toolbar styles. */forminput[type='submit'],forminput[type='reset']
{
margin-top:0.4em; /* space to form above */font-size:140%; /* using Unicode character as icon */width:33%; /* take a third of available space */
}
forminput[type='submit']
{
color:green;
}
forminput[type='reset']
{
color:red;
}
/* Variant label-top: put "Ok" to very right, "Cancel" will be at very left. */form:not(.left-label)+.button-containerinput[type='submit']
{
float:right;
}
/* Variant label-left: align "Cancel" and "Ok" to middle. */form.left-label+.button-container
{
text-align:center;
}
</style><style>/** General purpose horizontal bar. */.horizontal-bar/* flex-direction row */
{
display: flex !important; /* else overwritten by table-cell! */
align-items:center; /* do not stretch vertically */
}
.horizontal-bar-natural/* natural size */
{
flex: initial;
}
.horizontal-bar-stretch/* takes all available space */
{
flex:auto;
}
</style><style>/** General purpose layout styles. *//* Enable a fluid responsive display of forms and fieldsets. */div.responsive
{
display:inline-block; /* take just the space needed */vertical-align:top; /* align to top if any peer DIV is present */
}
/* Keep label and radio-button always on same layout row. */.sameline
{
white-space:nowrap;
}
/** Round border for fieldset. */fieldset
{
border-radius:0.5em;
}
</style><!-- Script to copy required and ids --><script>/** * Avoid duplication of "required" and "id" attributes in HTML forms. * Any LABEL before an INPUT must get the INPUT's "id" value into its "for" attribute. * Any LABEL before an INPUT must copy the INPUT's "required" if it exists. * Sometimes the "required" attribute is not in the next element but in its sub-DOM. */function manageIdAndRequired()
{
var count =1; /* sequence number for unique ids *//** Searches for "required" in given element and all sub-elements. */function containsRequired(element) {
if (element.getAttribute("required") !==null)
returntrue;
var children = element.children;
for (var i =0; i < children.length; i++)
if (containsRequired(children[i]))
returntrue;
returnfalse;
}
/* end containsRequired() *//** Copies the optional "required" attribute to LABEL, chains it with INPUT's id. */function chainLabelToIdAndCopyRequired(label) {
var nextSibling = label.nextElementSibling;
var nextTagName = nextSibling ? nextSibling.tagName :undefined;
/* previous is just for radio-buttons */var previousSibling = label.previousElementSibling;
var previousTagName = previousSibling ? previousSibling.tagName :undefined;
var isRadioLabel = (previousTagName ==="INPUT");
if (isRadioLabel ||
nextTagName ==="INPUT"||
nextTagName ==="SELECT"||
nextTagName ==="TEXTAREA"||
nextTagName ==="DIV"||
nextTagName ==="FIELDSET")
{
if ( ! isRadioLabel && containsRequired(nextSibling))
label.setAttribute("required", ""); /* copy attribute to non-radios */if (label.getAttribute("for") ===null) { /* chain id */var sibling = isRadioLabel ? previousSibling : nextSibling;
var id = sibling.getAttribute("id");
if ( ! id && sibling.getAttribute("name")) { /* generate id from name */var identity ="_"+count;
count++;
id = sibling.getAttribute("name")+identity;
sibling.setAttribute("id", id);
}
if (id)
label.setAttribute("for", id);
}
}
}
/* end chainLabelToIdAndCopyRequired() *//* Iterate all forms on page */var forms =document.getElementsByTagName("form");
for (var f =0; f < forms.length; f++) {
var elementsInForm = forms[f].getElementsByTagName("*");
for (var i =0; i < elementsInForm.length; i++) {
var element = elementsInForm[i];
if (element.tagName ==="LABEL")
chainLabelToIdAndCopyRequired(element);
}
}
}
/* Execute function on page-load */window.addEventListener("load", manageIdAndRequired);
</script></head><body><form><divclass="responsive"><fieldset><legend>HTML Form Layout Example</legend><divclass="table"><!-- <div class="table left-label"> --><div><label>Single Line</label><inputname="single-line-text"type="text"requiredvalue="Default value in text-field"></div><div><label>Password</label><inputname="hidden-password"type="password"required></div><div><label>Number</label><inputname="numeric"type="number"required></div><div><label>More Text</label><fieldset><divclass="table left-label"><div><label>E-Mail</label><inputname="e-mail"type="email"requiredvalue="a@b.c"></div><div><label>Telephone</label><inputname="phone-number"type="tel"/></div><div><label>URL</label><inputname="url-address"type="url"value="protocol://host"></div><div><label>Auto-Suggest</label><inputlist="browsers"name="auto-suggest"/><datalistid="browsers"><optionvalue="Firefox"><optionvalue="Chrome"><optionvalue="Opera"><optionvalue="Safari"><optionvalue="Edge"></datalist></div><div><label>Search</label><inputname="search-pattern"type="search"></div><div><label>Multiple Lines</label><textareaname="multiline-text"required>Default
value
in
text
area</textarea></div></div><!-- end table --></fieldset><!-- end cell --></div><!-- end row --><div><label>Date</label><divclass="horizontal-bar"><script>function calculateYearsSince(date) {
var millis =Date.now() -newDate(date).getTime();
var years = millis /1000/60/60/24/365;
var age = (years >0) ?Math.floor(years) :Math.ceil(years);
document.getElementById("yearsSince").value = age;
}
</script><inputclass="horizontal-bar-stretch"name="day-only"type="date"requiredoninput="calculateYearsSince(this.value);"> <labelclass="horizontal-bar-natural"for="yearsSince">Years Since</label><outputname="yearsSince"id="yearsSince"></output></div></div><div><label>Date / Time</label><fieldset><divclass="table left-label"><div><label>Time</label><inputname="time-only"type="time"></div><div><label>Date / Time Local</label><inputname="date-and-time-local"type="datetime-local"></div><div><label>Month</label><inputname="month-only"type="month"></div><div><label>Week</label><inputname="week-only"type="week"></div></div><!-- end table --></fieldset><!-- end cell --></div><!-- end row --><div><label>Other Inputs</label><fieldset><divclass="table left-label"><div><label>Radiobuttons</label><div><!-- span.sameline: don't let the label and the button separate to different layout rows --><spanclass="sameline"><inputname="gender"type="radio"value="male"required><label>Male</label></span><spanclass="sameline"><inputname="gender"type="radio"value="female"required><label>Female</label></span><spanclass="sameline"><inputname="gender"type="radio"value="other"required><label>Other</label></span></div></div><div><label>More Radiobuttons</label><div><!-- div: display each radio-button on a new layout row --><div><inputname="RGB"type="radio"value="red"><label>Red</label></div><div><inputname="RGB"type="radio"value="green"><label>Green</label></div><div><inputname="RGB"type="radio"value="blue"><label>Blue</label></div></div></div><div><label>Single Select</label><selectname="single-select"required><optgrouplabel="Compiled"><optionvalue="java">Java</option><optionvalue="c++">C++</option></optgroup><optgrouplabel="Interpreted"><optionvalue="es6">EcmaScript</option><optionvalue="python">Python</option></optgroup></select></div><div><label>Multiple Select</label><selectname="multi-select"multiplerequired><optionvalue="one">Use</option><optionvalue="two">Shift</option><optionvalue="three">and</option><optionvalue="four">Control</option><optionvalue="five">Keys</option><optionvalue="six">with</option><optionvalue="seven">Mouse</option></select></div><div><label>Range</label><inputname="slider"type="range"></div><div><label>Color</label><inputname="colour"type="color"></div><div><label>File</label><inputname="file-upload"type="file"></div></div><!-- end table --></fieldset><!-- end cell --></div><!-- end row --><div><label>License Read</label><inputname="boolean"type="checkbox"required></div></div><!-- end table --><divclass="button-container"><inputtitle="Reset"type="reset"value="✘"><inputtitle="Submit"type="submit"value="✔"></div></fieldset><!-- end top fieldset --></div><!-- end div.responsive --></form></body></html>