The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,860 other subscribers

Archive for the ‘Usability’ Category

Office 2011 for Mac update pesky Window pops up every 10 seconds

Posted by jpluimers on 2018/03/27

From the “I hate my users” department:

  • This dialog pops up every 10 seconds
  • The Office 2011 for Mac update requires non-Office apps to quit as well

–jeroen

Posted in Apple, Development, iMac, Mac, Mac OS X / OS X / MacOS, MacBook, MacBook Retina, MacBook-Air, MacBook-Pro, MacMini, Office, Office 2011 for Mac, Power User, Software Development, Usability, User Experience (ux) | Leave a Comment »

Some links and references to IBM CUA: Common User Access which defines a lot of the UIs and UX we still use.

Posted by jpluimers on 2016/02/04

Back in the late 80s and early 90s of last century, engineers Richard E. Berry, Cliff J. Reeves set a standard that still influences the user interfaces and user experience of today: the IBM Common User Access.

I mentioned CUA a few times before, but since an old client of mine managed to throw away their paper originals in a “we don’t need that old stuff any more as we are now all digital” frenzy, I wanted to locate some PDFs. And I promised to write more about CUA.

If anyone has printed versions of the non-PDF documents below, please donate them to aek at bitsavers.org or scanning at archive.org as they are really hard to get.

A few search queries I used:

The PDFs I think are most interesting:

Read the rest of this entry »

Posted in BitSavers.org, Development, History, IBM SAA CUA, Keyboards and Keyboard Shortcuts, Power User, Software Development, UI Design, Usability, User Experience (ux) | 3 Comments »

Dark Patterns – User Interfaces Designed to Trick People

Posted by jpluimers on 2014/10/30

Interesting:

A Dark Pattern is a type of user interface that appears to have been carefully crafted to trick users into doing things, such as buying insurance with their purchase or signing up for recurring bills.

We developers have a big responsibility. Martin Fowler and Erik Dörnenburg (both ThoughtWorks) did a great presentation about that at the GOTO Aarhus 2014 Conference.

A quote:

“The developer who wrote that code is every bit as responsible as the person who told them to do it. You have a choice. You have a responsibility to ensure that your users are well treated and to reject dark patterns,” says Fowler. “We have a whole profession of people writing software and doing enormous things to change the way we live in the world.”

Please watch the video: Our Responsibility to Defeat Mass Surveillance – Erik Dörnenburg and Martin Fowler – YouTube.

–jeroen

via

Posted in .NET, Delphi, Development, Software Development, Usability, User Experience (ux) | 3 Comments »

Windows 8.x: Three keyboard/mouse ways to zoom in or out on start screen (via: YouTube)

Posted by jpluimers on 2014/08/22

I love it that in Windows you can do everything both by mouse and keyboard.
Take the start screen: there are 3 ways (mouse only, mouse + keyboard, keyboard only) to zoom in/out in the start screen. Read the rest of this entry »

Posted in Keyboards and Keyboard Shortcuts, Power User, Usability, User Experience (ux), Windows, Windows 8 | Leave a Comment »

The “Just In Time” Theory of User Behavior

Posted by jpluimers on 2014/08/10

Abstract of The “Just In Time” Theory of User Behavior:

…the design of your software has a profound impact on how users behave within your software…

  • Encouraging the “right” things by making those things intentionally easy to do.
  • Discouraging the “wrong” things by making those things intentionally difficult, complex, and awkward to do.

–jeroen

via: The “Just In Time” Theory of User Behavior.

Posted in Development, Software Development, Usability, User Experience (ux) | Leave a Comment »

Beveiligde gedeelte internetsite Belastingdienst: Makkelijker kan @BDzakelijk hiet niet maken…

Posted by jpluimers on 2014/01/25

Even lachen om de eisen van een nieuw zakelijk belastingdienst wachtwoord:

Uw wachtwoord moet:

  • anders zijn dan uw vorige wachtwoorden
  • minstens 3 karakters bevatten die niet in het wachtwoord voorkwamen dat u van ons hebt ontvangen
  • minstens 6 karakters lang zijn
  • niet meer dan 3 dezelfde karakters bevatten
  • minstens 3 letters bevatten
  • minstens 1 cijfer bevatten

Ofwel:

  1. het mag niet te complex (want dan krijg je herhalingen)
  2. het mag niet te makkelijk

Je komt daarmee uit richting een relatief kort en moeilijk te onthouden wachtwoord. Wat dan vast ergens genoteerd wordt en dus automatisch minder veilig is.

Iets als “WatWasDitEenGoedeUserExperience” kan dus niet (meer dan 3 keer een “e”)…

En dan komt daarna natuurlijk de password reset optie. Waar je “dus” niet je eigen controlevraag mag invullen, maar moet kiezen uit voor gedefinieerde vragen.

Controlevraag en antwoord opgegeven

Kies nu een controlevraag en antwoord. Bewaar uw controlevraag en antwoord goed. Hiermee kunt u zelf uw gebruikersnaam en/of wachtwoord achterhalen als u die later vergeten bent.


<select name="vraag"><option value="1" selected="selected">Initiële wachtwoord op de uitnodigingsbrief van de Belastingdienst</option>
<option value="2">Klantnummer van uw onderneming bij uw energiebedrijf</option>
<option value="3">Verloopdatum rijbewijs (dd-mm-jjjj) hoofdverantwoordelijke aangiften</option>
<option value="4">Pasnummer privé-bankpas van de hoofdverantwoordelijke aangiften</option></select>

De default is niet handig: stel je voor dat iemand de brief onder ogen krijgt. En de andere antwoorden zijn ofwel op te zoeken, ofwel met wat social engineering te achterhalen. Niet veilig.

De tekst boven de keuze suggereert dat je de informatie moet bewaren. Wat meestal een minder goede beveiliging oplevert, juist omdat bewaren (vaak op papier) vrijwel altijd impliceert dat ook anderen die informatie ooit te zien kunnen krijgen.

–jeroen

via: Beveiligde gedeelte internetsite Belastingdienst.

Posted in Usability, User Experience (ux) | Leave a Comment »

eLoket (Profiel)

Posted by jpluimers on 2013/03/20

Fijne foutmelding:

Uw formulier voldoet niet aan de volgende controles:

!

U heeft geen correct telefoonnummer ingevoerd. Een telefoonnummer moet beginnen met een 0 of + , bestaat uit minimaal 10 cijfers en mag geen leestekens bevatten

U heeft geen correct telefoonnummer ingevoerd. Een telefoonnummer moet beginnen met een 0 of + , bestaat uit minimaal 10 cijfers en mag geen leestekens bevatten

Inderdaad twee velden: telefoon en mobiel.

Noem ze dan niet beide “telefoonnummer!”.

En hou je gewoon aan de ITU-T E.123 standaard waar spaties, haakjes en plus gewoon zijn toegestaan.

Het vervolg is nog meer bizar:

Let op: een aantal gegevens kunt u niet meer wijzigen nadat ze zijn opgeslagen.

Zijn uw gegevens correct ingevuld?

Uiteraard staat nergens aangegeven WELKE gegevens niet meer te wijzigen zijn.

Stel je voor!

–jeroen

via: eLoket (Profiel).

Posted in Development, Software Development, Usability, User Experience (ux) | Leave a Comment »

.NET/C#: Generating a WordPress posting categories page – part 2

Posted by jpluimers on 2012/08/22

In Generating a WordPress posting categories page – part 1, you learned how to

  1. get the HTML with all the category information from your WordPress.com blog,
  2. convert that to XHTML,
  3. generate an XSD for the XHTML,
  4. generate C# classes from that XSD

This episode, you will learn how the data read from the XHTML can be transformed to a simple tree in HTML suited for a posting categories page like mine.

In the final post, the same data will be transferred into a real category cloud with font sizes indicating the frequency of the category usage.

From there, you can go into other directions (for instance generating squarified treemaps from the data).

That’s the cool thing about data: there are many ways to visualize, and this series was meant – next to some groundwork on how to get the data – as inspiration into some forms of visualization.
Hope you had fun reading it!

Getting a HTML tree from the optionType items

                StringBuilder outputHtml = new StringBuilder();
                string rootUrl = args[1];
                foreach (optionType item in select.option)
                {
                    if (item.Level == optionType.RootLevel)
                        continue;

                    // <a style="font-size: 100.3986332574%; padding: 1px; margin: 1px;" title="XML/XSD (23)" href="https://wiert.me/category/development/xmlxsd/">XML/XSD</a>
                    string url = String.Format("{0}/category{1}", rootUrl, item.HtmlPath);
                    string prefix = new string('.', item.Level * 5);// optionType.NbspEscaped.Repeat(item.Level);
                    outputHtml.AppendFormat("{0}<a title="{2}" href="{1}">{2} ({3})</a>", prefix, url, item.Category, item.Count);
                    outputHtml.AppendLine();
                }

One way of generating an HTML tree, is to prefix every node with a series of dots corresponding with the level of that node. Not the most pretty sight, but it will suffice for this episode.

Inside each node, I want to show the Category and Count.

Since the optionType as generated from the XSD only contains the below properties, a major portion on this posting is how to decode the Value so we can generate HTML like this:

...............<a href='https://wiert.me/category/development/software-development/net/c-' title='C#'>C#&nbsp;(118)</a>
....................<a href='https://wiert.me/category/development/software-development/net/c-/c--2-0' title='C# 2.0'>C# 2.0&nbsp;(46)</a>
....................<a href='https://wiert.me/category/development/software-development/net/c-/c--3-0' title='C# 3.0'>C# 3.0&nbsp;(33)</a>
....................<a href='https://wiert.me/category/development/software-development/net/c-/c--4-0' title='C# 4.0'>C# 4.0&nbsp;(31)</a>
....................<a href='https://wiert.me/category/development/software-development/net/c-/c--5-0' title='C# 5.0'>C# 5.0&nbsp;(2)</a>

Decoding the optionType Value property

optionType only contains the these properties:

  1. class
    • the class used to reference the style in the stylesheet
    • example value: “level-4”
  2. value
    • internal unique WordPress ID for the category (this allows you to alter the Slug and Value without breaking the links between posts and categories
    • example value: “45149061”
  3. Value
    • string that WordPress uses to make the category combobox look like a tree structure
    • example value: “&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C# 5.0&nbsp;&nbsp;(2)”

The extra properties needed for the HTML generation logic above are these:

  1. Category
    • the Value undone from leading non breaking space character escapes, and the trailing count information
    • example value: C# 5.0
  2. Count
    • the Value undone from leading non breaking space character escapes, Caption information, separator non breaking space character escapes, and surrounding parenthesis
    • example value: 2
  3. Level
    • the class undone from the level- prefix
    • example value: 4
  4. Slug
    • the category slug is the unique value for a category that WordPress uses to form category urls. It is auto-generated from the Category, but you can also edit it. I don’t, as it is not in the combobox HTML, so I derive it from the Category. Note there are also posting slugs used in the permalink of each post.
    • example value: c--5-0 (it consists of lowercase letters and hyphens derived from the Category)
  5. HtmlPath
  6. parent (used internally for making the HtmlPath code much easier

The really cool thing about XSD2Code is that it generated the optionType C# code as a partial class.
Which means we can extend the generated partial classes in a seperate C# file like the code fragments below (you can download it from the WordPressCategoriesDropDown.cs file at BeSharp.CodePlex.com)

    partial class optionType
    {
        public const int RootLevel = -1;

        private const string slash = "/";
        private const char hyphen = '-';
        public const string NbspEscaped = "&nbsp;";
        private const string emptyCountInParenthesis = "(-1)";

        public optionType parent { get; set; }

        public string Category
        {
            get
            {
                string result;
                string countInParenthesis;
                splitValue(out result, out countInParenthesis);
                return result;
            }
        }

        public int Count
        {
            get
            {
                string category;
                string countInParenthesis;
                splitValue(out category, out countInParenthesis);
                string count = countInParenthesis.Substring(1, countInParenthesis.Length - 2);
                int result = int.Parse(count);
                return result;
            }
        }

        public int Level
        {
            get
            {
                if (string.IsNullOrWhiteSpace(@class))
                    return RootLevel;
                string[] split = @class.Split(hyphen);
                string number = split[1];
                int result = int.Parse(number);
                return result;
            }
        }

        /// <summary>
        /// This is the HTML part that WordPress uses to reference a Category
        /// </summary>
        public string Slug
        {
            get
            {
                StringBuilder result = new StringBuilder();
                foreach (char item in Category)
                {
                    if (char.IsLetterOrDigit(item))
                        result.Append(item.ToString().ToLower());
                    else
                        if (result.Length > 0)
                            result.Append(hyphen);
                }
                return result.ToString();
            }
        }

        public string HtmlPath
        {
            get
            {
                if (RootLevel == Level)
                    return string.Empty;

                string result = Slug;
                if (null != parent)
                    result = parent.HtmlPath + slash + result;
                return result;
            }
        }

        private void splitValue(out string category, out string countInParenthesis)
        {
            // might want to do this using RegEx, but that is a write-only language https://wiert.me/category/development/software-development/regex/
            string result = Value;
            int nbspCountToStripFromLeftOfValue = Level * 3; // strip 3 &nbsp; for each Level
            for (int i = 0; i < nbspCountToStripFromLeftOfValue; i++)
            {
                int nbspEscapedLength = NbspEscaped.Length;
                if (result.StartsWith(NbspEscaped))
                    result = result.Substring(nbspEscapedLength, result.Length - nbspEscapedLength);
            }
            string doubleNbspEscaped = NbspEscaped + NbspEscaped;
            if (result.Contains(doubleNbspEscaped))
            {
                string[] separators = new string[] { doubleNbspEscaped };
                string[] split = result.Split(separators, StringSplitOptions.None);
                category = split[0];
                countInParenthesis = split[1];
            }
            else
            {
                category = result;
                countInParenthesis = emptyCountInParenthesis;
            }
        }

        public override string ToString()
        {
            string result = string.Format("Level {0}, Count {1}, Slug {2}, HtmlPath {3}, Category '{4}'", Level, Count, Slug, HtmlPath, Category);
            return result;
        }
    }

The bulk of the above code is in the splitValue method (that could have used RegEx, but I try to avoid RegEx when I can do without it).
Note that the HtmlPath propererty uses the parent property. Without it, the HtmlPath code would have been very complex. The value of the parent properties for all optionType instances is generated in the selectType.FixParents method below since the selectType instance contains all the optionType instances in its’ option property.

    partial class selectType
    {
        public void FixParents()
        {
            Stack<optionType> itemStack = new Stack<optionType>();
            optionType parent = null;
            int previousLevel = optionType.RootLevel;

            foreach (optionType item in option)
            {
                int itemLevel = item.Level;
                if (itemLevel == previousLevel)
                {
                    if (optionType.RootLevel != itemLevel)
                    {
                        itemStack.Pop();
                        item.parent = parent;
                    }
                    itemStack.Push(item);
                }
                else
                {
                    if (itemLevel > previousLevel)
                    {
                        parent = itemStack.Peek();
                    }
                    else
                    {
                        do
                        {
                            itemStack.Pop();
                            parent = itemStack.Peek();
                            previousLevel = parent.Level;
                        }
                        while (previousLevel >= itemLevel);
                    }
                    itemStack.Push(item);
                    item.parent = parent;
                    previousLevel = itemLevel;
                }
            }
        }
    }

–jeroen

Posted in .NET, C#, C# 4.0, C# 5.0, Development, LINQ, Software Development, Usability, User Experience (ux), Web Development, WordPress, WordPress, XML, XML escapes, XML/XSD, XSD | 4 Comments »

.NET/C#: Generating a WordPress posting categories page – part 1

Posted by jpluimers on 2012/07/31

From the category cloud it is hard to see that the categories are organized as a hierarchy. The combobox on the right shows that, but does not have room to properly show the hierarchy. Since WordPress.com does not allow you to deploy your own code, I worked around it in this way using a small .NET C# console program:

  1. Extract the HTML for the All Categories combobox on the right of the page.
  2. Convert that HTML to XHTML (and therefore XML)
  3. Generate XSD from that XML
  4. Generate C# class wrappers from the XSD

Future posts will show more logic on how to handle the imported information, and generate nice category overviews. Preliminary source code is at the BeSharp.net source repository.

Extract the HTML

The HTML is not fully accurate (see my post on HTML and XML escapes from last week), but it is fairly easy to extract. Most web browsers allow you to view the source of your web page. Do that, then search for “All Categories”. Now you see HTML like this:

</pre>
<h2 class="widgettitle">All categories</h2>
<pre><select class="postform" name="cat"><option value="-1">Select Category</option></select><select class="postform" name="cat"><option class="level-0" value="256">About  (66)</option></select><select class="postform" name="cat"><option class="level-1" value="64">   Personal  (60)</option></select><select class="postform" name="cat"><option class="level-2" value="20254983">      Adest Musica  (7)</option></select><select class="postform" name="cat"><option class="level-2" value="32122">      Certifications  (2)</option></select><select class="postform" name="cat">...</select><select class="postform" name="cat"><option class="level-0" value="756">Comics  (3)</option></select><select class="postform" name="cat"><option class="level-0" value="780">Development  (473)</option></select><select class="postform" name="cat"><option class="level-1" value="872460">   Database Development  (55)</option></select><select class="postform" name="cat">...</select><select class="postform" name="cat"><option class="level-0" value="9280">User Experience  (3)</option></select>

I don’t need the H2 heading line, but the rest I do need to generate XML from. I saved the HTML into a text file for processing by the console app.

Convert the HTML to XML

The HTML contains loads of &nbsp;, but XML does not allow for that entity. So the & ampersand needs to be escaped into &amp;This also solves other uses of & in the HTML. The rest of the HTML is XHTML compliant, so does not require change, which results into this C# conversion method:

        private static string toXml(string inputHtml)
        {
            string result = inputHtml.Replace("&", "&");
            return result;
        }

Generate an XSD for the XML, then amend the XSD

Given my comparison of tools for generating XSD from XML, so I used the XmlForAsp XML Schema generator, with the “Separate Complex Types” option. (Note: I will link to the XSD before/after, as WordPress – yet again – screws the XSD sourcecode in the post; this should do for now). That gives me XSD like this (XML is also at pastebin):

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="select" type="selectType" />
 <xsd:complexType name="selectType">
  <xsd:sequence>
   <xsd:element maxOccurs="unbounded" name="option" type="optionType" />
  </xsd:sequence>
  <xsd:attribute name="name" type="xsd:string" />
  <xsd:attribute name="id" type="xsd:string" />
  <xsd:attribute name="class" type="xsd:string" />
 </xsd:complexType>
 <xsd:complexType name="optionType">
  <xsd:attribute name="value" type="xsd:int" />
 </xsd:complexType>
</xsd:schema>

Which is not complete, but gives a good start. The actual XSD it needs to be like this with a more elaborate optionType complex type that also defines it’s own content as deriving from xsd:string, and adds the class attribute (XML is also at pastebin):

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="select" type="selectType" />
 <xsd:complexType name="selectType">
  <xsd:sequence>
   <xsd:element maxOccurs="unbounded" name="option" type="optionType" />
  </xsd:sequence>
  <xsd:attribute name="name" type="xsd:string" />
  <xsd:attribute name="id" type="xsd:string" />
  <xsd:attribute name="class" type="xsd:string" />
 </xsd:complexType>
 <xsd:complexType name="optionType">
  <xsd:simpleContent>
  <xsd:extension base="xsd:string">
   <xsd:attribute name="class" type="xsd:string" />
   <xsd:attribute name="value" type="xsd:int" />
  </xsd:extension>
 </xsd:simpleContent>
 </xsd:complexType>
</xsd:schema>

Generate C# classes from the XSD

You can generate C# wrapper classes using the XSD.exe tool that ships with Visual Studio, but XSD.exe is hard to use, is hard to integrate into Visual Studio (despite Microsoft Connect request for it), the XSD.exe generated code still needs work for deserializing, and XSD.exe has very limited generation options (heck, after it changed from .NET 1.x to 2.0, it hasn’t been updated for about a decade). XSD2Code has some great reviews, to I used that in stead. And indeed, very well integrates into Visual Studio 2010, and generates very nice C#, especially when you use the options (see also the screenshot on the right):

  • Under Serialization, set Enabled to True
  • Under Serialization, set GenerateXmlAttributes to True

That way, loading the HTML, converting it to XML, then deserializing it into object instances is as simple as this:

                string inputFileName = args[0];
                string inputHtml = getHtml(inputFileName);
                string xml = toXml(inputHtml);
                selectType select = selectType.Deserialize(xml);

More on actually working with the loaded instances in the next episode, including the great benefit of XSD2Code: it generates C# code as partial classes.

–jeroen

Posted in .NET, C#, C# 4.0, C# 5.0, Development, SocialMedia, Software Development, Usability, User Experience (ux), Web Development, WordPress, WordPress, XML, XML escapes, XML/XSD, XSD | 2 Comments »

Please web-people, post screen shots as PNG, not JPEG!

Posted by jpluimers on 2012/04/16

Don’t post screen shots as low quality JPEG.

Use PNG, which results in smaller files and better looking images.

Not like ING did: no screen reader can help visually impaired, and it gives a very bad user experience to the rest of the world.

Low quality JPEG screen shot; someone at ING has been sleeping again.

–jeroen

Posted in LifeHacker, Power User, Usability, User Experience (ux) | 1 Comment »