{"id":68691,"date":"2016-10-13T08:43:43","date_gmt":"2016-10-13T08:43:43","guid":{"rendered":"https:\/\/www.simple-talk.com\/?p=68691"},"modified":"2022-05-02T21:04:52","modified_gmt":"2022-05-02T21:04:52","slug":"tips-minimising-pain-html-input-forms","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/javascript\/tips-minimising-pain-html-input-forms\/","title":{"rendered":"Some Tips for Minimising the Pain of HTML Input Forms"},"content":{"rendered":"<p>The FORM element has been part of the HTML standard since the early days of the standard, and for this reason any online forms built, say, in the late 1990s still work today. However, no user would be happy to use a twenty-year-old HTML form. Why? Because of the whistles and bells that modern input forms are expected to have. In <a href=\"http:\/\/www.simple-talk.com\/dotnet\/asp-net\/multi-step-input-forms-asp-net-mvc\/\">a recent article<\/a> for Simple Talk touched on the problem of simplifying input when there\u2019s a large amount of data to provide. Multi-page, stepped forms are definitely a must in similar situations. However, just by using stepped forms on a recent project I learned a number of other things that, taken individually, are minor aspects of HTML input, but all together can provide a critical mass of tips for better HTML input.<\/p>\n<p>For this article, I collected a few of these tips that, with a very limited effort on your end, can make HTML forms look much nicer, and can guide users to entering data more comfortably.<\/p>\n<h2>Going beyond hidden-xs in Bootstrap<\/h2>\n<p>Like many of you, I do use Bootstrap nearly everywhere when constructing websites. Bootstrap has many merits and it\u2019s not perfect\u2014not even in upcoming version 4. Yet, I don\u2019t know anything better, and anyway it works well enough for my needs. With one notable exception\u2014the <strong>hidden-xs<\/strong> class.<\/p>\n<p>According to Bootstrap\u2019s syntax, <strong>hidden-xs<\/strong> is a responsive utility exposed as a CSS class that developers use to hide HTML elements when the viewport is less than 768 pixels wide. The Bootstrap folks call this size as \u201cextra-small\u201d. Doubtless this is too big to be the smallest point of control you can have on a responsive layout. Personally I\u2019d love to have a breakpoint around 480 pixels and judging from the comments on the Github repository of Bootstrap I\u2019m not the only one. The good news is that Bootstrap 4\u2014at the moment only in the alpha stage \u2013 will add a fifth breakpoint and resize the XS breakpoint to 544 pixels.<\/p>\n<p>The reason why many people wish to have a breakpoint around 500 pixels is to have more control over the markup rendered on really small screens. But the small screens that people are really concerned about are not the windows of desktop windows resized to the dimensions of a stamp. More realistically, if you\u2019re concerned about small screens, it is because of mobile devices, specifically smartphones. When it comes to smartphones you sometimes want to do certain things differently than in equivalent XS screens of a desktop. Let me give you a concrete example. The figure below shows a classic login form. The fancy thing about the form is that the page contains some JavaScript that hooks up a particular keyboard combination and completes the email address.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2016\/10\/word-image-5.png\" \/><\/p>\n<p>To be distinct from regular typing, the keyboard hotkey must necessarily include special key such as CTRL or ALT. Those keys are not available on smartphone and tablets. This is no big deal from a purely functional point of view because the hotkey will never fire. However, it would be nice if there were a way to hide that small piece of informative markup when the page is viewed on mobile devices. Unfortunately, hidden-xs was not designed for that. More, it\u2019s the entire Bootstrap framework that was designed to follow the principles of Responsive Web Design which makes a point of just ignoring any user agent strings.<\/p>\n<h3>From hidden-xs to hidden-mobile<\/h3>\n<p>In my Razor files, I wish I could write a piece of HTML markup like below:<\/p>\n<pre>&lt;div class=\"hidden-mobile\"&gt;\r\n     &lt;kbd&gt;ALT+P&lt;\/kbd&gt;\r\n     &lt;i class=\"fa fa-hand-o-right\"&gt;&lt;\/i&gt;\r\n     @MyApplication.AppSettings.DefaultEmailCompletion\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>The weird thing is the hidden-mobile CSS class. In spite of the Bootstrap-friendly name, it is not a new class of the framework and not even part of any add-ons. However, by combining together a small piece of JavaScript with a reliable client-side framework for device detection even a class like \u201chidden-mobile\u201d can become a reality. Here\u2019s my trick.<\/p>\n<p>First and foremost, the CSS class is just a marker and it\u2019s not defined anywhere. All elements styled with the class will be hidden programmatically. In other words, the class is used only as a jQuery selector to locate all the elements to hide. The crucial thing is in identifying the JavaScript framework that will do the device-detection. The only possible candidate for the role that I can recommend is <a href=\"http:\/\/web.wurfl.io\">WURFL.JS<\/a>. The framework is free to use, even though the vendor also offers a commercial license with many more features and a service-level agreement. For our purposes, though, the free basic version is more than enough. WURFL.JS is not a JavaScript file with logic inside. It is simply the JavaScript-like endpoint of a remote web service. You use the library by simply adding a SCRIPT tag.<\/p>\n<pre>  &lt;script type=\"text\/javascript\" src=\"\/\/wurfl.io\/wurfl.js\"&gt;&lt;\/script&gt;\r\n<\/pre>\n<p>You can do that in the _Layout.cshtml file or in individual views. The net effect of the linking of the SCRIPT element is to have a JavaScript object dynamically injected in the page DOM. The name of the object is WURFL and here\u2019s its prototype.<\/p>\n<pre>{\r\n    \"is_mobile\": false,\r\n    \"complete_device_name\": Microsoft Internet Explorer,\r\n    \"form_factor\": Desktop\r\n}\r\n<\/pre>\n<p>Needless to say, the values are what it returns when you view a page with Internet Explorer. The magic behind WURFL.JS is that it detects the user agent string that the browser sends while it is requesting what it believes is a plain JavaScript file. Based on that, the remote endpoint performs a sophisticated (and entirely server-side) analysis of the user agent string and packs any information available in the aforementioned JavaScript object. As a result, you have a brand new WURFL JavaScript object to check to make device-specific arrangements to the markup. At this point, all that remains to do is adding some custom JavaScript that checks WURFL information and finds a way to react.<\/p>\n<pre>(function() {\r\n    try {\r\n       var mobi = WURFL.is_mobile;\r\n       if (mobi) {\r\n          $(\".hidden-mobile\").hide();\r\n       }\r\n    } catch(e) {\r\n    })();\r\n<\/pre>\n<p>The <strong>form_factor<\/strong> property of the WURFL object contains detailed information about the class of the device, whether smartphone, tablet, webview within a native app, plain cell phone, smart-TV and a few more.<\/p>\n<h2>Bootstrap Button Drop-downs<\/h2>\n<p>It\u2019s really easy to take a Bootstrap button and turn it into the trigger of a drop-down menu. All it takes is a BUTTON and UL elements surrounded by a DIV.<\/p>\n<pre>&lt;div class=\"btn-group\"&gt;\r\n  &lt;button type=\"button\" \r\n          class=\"btn btn-default dropdown-toggle\" \r\n          data-toggle=\"dropdown\"&gt;\r\n    Open \r\n  &lt;\/button&gt;\r\n  &lt;ul class=\"dropdown-menu\"&gt;\r\n    &lt;li&gt;&lt;a href=\"#\"&gt;One&lt;\/a&gt;&lt;\/li&gt;\r\n    &lt;li&gt;&lt;a href=\"#\"&gt;Two&lt;\/a&gt;&lt;\/li&gt;\r\n    &lt;li&gt;&lt;a href=\"#\"&gt;Three&lt;\/li&gt;\r\n  &lt;\/ul&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>If you ever used Bootstrap, you are certainly familiar with this markup. It works just fine as long as you have a menu to display. The Bootstrap documentation doesn\u2019t provide any examples different from a drop-down menu and it\u2019s not unusual for me to meet developers that believe all they can drop-down is a menu-style list of hyperlinks. That\u2019s absolutely not the case. A drop-down is a drop-down, we could say, so you can replace the UL element with any other element you wish to drop-down when the user clicks the button.<\/p>\n<pre>&lt;div class=\"btn-group\"&gt;\r\n  &lt;button type=\"button\" \r\n          class=\"btn btn-default dropdown-toggle\" \r\n          data-toggle=\"dropdown\"&gt;\r\n    Open \r\n  &lt;\/button&gt;\r\n  &lt;div class=\"dropdown-menu\"&gt;\r\n     &lt;!-- Your content here --&gt;\r\n  &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>The most common and flexible thing you can do is replacing the UL element with a DIV element and place in the body of the DIV whatever content you wish. You\u2019re not even limited to read-only content. You can host an entire form and accept user\u2019s clicking. The figure below shows drop-down input form that illustrates a common scenario\u2014register as a user of the system from the same view you use to sign in.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2016\/10\/word-image-6.png\" \/><\/p>\n<p>The form schedule an appointment in the calendar for a client. The text input field on left will use auto-completion to find the client but if it\u2019s a new client, only minimal information can be entered through the NEW button drop-down.<\/p>\n<p>When you replace the UL with a DIV, you might want to overwrite the dropdown-menu CSS class. The most important change\u2014a necessary change I\u2019d say\u2014is to add a bit of padding because the default style sets rendering to start at 0,0 pixels in the top-left corner of the drop-down block.<\/p>\n<h2>SELECT and tabs<\/h2>\n<p>From a purely graphical perspective, I don\u2019t much like drop-down lists\u2014the SELECT element of HTML. When you give your views a Bootstrap refresh, the only elements that seem out of place are drop-down lists. However, if you use the form-control style on the SELECT element you get an acceptable result as far as pure display is concerned.<\/p>\n<pre>&lt;SELECT class=\"form-control\"&gt;\r\n   &lt;OPTION&gt; ... &lt;\/OPTION&gt;\r\n&lt;\/SELECT&gt;\r\n<\/pre>\n<p>The form-control style works by padding the container element of the displayed text and styling the border. When you move the focus to the list or when you click to change the current selection, the effect is quite ugly. Browsers typically emphasize only the background of the text which appears a thin line in a far larger container. On the other hand, if you don\u2019t just use the form-control Bootstrap style, then the native look of the SELECT element clashes brutally with the rest of the styled page.<\/p>\n<p>Frankly, there\u2019s not much you can do, other than reskinning the SELECT element entirely as quite a few jQuery plugins do out there. What I do sometimes is to capture the change event of the SELECT element and move the focus away.<\/p>\n<pre>$(\"select\").change(function (e) {\r\n    this.blur();\r\n});\r\n<\/pre>\n<p>This trick is just a trick and, as with many other tricks, it fixes one thing and breaks another. With the code in place, every time you make a selection the new item is selected with no visible clue of the focus. However, just because of that, if the user next starts tabbing through the input fields, well, the focus is not there anymore. To try repairing what I broke myself with the <strong>blur() <\/strong>call in the change event, I played with the <strong>tabIndex<\/strong> property. In HTML the <strong>tabIndex <\/strong>property indicates the order in which input fields are tabbed. By assigning the <strong>tabIndex<\/strong> to any field, you can take programmatic control of the order of tabs. In this way, here\u2019s how I rewrote the change event handler of SELECT elements.<\/p>\n<pre>$(\"select\").change(function (e) {\r\n    this.blur();\r\n\r\n    \/\/ Move the focus to the next input field\r\n    var index = parseInt($(this).attr('tabIndex')) + 1;\r\n    $(':input[tabindex=' + index + ']')[0].focus();\r\n});\r\n<\/pre>\n<p>After moving the focus away from the clicked SELECT element, the code reads the<strong> tabIndex<\/strong> of the SELECT and increases by one. Next, the code finds the INPUT element with the matching tab index. As long as <strong>tabIndex<\/strong> attributes are set through all the form, the effect is selecting the next input element. Not really a bad effect, all considered.<\/p>\n<h2>Changing colors on selection<\/h2>\n<p>Bootstrap doesn\u2019t offer classes or plugins to completely restructure a drop-down list. If you don\u2019t want to use the native SELECT element, you can choose one of the many jQuery plugins available. My favorite is <a href=\"https:\/\/developer.snapappointments.com\/bootstrap-select\/\">https:\/\/developer.snapappointments.com\/bootstrap-select\/<\/a>. The reason I like it is that it just works as Bootstrap would have done: You set a CSS class, import a JavaScript file and go. The markup is the same and some visual facilities for multiple selections are worth the choice.<\/p>\n<p>Frankly I have no idea of the reason why Bootstrap developers didn\u2019t even attempt to restyle or rewrite the SELECT element. However, I must mention that SELECT is one of those input elements that you don\u2019t want to modify at all on mobile devices. Mobile browsers provide a specific experience for SELECT elements and it would make no sense to change it to make it work better on desktop browsers.<\/p>\n<p>Remaining in the realm of the native SELECT element, I\u2019d like to mention a tip that is much appreciated by users although fairly simple to code. Sometimes, you use a drop-down list to select one of a few states, such as Active, Inactive, Locked and so forth. In this case, it might nice to show different colors depending on the selection, as in the figure below.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2016\/10\/word-image-7.png\" \/><\/p>\n<p>To obtain the effect, all you do is to intercept the change event and change the background color. In this case, when the user next clicks to change again, the background color is the same as was set last time. There\u2019s no way, in fact, to intercept the \u201copen\u201d event and change to a neutral color. As you can guess from the figure, it is immensely helpful for a user to see the status of an item from a color.<\/p>\n<h2>Summary<\/h2>\n<p>Any web sites today that collect information from users are obliged to do as much as possible to minimize the pain and improve the experience. Whether it\u2019s a matter of checking registration data on the server, validating email addresses or complaining about empty fields, even the scantiest login form nowadays is full of JavaScript and colorful effects. This article presented a few simple tips that, especially on top of a Bootstrap view, deliver benefit to users. Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>HTML Input forms are, by their nature, tiresome for the user of any website. However, with some attention to detail and a dash of JavaScript, it is possible to reduce the drudgery of form-filling to the minimum and minimise mistakes.  Dino explains four ways of making things better for the user of your website.&hellip;<\/p>\n","protected":false},"author":221911,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[146044],"tags":[],"coauthors":[6780],"class_list":["post-68691","post","type-post","status-publish","format-standard","hentry","category-javascript"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/68691","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221911"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=68691"}],"version-history":[{"count":6,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/68691\/revisions"}],"predecessor-version":[{"id":80604,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/68691\/revisions\/80604"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=68691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=68691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=68691"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=68691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}