Posts mit dem Label HTML/CSS werden angezeigt. Alle Posts anzeigen
Posts mit dem Label HTML/CSS werden angezeigt. Alle Posts anzeigen

6. August 2015

Minimalinvasiver Bootstrap Bestätigungsdialog (Confirm Modal Dialog)

Ab und zu braucht man bei Webanwendungen einen Bestätigungsdialog, bevor die Benutzerin eine Aktion auslöst, zum Beispiel "Do you really want to delete …"


Das geht mit Bootstrap sehr schlank und fast ohne Änderungen am Code. Kein Umstellen eines Links auf Button mit click-Aktion, kein Aufruf einer Javascript Dialog-Klasse, keine extra Funktionen als Callbacks, die auf Dialog-Button-OK oder –Abbrechen reagieren, sondern…

…etwas HTML (für den Dialog) und 2 Zeilen JavaScript zum Verdrahten.

Der Trick: Angenommen es gibt einen Link, dem der Confirm-Dialog vorgeschaltet werden soll. Das href-Attribut des Links wird zum "OK"-Button des Dialogs weitergereicht und der Link stattdessen zum Öffnen des Dialogs benutzt.

Ein Klick auf:

Delete

<a href="/Offer/Delete">Delete</a>

würde das Angebot (Offer) sofort löschen. Das soll durch einen Bestätigungsdialog abgesichert werden:

Dafür muss man 3 Dinge tun:

1. Dem Link sagen, dass er den Dialog aufrufen soll

<!—data-target und data-toggle aktivieren den Dialog beim Klick-->
<a href="/User/Delete" data-target="#ConfirmDialog" data-toggle="modal" id="DeleteButton">Delete</a>

2. Den Dialog definieren (irgendwo im Body)

<!-- Modal dialog -->
<div class="modal fade" id="DeleteDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">Echt jetzt?</h4>
            </div>
            <div class="modal-body">Willst du das Angebot wirklich löschen?</div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary btn-ok">OK</button>
                <button type="button" class="btn btn-default" data-dismiss="modal">Abbrechen</button>
            </div>
        </div>
    </div>
</div>

3. Alles verdrahten:

// Beim ursprünglichen Link:
$('#DeleteButton').each(function () { $(this)
  // Link als data-href sichern
  .data('href', $(this).attr('href'))
  // Link durch # entschärfen
  .attr('href', '#');
});
// Beim Öffnen des Dialogs:
$('#DeleteDialog').on('show.bs.modal', function (e) { $(this).find('.btn-ok')
    // …das gesicherte href-Attribut zum OK-Button weiterreichen 
  .attr('href', $(e.relatedTarget).data('href'))
    // Beim OK-Klick zum href navigieren
  .click(function () { location.href = $(this).attr('href'); });
});

Das sieht viel aus, aber in der Praxis schreibt sich das so:

$('#DeleteButton').each(function () { $(this) .data('href', $(this).attr('href')) .attr('href', '#'); });
$('#DeleteDialog').on('show.bs.modal', function (e) { $(this).find('.btn-ok') .attr('href', $(e.relatedTarget).data('href')) .click(function () { location.href = $(this).attr('href'); }); });

_happy_confirming()

PS: Nur eins der vielen kleinen Themen, die so ein Web-Projekt aufwirft: www.essenbeifreunden.com

7. Februar 2015

How to Make Your Site Responsive and Mobile Friendly in Minutes

Assumed you have a web site for years. It has a traditional layout with a header, a menu sidebar, and a content area. The menu sidebar and also the header do not fit very well on a smartphone screen.

We need a scrolling friendly vertical design. It should appear automatically whenever the screen width is the size of a smartphone. We need an overlay menu instead of the menu sidebar.

And we need it quickly without a complete redesign. 

This is what I just did for my old web site http://www.galactic-developments.de

(Because it went so smooth and easy, I'll report what I did. Maybe it helps someone. Paying back to the Web.)


Starting with a typical nice static, not responsive, not smartphone compatible design:




We will turn it into a responsive design with popup menu:




...in 10 minutes.

The Basic Principle:

HTML5/CSS3 offers a simple mechanism to switch designs based on device properties: media queries. A media query applies the enclosed CSS only if the query condition is met. 

I insert this into the HTML of the page template of my CMS (I could also add it to my CSS file):

@media screen and (max-width:700px) {
  // here will be CSS
}

Media Queries override general CSS-styles. Inside the curly braces I will now redefine some of the styles. By redefining I can make elements disappear, change sizes, and change the layout.

The above CSS means, that the styles will be applied to screens (not when printed) and which are smaller than 700 pixels.

Things to do:

1. Remove Header, Footer, and Frame

The frame in the background must disappear. The background consists of three <div>s with a background image each. Top and bottom <div>s also contain other graphics and buttons. They will all disappear. The center <div> also has my text and the menu. The center <div> will stay. But it will loose it's background. Luckily these three <div>s already have IDs. So I can add these lines inside the media query:

  #bgtop { display: none; }
  #bgcenter { background: none; }
  #bgbottom { display: none; }

... which makes my new media query CSS look like:

@media screen and (max-width:700px) {
  #bgtop { display: none; }
  #bgcenter { background: none; }
  #bgbottom { display: none; }
}

See, how the header and the vertical frame disappeared:


2. Menu

The menu should not be statically on the left side. It should be invisible at start and accessible from a menu button. If I press the menu button, then the menu should appear.

I decided, that the menu button should be in the top right corner of the screen and the menu will appear on the right side. Reason: the button in the top right corner will cover less of the text. There is free space at the top right while the top left always has text. I move the menu from the left side, which is also left of the text, to right side and above the text. My menu <div> has the ID "menu":

#menu {
  position:fixed; right:0px; top:0px; 
  background-color:#ffffff; padding:4px; 
}

The position will to be fixed even if the page is scrolled. There is a 4 pixel padding which is filled by a white background color for a small distance between the content below and the menu:


If you make the window wide, then it has still the original design.

3. Menu Button

This will be my menu button:


I insert the button <div> into the HTML (I put it just before the header <div>):

<div id="menubutton"></div>

Add CSS for the menu button:

#menubutton {
  display: block; position:fixed;
  right:4px; top:4px; width:24px; height: 24px;
  background:url(img/menubutton.png);
}

Shift the the menu down to make room for the menu button:

  #menu { margin-top:28px; }

Add a small JavaScript section to the HTML to toggle the visibility of the menu, when the menu button is pressed (jquery would be overkill, could use jquery for fade/slide animations, though):

<script>
 
document.getElementById('menubutton').onclick = function()
  {     
    var m = document.getElementById('menu'); 
    m.style.display = (m.style.display == 'block' ? 'none' : 'block');
  };
</script>

    When the page loads, then the menu should not be visible (it will be shown by the menu button):

      #menu { display: none; }


    4. Device Scaling:

    Pixel densities on mobile devices are usually higher than on desktop/laptop screens. And they differ. But all devices should show about the same amount of text. This means, that a scaling factor must be applied, which scales the page depending on the DPI of the device. The command for that comes as a meta tag. Add it to the HTML <head> section (of the web site template):

    <meta name="viewport" 
      content="width=device-width,initial-scale=1,user-scalable=no"
    />

    That's basically it:

    5. Additional Tweaks:

    Pixel densities on mobile devices are usually higher than on desktop/laptop screens. So I changed the baseline font size from 12px to 14px (this might be more effort depending on your existing CSS). In my case:

    * { font-size:14px; }

    On small smartphone screens, like old iPhones, the menu is too long. I remove some menu entries, which are not really important. I do this by assigning IDs to menu entries like. I changed:

    <li><a href="stuff.html">Wallpapers</a></a>

    to:

    <li id="menuWallpapers"><a href="stuff.html">Wallpapers</a></a>

    ...and add this to the CSS:

      #menuWallpapers { display: none; }

    As you see in the screen shot, my text is too wide. The reason is, that in my original design I assigned a fixed width to the content area, so that the text does not flow outside the border. Now, the text width should adjust to the device width. In my case, there are two <div>s to be fixed:

      #bgcenter, #main { width: auto; }

    I want to remove the page URL from the top. I don't think it's very useful, especially on a mobile screen. The page URL is only on the start page. It is a page content, not in the template of all pages. Still, I can hide it with a CSS in the same place as the other CSS tweaks.

    In other words: a style which is only used by a single page is configured globally by the media query CSS section. No problem. Since the link is inside a <div class="link">:

      .link { display: none; }


    A small shadow for the menu is no mistake:

      #menu {
        -webkit-box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 1);
        -moz-box-shadow:    0px 0px 8px 0px rgba(0, 0, 0, 1);
        box-shadow:         0px 0px 8px 0px rgba(0, 0, 0, 1);

      }

    Result:




    Summary:

    The complete CSS:

    @media screen and (max-width:700px) {
      #bgtop { display: none; }
      #bgcenter { background:none; }
      #bgbottom { display: none; }
      #menu { margin-left: 0px; }
      #menu { 
        position:fixed; right:0px; top:0px; 
        background-color:#ffffff; padding:4px; 
      }
      #menubutton {
        display: block; position:fixed;
        right:4px; top:4px; width:24px; height: 24px;
        background:url(img/menubutton.png);
      }
      #menu { margin-top:28px; }
      #menu { display: none; }
      * { font-size:14px; }
      #menuWallpapers { display: none; }
      #bgcenter, #main { width: auto; }
      .link { display: none; }
      #menu {
        -webkit-box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 1);
        -moz-box-shadow:    0px 0px 8px 0px rgba(0, 0, 0, 1);
        box-shadow:         0px 0px 8px 0px rgba(0, 0, 0, 1);

      }
    }

    A bit HTML and JavaScript for the menu button:

    <div id="menubutton"></div><script>
      document.getElementById('menubutton').onclick = function()
      {     
        var m = document.getElementById('menu'); 
        m.style.display = (m.style.display == 'block' ? 'none' : 'block');
      };
    </script>
    A meta tag in the HTML <head>:

    <meta name="viewport" 
      content="width=device-width,initial-scale=1,user-scalable=no"
    />

    _happy_scaling();

    Of course, there are other ways to make a responsive web site. You could use a mobile friendly CSS package, like bootstrap. But that probably means, that you will redesign your site, which won't be done in an hour.

    Of course, there are more modern ways to program the menu button. You could use jquery and this JavaScript:

      $('#menubutton').click(function() { $('#menu').fadeToggle(); });

    But you have to include 100 kB jquery library:

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

    17. August 2009

    HTML Video Tag

    They did it again. 15 years after the img-tag, they invented a video-tag. I know, that native video makes the world better. I am totally pro-video. But to call the tag "video" is just plain wrong.

    In HTTP, the server tells the content type of data. The client has no say. But if you call a tag "img" (or "video") then the browser expects a certain (subset) of content types. Ever tried to return an HTML from the URL of an img-tag: broken image. Even though it was valid HTML. Why doesn't the browser show an embedded HTML fragment instead? Why does it insist on an image? The browser requests a resource by URL to fill some screen space. If the server returns HTML, the client could show the HTML. This would have eliminated the need for frame and iframe.

    One embed-tag would have been enough instead of img, iframe, and video. An embed-tag would simply tell: "here comes some screen space that is to be filled with the src-URL". And nobody would care if the content type is an image or PDF or video or HTML.

    On the other hand, it's not really that bad.
    Not really worth a rant.
    Thanks for the native video, guys.
    It's cool.
    Especially combined with (the much too long ignored) SVG.

    :-) It's not like embedded native video hasn't been postulated 13 years ago. I asked them at RTMW 96 (last century), if they would just add a video codec to the browser and a simple request/response. But back then, people wanted to make it complicated with RTSP, multimedia frameworks and such. In the meantime we had never-really-working-MPEG-plugins, a Microsoft video player disaster, a Flash workaround, because Macromedia just could not stand it anymore. Finally, the browser guys made it as simple as requested in 1996.

    _happy_embedding()

    31. August 2005

    HTML Olymp

    Heute hat sich meine HTML-Messlatte verschoben. Ich dachte bisher ich kann HTML, aber es gibt Websites, da schlackern einem die Ohren ob der Korrektheit, Barrierefreiheit und technischen Aktualitaet. Ein schoenes Beispiel ist http://www.rainerwiegard.de/. Die Site ist barrierefrei in XHTML, sehr schick mit Design, aber ohne Tabellen. Mit Javascript und ohne gut lesbar, sogar in alten Browsern, nicht schoen, aber lesbar. Ohne, dass ein PHP im Server speziellen HTML-Code liefern muss. Wer hat schonmal eine Menuleiste ohne Tabellen gesehen? Ein Menu ist ein <ul> und Menuitems sind <li>. Es geht und man kann es auch echt schick aussehen lassen. Genauso sollte man es machen. Tolles HTML. Gratulation an Sandra Wiegard, die Designerin. OK, mein HTML bekommt kein "sehr gut" mehr. Im Web-Bereich rettet mich nur noch Javascript vor der Mittelmaessigkeit.

    _happy_coding()

    6. Juli 2005

    Wer braucht XSL?

    Habe ich jemals über meine Abneigung gegenüber XSL geschrieben? 2 Kritikpunkte: 1. Lesbarkeit, 2. Trennung von Code und Design. Wegen Punkt 2 finde ich XSL schlecht und falsch. Wegen Punkt 1 hasse ich es. Kurz: 1. XSL ist unleserlich. Die Skriptbefehle sehen genauso aus, wie die Daten und sind dazwischen verstreut. 2. Der Skriptcode im gleichen Dokument, wie das Design. Beides vermengt bildet das XSL. Früher hat man mal Code und Design getrennt.

    Zu 1: XSL kommt heraus, wenn ein XML-Liebhaber eine Skriptsprache erfinden will und deshalb alle Sprachelemente in spitze Klammern packt.

    Muss eine foreach Schleife wirklich so aussehen:

    <?xml:namespace prefix = xsl /></xsl:for-each>

    Das sah auch schon mal in anderen Sprachen so aus:

    foreach (item in dom.xpath("/sales/record")) ;

    Glaubten die XSL Erfinder wirklich, dass man nur XML ganz toll parsen kann und deshalb muss man eine Skriptsprachen im XML Format machen? Dazu kommt noch, dass die meisten Leute mit XSL am Ende dann HTML/XHTML erzeugen. Die HTML Fragmente stehen zwischen den XSL Tags und alles sieht nach Spitze-Klammer-Doppelpunkt-Slash Einheitsbrei aus.

    Zu 2: Wo wir schon gerade bei der Mischung von XSL-Skript und HTML sind. Die XSL-Skriptanweisungen sind Code. HTML mit CSS ist das Design. Gerade, weil man bei HTML ja gerne mal Formatierung mit Tabellen macht. Also sind bei XSL Code und Design vermischt. Eine tolle Idee. Wer hat schon mal von Templates gehört? Ein Template, das ist ein Dokument, dass ein Design festlegt. Es enthält keinen Code, außer vielleicht Javascript Code für die Clientseite. Code sollte ein Template benutzen, nicht im Template drin stehen.

    Das richtige Design wäre gewesen: Eine Skriptsprache, die aus Daten und einem Template schließlich HTML erzeugt. 3 Dateien: Skript(Code), Daten(XML oder Datenbank), Design(Template). XSL verwendet typischerweise nur 2 Dateien: Daten(XML), Code und Design(XSL). Schade.

    Skriptsprachen gibt es genügend. Die hätte man nicht erfinden müssen. Im Fall von XSL hätte sich das Javascript angeboten, weil das sowieso schon im Browser implementiert ist und auch in vielen Application-Servern. Oder vielleicht PHP oder Python oder man hätte das variabel gelassen und nur eine einheitliche Templateschnittstelle geschaffen.

    Warum rege ich mich überhaupt auf? Wir trennen Skriptsprache und Template bei allen Projekten. Was schert uns was die anderen machen? Es gibt eben Leute, die großen Einfluss auf die technische Entwicklung haben, weil sie in einem Moment an der richtigen Stelle sitzen und alle zu ihnen aufschauen. Eine solche Stelle ist(war) das W3C (WWW Consortium), dass die Web Standards macht(e). Wenn solche Leute falsche technische Entscheidungen treffen, dann haben sie eine Chance, dass es trotzdem die ganze Welt nachmacht. Auf diese Weise ist XSL zum Standard geworden und sogar in Browser eingebaut worden. Das wäre einfacher und besser gegangen. Schade dass keine 3-komponentige Formatierungsengine in Browser eingebaut wurde. Die könnte man gut verwenden.

    Bei der Gelegenheit möchte ich auch noch mal anmerken, dass Leute, die HTML und PHP mischen, keinen Deut besser sind, als XSL-ler.

    Etwas ausführlicher und auch schon etwas früher steht das auch hier, aber ich habe es erst heute entdeckt und musste das mal loswerden.

    _happy_coding_