Blog-Archiv

Samstag, 29. Dezember 2018

Labels and Required Fields in HTML Forms

This Blog is about writing HTML forms in an elegant way, concerning the label for a field, and the attribute "required". It is about structure and DRY source-code, not about layout.

Fields need labels to be understood. Fields are required (mandatory) sometimes, and should be identifiable as such right from start, not just after validation. The traditional way is to put an asterisk (star) on the label. Would be nice if labels of required fields also were bold. Further labels should be chained to their fields by id reference, this enables the user to focus the field by clicking onto the label.

Not Elegant Code

Here is a raw login-form, assuming "User" is required but "Password" is optional:

This looks ugly, but forget layout and styling for now. I want to think about the HTML structure of forms. Let's review the source-code of this "Login" form.

Here is CSS defining a basic table-layout, allowing table-cells being other than div elements:

    <style>
      .table
      {
        display: table;
      }
      
      .table > div
      {
        display: table-row;
      }
      
      .table > div > label,
      .table > div > input,
      .table > div > select,
      .table > div > textarea,
      .table > div > div,
      .table > div > fieldset
      {
        display: table-cell;
      }
    </style>

HTML, using label and input as table cells:

    <form>
      <div class="table">
        <div>
          <label for="username-id"><b>* User:</b></label>
          <input name="username" required id="username-id">
        </div>
        <div>
          <label for="password-id">Password:</label>
          <input name="password" id="password-id">
        </div>
      </div>
    
      <div>
        <input type="submit" value="Login">
      </div>
    
    </form>

Why is this HTML source not elegant?

First, the "User" field has been marked three times as required:

  1. through the required attribute (browser validation)
  2. through the * asterisk
  3. through the <b> bold markup

This would have to be repeated for all required fields. Can't we do better using CSS? I would suggest a ::before pseudo-element for the asterisk, and a rule for the bold markup. Also the trailing colon could be done by an ::after pseudo-element.

Second, I would like to avoid the handwritten id-chaining via <label for="username-id">. The label should be automatically chained to the field after it (or, in case of radio-buttons, before it).

Thus the table inside the form above should look like the following:

      <div class="table">
        <div>
          <label>User</label>
          <input name="username" required>
        </div>
        <div>
          <label>Password</label>
          <input name="password">
        </div>
      </div>
  1. Just set required once on input. The associated label should then know by CSS rules how to look like.

  2. Just use the elements without id. Let's generate an artificial id out of the name attribute and chain the label to the input that way automatically.

Why not enclose the field into label?

          <label>User
            <input name="username" required>
          </label>

I admit, the id-chaining would not be necessary then!

But: the field being a child element of the label would it make impossible to arrange them into a table layout. Further I plan to optionally move the label above the input via CSS, which is much easier when the label is not parent but sibling.

The Elegant Way

Not an easy way, beside CSS we will have to use JavaScript.

The basic problem here is that we can not write a CSS selector pointing to the label of a required field. Styles inside the rule-set will be applied to the last element in the selector. It is impossible to write a CSS selector that designates a <label> followed by an <input required>:

label + input[required]  {
  /* this selector would style the INPUT, not the LABEL! */
}

So, why not put the label behind the input-field? This leads to other problems that are not easy to solve either, the label structurally being right of the field. Moreover it would result in HTML that is not intuitive. So let's implement some CSS and a JavaScript that solves the problems.

CSS

      /* Set asterisk before required fields. */
      form label[required]::before
      {
        content: "* ";
      }
      
      /* Add colon after any label. */
      form label::after
      {
        content: ": ";
      }
      
      /* Make labels for required fields better visible. */
      form label[required]
      {
        font-weight: bold;
      }

This CSS puts the * (asterisk) before any label that holds an attribute required, and it puts a : (colon) behind. It displays the label text in a bold font.

Two of these CSS selectors are built on the fact that the label element itself holds the required, which is not true for our goal-HTML above! So the JavaScript needs to copy that attribute from the input (select, textarea) to the label to make this CSS work.

JS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
      /**
       * 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)
            return true; 
          
          var children = element.children;
          for (var i = 0; i < children.length; i++)
            if (containsRequired(children[i]))
              return true;
          
          return false;
        }
        /* 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);

This script installs a document-load listener that will execute the function manageIdAndRequired() when called. That means, this function will be executed just once when the document is ready.

The manageIdAndRequired() is a function that encapsulates two other internal functions. It loops over all forms and the elements contained in them, searching for label elements. When it found one, it calls chainLabelToIdAndCopyRequired() with the label as parameter.

The chainLabelToIdAndCopyRequired() function looks at the next sibling element. In case it's none of "INPUT", "SELECT", "TEXTAREA", "DIV" or "FIELDSET" it will do nothing (mind that tagName values are uppercase!). Else it will check whether the next sibling has an attribute required. When yes, it copies it to the label, this will make the CSS above work.

Next it will check whether there is an id in next sibling (previous sibling for radio buttons). When no, it uses the sibling's name to generate a unique id for it. That id is then also written to the label's for attribute.

The containsRequired() function is quite simple. It returns true in case the given element holds an attribute named required, else it searches in all child elements for that, recursively.

Mind that the chainLabelToIdAndCopyRequired() function strongly depends on the HTML structure. In case you have label and input separated by td or div elements, it won't work. You would have to introduce a findSibling() function then.

This script has been written to cope with much more than the fields used in the login-form above. It also can handle nested fieldset boxes and radio buttons inside div wrappers.

Here is how the HTML source looks after the script has run:

      <div class="table">
        <div>
          <label required="" for="username_1">User</label>
          <input name="username" required="" id="username_1">
        </div>
        <div>
          <label for="password_2">Password</label>
          <input name="password" id="password_2">
        </div>
      </div>

For each input, the required has been copied to the label when present, and an id has been generated and copied into the label. No need any more to write these things explicitly into the HTML source!

Resume

A simple HTML structure helps to keep CSS and JavaScript code simple. I prefer a DIV-table to a traditional TABLE, because it is more flexible. I want to use this flexibility in a following Blog where I will introduce a form layout proposal, using all native input fields that HTML-5 browsers provide.

Main subject are the labels again. They need to be sometimes above, sometimes left of the fields. We would like to decide this through a CSS class on the DIV-table. Or maybe let the user control it through a toggle button?




Donnerstag, 27. Dezember 2018

HTML Form Talks HTTP

HTML forms are not so much in use any more, outdated by AJAX-driven single page applications. Nevertheless they still work and are a simple way to get inputs from browser users.

Mind that using HTML-forms makes sense only when you have your own web application running inside some public HTTP server, so that you can implement the responses for the incoming requests. What I present here just uses public "echo" servers on the internet.

In subsequent articles I will propose an element-structure and CSS-layout for HTML forms. In this Blog I just want to outline their HTTP capacities.

Form Skeleton

Following is a minimal HTML form with just one text-field (text is the default INPUT type):

<form action="http://www.tipjar.com/cgi-bin/test" method="post">
    <input name="single-line-text">
    <input type="submit" value="Ok">
</form>

→ The action attribute determines to which URL the form data get sent.

→ The method attribute determines the HTTP command to use for the HTTP request. GET and POST would make sense. Both can send data (although the name "GET" would not let expect sending; we could understand it as "GET me the result of the search-pattern I sent").
The difference between GET and POST is that GET transmits the form field values in URL parameters, while POST puts them into the HTTP request body. Consequence is that GET requests are unprotected.

→ Any form field (like single-line-text) needs to have the name attribute, else it would be ignored on sending.

→ The submit button would actually send the form data after their validation succeeded. Validation refers to syntactical correctness, and to the optional required attribute of HTML elements.

Thus forms are about

  • Field value retrieval, elements are:
    • <INPUT type="....">
    • <SELECT>
    • <TEXTAREA>
  • Value validation
  • Packing into an HTTP request
  • HTTP response processing

Example Form

The example below contains some input-fields and two action buttons. The red "Reset" button would clear the form, the green "Submit" button would send it. Both go just to the form they are contained in, because there can be several forms on a page. By the way, any button inside the form would submit when clicked, except when it is of type="button" or type="reset".

Mind that required fields must have a non-empty value, the browser checks this before sending! In this form, all fields except the "Multiple Lines" textarea are required. The browser would most likely mark invalid fields red on submit.

HTML Example Form
Male Female Other

Before you click the green "Submit" button, choose which action-URL you want to send to, this will determine what you see in the "HTTP Response" area below:

http://jkorpela.fi/cgi-bin/echo.cgi http://www.tipjar.com/cgi-bin/test # (own page)
Thanks to http://jkorpela.fi/cgi-bin/echo.cgi for his gorgeous form echo!

The chosen HTTP method won't play a role now, because the server-response is redirected to the "HTTP Response" area below; just when you choose www.tipjar.com you may see a difference, because this page echoes very detailed.

POST GET

Fill all fields, then click the green "Submit" button. You should see the HTTP response in iframe below (where the form redirects to).

HTTP Response:

Source

This example form was done by following HTML source:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  <form method="post" action="http://jkorpela.fi/cgi-bin/echo.cgi" target="submit-result">

    <fieldset>
      <legend>HTML Example Form</legend>

      <div class="table">
        <div>
          <label>Single Line</label>
          <input name="single-line-text" id="text-id" required value="Default value in text-field">
        </div>
      
        <div>
          <label>Password</label>
          <input name="hidden-password" type="password" required>
        </div>
      
        <div>
          <label>Multiple Lines</label>
          <textarea name="multiline-text" required>Default
value
in
text
area</textarea>
        </div>
        
        <div>
          <label>Radiobuttons</label>
          <div class="radio-container"> 
            <input name="gender" type="radio" value="male" required>Male
            <input name="gender" type="radio" value="female" required>Female
            <input name="gender" type="radio" value="other" required>Other
          </div>
        </div>
        
        <div>
          <label>Multiple Select</label>
          <select name="multi-select" multiple required>
            <option value="one">Use</option>
            <option value="two">Shift</option>
            <option value="three">and</option>
            <option value="four">Control</option>
            <option value="five">Keys</option>
          </select>
        </div>
            
        <div>
          <label>License Read</label>
          <input name="boolean" type="checkbox" required>
        </div>
      
      </div>  <!-- end table -->
           
      <div class="buttonbar">
        <input type="reset" value="&#x2718;" class="reset-button">
        <input type="submit" value="&#x2714;" class="submit-button">
      </div>

    </fieldset>
  </form>

  <iframe name="submit-result"></iframe>

The form redirects the HTTP response, using the target attribute, into the iframe on bottom. Mind that this iframe was referenced by name, not by id. In case target is not present, the page itself would be replaced by the HTTP response.

Yes, the CSS layout is missing. Do not care, another Blog will explain this in more detail.

Example Response

If you enter the values shown in this screenshot (the password was "aaa"):

you should see following HTTP response:

single-line-textDefault value in text-field
hidden-passwordaaa
multiline-textDefault
value
in
text
area
genderother
multi-selectone
multi-selecttwo
booleanon

→ We can see that the name attribute of the field has been used as field identification, not the id.

→ The password arrived as clear text, thus any modern browser will warn you that the safe https protocol has not been used.

→ The newlines in the multiline-text were preserved correctly.

→ For the gender radio buttons, the value attribute of the INPUT field has been sent, not the visible label.

→ Two multi-select parameters (with same name!) arrived, representing all selected options in the "Multiple Select" field.

→ The boolean field delivered "on", not "true".


Resume

Thanks to web servers that echo form requests we can play with form fields here.

In a past Blog I introduced a way to quickly build a Java servlet via Maven. You could do that, start the servlet with mvn jetty:run, then put the http://localhost/your_serlvet_name URL into the action attribute of the form and see what happens on the server side.




Samstag, 22. Dezember 2018

Responsively Sizing Iframes

I discovered the techniques explained here on Ben Marshal's and John Surdakovski's pages on the web. It is about "responsive" iframe HTML elements, meaning that an embedded iframe should resize when the browser window gets resized.

WARNING: Studying this article on a mobile could lead to misunderstandings, because all example iframes may have the same size then, also you won't be able to resize the browser window.

Following shows how a video player embedded in an iframe looks when you don't assign pixel values to width and height attributes:

  <iframe
    src="https://www.youtube.com/embed/-p3h2Xcay_o"
    frameborder="0"
    allowfullscreen>
  </iframe>

Would be nice now if it filled the whole width, keeping its aspect ratio, and grew bigger when the browser window grows bigger.

But there is a problem with aspect ratio (= height / width). The iframe element can host a whole HTML page, and an HTML page has no height by default (although it is aware of width). That's the reason why you always find the hardcoded width and height attributes on iframes, they express the aspect ratio, but, as a side effect, they also fix its size: <iframe width="640" height="360" ...>. Thus an iframe having these attributes would not resize dynamically, and without them it has no aspect ratio.

Nevertheless the video player has an aspect ratio, only its wrapping iframe does not know about it, because it was made for HTML pages. Tricks like setting the CSS height: auto; and width: 100%; do not help, this looks like the following:

  <iframe
    style="width: 100%; height: auto;"
    src="https://www.youtube.com/embed/-p3h2Xcay_o"
    frameborder="0"
    allowfullscreen>
  </iframe>

You see that the height remained small, while stretching the width actually worked. Setting height to 100% won't help either, because this would work just when all parents' heights had been set to a defined value.

So we need a technique that gives us a rectangle which sizes dynamically. What people use is a parent block element that has a vertical padding percentage, and then putting the iframe onto that padding rectangle, stretching it to full-size. We need to study some basics to understand that.

On the CSS Box Model specification we find for padding-xxx:

Percentages: refer to logical width of containing block.
Logical width: refers to the physical width (horizontal dimension) in horizontal writing modes, and to the physical height (vertical dimension) in vertical writing modes.

Thus a percentage in some padding takes the dynamically calculated dimension as base. So what we need is a parent element with such a dynamic padding rectangle, and then place the iframe absolutely over it. Consider following CSS and HTML.

  .iframe-container
  {
    position: relative;
  }

  .youtube-aspect-ratio
  {
    /* The default YouTube aspect-ratio: height / width */
    padding-bottom: 56.25%;
  }

  .iframe-container iframe
  {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }

This CSS defines three rule-sets:

  1. Any element with class iframe-container will have position: relative; that is to be a parent for an absolutely positioned child element.

  2. Any element with class youtube-aspect-ratio will have padding-bottom: 56.25%; that means it takes 56.25% of the width of the element! This is the dynamic rectangle where the iframe can go to. It could also have been the padding-top.

  3. An iframe inside an element with class iframe-container will fill all available space given by the parent (width: 100%; height: 100%;) and be attached to top-left corner through position: absolute; and top and left set to zero. It will not be affected by the undefined height of its parent element, because absolutely positioned elements go out of the normal layout flow. The height of its parent will be zero when nothing is inside.
  <div class="iframe-container youtube-aspect-ratio">
    <iframe
      src="https://www.youtube.com/embed/-p3h2Xcay_o"
      frameborder="0"
      allowfullscreen>
    </iframe>
  </div>

This HTML wraps the iframe into a div element with class iframe-container, and it adopts the youtube-aspect-ratio of the video-player as the aspect ratio for the padding-bottom rectangle. Mind that there are no width and height HTML-attributes on the iframe, just the according CSS-properties were set to 100% through the rule-set above.

Here is the outcome:

That's it!
Resize the browser window to try it out. The video player should resize proportionally, keeping its aspect ratio.
You will want to create different aspect ratio CSS-classes for other links embedded in further iframes.




Sonntag, 9. Dezember 2018

Upgrade to Ubuntu 18.04 LINUX 4.15.0

Every two years a major version of the open-source operating-system Ubuntu LINUX gets released. This time it was 18.04, where 18 refers to 2018, and 04 to April.

If you are considering to upgrade your Ubuntu, this Blog may contain some useful informations for you. It can be done with the graphical "Software Updater" tool. They recommend to install all updates before upgrading.

Caveat

Applications that you installed using the "Software" tool of Ubuntu will be replaced by the newest version without confirmation. So you may lose beloved applications you wouldn't have liked to be upgraded.

I had an old version of the OpenShot video editor that was fast and simple, and I didn't like the newest one which is slow and complex. Moreover it is not fully backwards-compatible, e.g. the video titles' layout is broken.

There was no way back to the old version. The necessary Python libraries are not available any more, and even if they were, they might conflict with the new ones. I will keep on trying, but until now I could not install OpenShot 1.4.3.

Surprise

I am not sure if this was a positive or negative surprise:

The desktop environment is no more Unity. Consequences are as follows.

  1. Desktop icons are deprecated. Gnome decided so. Your old icons still will be there, but without image. If you double-click one, a dialog will ask you to trust it, and then it will work again, and also get back its image. But that is a workaround provided by Ubuntu!

  2. So where to put the quick-starters for our applications? Drag- and dropping a desktop icon into the left-side toolbar failed. Searching the web for adding application launchers to the toolbar failed.
    Update: it is possible! Copy the .desktop file from $HOME/Desktop to $HOME/.local/share/applications and its icon to $HOME/.local/share/icons, then open "Find Applications" (dash), search for it, and drag it into the left-side toolbar.

  3. The "X" button ("Close Window") in the title-bar of windows is on right side again. Yes you can (configure it). Or you sit head-shaking before your Gnome like me (was it left, was it right? :-)

  4. File-chooser "OK" button is in title-bar on top right side, "Cancel" on left, actually ergonomic. Here you have to shake your head vertically:-)

  5. The "Find Applications" button on left-side toolbar travelled from top (Unity) to bottom (Gnome). Another vertical head shake, but not a "Yes":-)

  6. The desktop-bar on top doesn't contain any more the full-screen window title-bar, like it was with Unity. Although confusing for beginners, this saved space on small laptop screens, and I appreciated it.

  7. You can't terminate the screen-saver by a simple mouse-click any more, you need to drag & drop from bottom to top now, like they do on mobiles, or you use the keyboard (ENTER, SPACE, this didn't change).

It seems to be possible to get back Unity, have a look at this page.

Shutter "Edit" Button Disabled?

The screenshot utility Shutter is quite popular, because it provides some basic markup drawing functionality on the screenshot, circles, arrows etc. But on 18.04 the "Edit" button is disabled. Here is a page that explains how you can get it back. You must install three additional libraries: libgoocanvas-common, libgoocanvas3, libgoo-canvas-perl, and then purge Shutter with sudo killall shutter.

Beeping Backspace

Sorry for this personal attitude, but I don't like beeping keyboards. Here is how to get rid of the sound that the BACKSPACE key makes in case it can't delete anything. Turn OFF the "Alert Volume" on tab "Sound Effects":

You find the "Settings" application in top-right system-menu, click the "tools" button.


"Suspend" Button Missing

There is no "Suspend" button any more in the system-menu. "Power Off" will shut down the computer completely. But hibernation is not related to the Gnome desktop. The web says, Ubuntu dropped hibernation in 2012. So why did the 16.04 "Suspend" then work?

A closer investigation showed that 18.04 supports hibernation via the computer's power-button (the physical ON/OFF switch). When you configure in "Settings" - "Power" the option "When the Power Button is pressed" to "Suspend", pressing the computer's power-button will hibernate it. Another press on the power-button will wake it up again.

Mind that holding down the button too long will turn off the computer the hard way, without shutdown!

Get Date in Top Bar

Launch following command in a terminal-window:

$ gsettings set org.gnome.desktop.interface clock-show-date true

Quickly Connecting to Remote File Systems

Here is the new way how to connect to your FTP server using Nautilus file browser. Click "Other Locations" on left side to see this "Connect to Server" input field:

It supports a lot of protocols like FTP, SFTP, NFS, SMB, DAV (HTTP).

New Progress Indication

Copying files in Nautilus file explorer shows a new kind of progress bar. You need to click onto the pie-chart button in top-toolbar to see it, see screenshot below. No other response shows up when starting to copy!



Resume

Lost a full day upgrading. Lost my old OpenShot.

But graphics of 18.04 is definitely better than 16.04. The desktop became simpler. The underlying LINUX is said to be much safer. So don't always insist on your old habits, move forward, it's not so bad!




Samstag, 8. Dezember 2018

Mount Disk on LINUX Startup

I removed 3 of 5 LINUX systems from my laptop hard-disk, using the graphical tool gparted (GNU partition editor). The resulting space I used to create a new hard-disk partition. As gparted did not let me define a mount-point for the new partition, I turned to the fstab file

$ sudo gedit /etc/fstab 

to add a mount line manually. But there I saw following line (for my MINT-partition):

UUID=e6606afe-96d5-4a4b-8f40-bdb5c2e98e51 /media/mint ext4  defaults 0 2

The partition is addressed using its UUID here, no more by device-name (like /dev/sda11). This is said to be safer. So I decided to do it that way - but, how to find out the UUID of the partition?

$ blkid
....
/dev/sda10: LABEL="Mint" UUID="e6606afe-96d5-4a4b-8f40-bdb5c2e98e51" TYPE="ext4" PARTUUID="bb049714-4b60-43b7-b8bd-997ebf94f085"
....

The blkid (block-identity) command helps out. But now I wondered how I can avoid all that investigations for LINUX commands, and do it with a graphical tool like a modern computer user would do! So instead of copy & pasting the UUID that blkid showed my into /etc/fstab, I started to search for a graphical fstab-editor. And here it is (at least for Gnome-systems):

$ sudo gnome-disk

This UI comes up, below it you see the output of the blkid command:

This shows both the device-name and the UUID of my new partition. Here is how to add it to /etc/fstab:

In the tools-menu, you find the item "Edit Mount Options", and there you can do it:

Here I have set the mount-directory to /media/space. Then I chose the UUID-identification from the drop-down below. Saved it, and it was in /etc/fstab! I created the mount-directory:

$ sudo mkdir /media/space
$ ls -l /media
drwxr-xr-x   2 root root 4096 Dez  8 21:24 space

Restarted the computer, and I had a big disk instead of the 3 redundant LINUX installations that I never used. And I learnt how to solve problems with graphical tools instead of mystic command line hacking. Keep yourself organized!