{"id":1251,"date":"2010-06-20T20:49:36","date_gmt":"2010-06-21T00:49:36","guid":{"rendered":"http:\/\/www.useragentman.com\/blog\/?p=1251"},"modified":"2018-07-17T15:49:03","modified_gmt":"2018-07-17T19:49:03","slug":"visibleif-html5-custom-data-attributes-with-javascript-make-dynamic-interactive-forms","status":"publish","type":"post","link":"https:\/\/www.useragentman.com\/blog\/2010\/06\/20\/visibleif-html5-custom-data-attributes-with-javascript-make-dynamic-interactive-forms\/","title":{"rendered":"visibleIf \u2013 Dynamic and Complex Interactive Forms Using HTML5 Custom Data Attributes"},"content":{"rendered":"<div class=\"importantNotes\">\n<ul>\n<li><strong>Update (July 17, 2018):<\/strong> Updated this script to remove IE8 support.<\/li>\n<li><strong>Update (July 28, 2010):<\/strong> I have fixed a minor bug in this script to ensure compatibility with webforms2, part of <a href=\"https:\/\/www.useragentman.com\/blog\/2010\/07\/27\/cross-browser-html5-forms-using-modernizr-webforms2-and-html5widgets\/\">a suite of scripts that implement cross-browser compatibility with the HTML5 forms specification<\/a>.<\/li>\n<\/ul>\n<\/div>\n<p>I have been following the progression of the HTML5 Forms standard with great interest.  It promises a whole slew of new visual and usability goodness to existing HTML forms (e.g. slider and calendar widgets), a client-side validation framework, and so much more.  One of the things I was disappointed with, though, was that <strong>HTML5 cannot hide and show form elements depending on what the user has input into the form so far.<\/strong>  To give a very simple example of what I am talking about, select a country of origin in the form below:<\/p>\n<form>\n<table class=\"formTable\">\n<tbody>\n<tr>\n<th>Country of Origin: <\/th>\n<td><select name=\"country\"><option> Select One&#8230; <\/option><option value=\"Canada\"> Canada <\/option><option value=\"United States\"> United States <\/option><\/select><\/td>\n<\/tr>\n<tr class=\"visibleIf\" data-visibleif-rule=\" country == 'Canada'\">\n<th>Postal Code: <\/th>\n<td><input name=\"postalCode\" type=\"text\" \/><\/td>\n<\/tr>\n<tr class=\"visibleIf\" data-visibleif-rule=\" country == 'United States'\">\n<th>Zip Code: <\/th>\n<td><input name=\"zipCode\" type=\"text\" \/><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/form>\n<p>In HTML5, there is no way for a developer to tell the browser <em>&#8220;only show me this block of HTML if <\/em><code>country == 'Canada'<\/code><em>&#8220;<\/em>.  This is not a criticism of HTML5 or its authors &mdash; HTML5 forms has a lot of awesomeness in it (some of which I will blog about in my next article) and we can&#8217;t expect it to do everything. However, I have been using custom JavaScript to do this kind of stuff all the time, and wouldn&#8217;t it be great if the JavaScript challenged could do so?  In the ideal world graphic designers, J2EE programmers with minimal front-end experience, and even my 75-year-old mom should be able to do this.<\/p>\n<p>As a result, I present a JavaScript library, <code>visibleIf<\/code>, which allows web developers to use <a href=\"http:\/\/ejohn.org\/blog\/html-5-data-attributes\/\">HTML5 custom data attributes<\/a> to define when blocks of HTML should be visible or invisible.  <strong>Even if you are not a JavaScript genius, you will be able to make cool looking dynamic forms with very simple markup.<\/strong>  For example, let&#8217;s take a look at the HTML of the example above:<\/p>\n<blockquote class=\"code\">\n<pre>&lt;form&gt;\r\n    &lt;table class=\"formTable\"&gt;\r\n        &lt;tr&gt;\r\n            &lt;th&gt;Country of Origin&lt;\/th&gt;\r\n\r\n            &lt;td&gt;&lt;select name=\"country\"&gt;\r\n                &lt;option value=\"\"&gt;\r\n                    Select One...\r\n                &lt;\/option&gt;\r\n\r\n                &lt;option value=\"Canada\"&gt;\r\n                    Canada\r\n                &lt;\/option&gt;\r\n\r\n                &lt;option value=\"United States\"&gt;\r\n                    United States\r\n                &lt;\/option&gt;\r\n            &lt;\/select&gt; &lt;\/td&gt;\r\n        &lt;\/tr&gt;\r\n\r\n        &lt;tr <span class=\"hilite\">class=\"visibleIf\" data-visibleif-rule=\"country == 'Canada'\"<\/span>&gt;\r\n            &lt;th&gt;Postal Code&lt;\/th&gt;\r\n\r\n            &lt;td&gt;&lt;input type=\"text\" name=\"postalCode\"\r\n            value=\"\" \/&gt; &lt;\/td&gt;\r\n        &lt;\/tr&gt;\r\n\r\n        &lt;tr <span class=\"hilite\">class=\"visibleIf\" data-visibleif-rule=\"country == 'United States'\"<\/span>&gt;\r\n            &lt;th&gt;Zip Code&lt;\/th&gt;\r\n\r\n            &lt;td&gt;&lt;input type=\"text\" name=\"zipCode\"\r\n            value=\"\" \/&gt; &lt;\/td&gt;\r\n        &lt;\/tr&gt;\r\n    &lt;\/table&gt;\r\n&lt;\/form&gt;\r\n<\/pre>\n<\/blockquote>\n<p>This example is rather simple: the Postal Code form field is shown when <code>country == 'Canada'<\/code> and Zip Code is shown when <code>country == 'United States'<\/code>.  Note that in order to hide and show a block of HTML, you must set two attributes inside the containing tag:<\/p>\n<ul>\n<li><strong><code>class=\"visibleIf\"<\/code>:<\/strong> which lets the visibleIf.js script know that this block of HTML is to be hidden or shown according to the <code>data-visibleif-rule<\/code><\/li>\n<li><strong><code>data-visibleif-rule='<em>rule expression'<\/em><\/code>:<\/strong> which contains the visibility rule.  The rule variables are form element names, like <code>country<\/code> is in the above example. You can do simple equality rules like this, or complex ones like:<br \/>\n<blockquote class=\"code\">\n<pre>\r\n&lt;div class=\"visibleIf\" \r\n   data-visibleif-rule=\"country == 'Canada' &#038;& (city == 'Toronto' || city == 'Vancouver')\"&gt;\r\n  ...\r\n&lt;\/div&gt;\r\n<\/pre>\n<\/blockquote>\n<p>If you know a little bit of JavaScript, you will note that you can use JavaScript functions to do interesting rules like:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n&lt;div class=\"visibleIf\" data-visibleif-rule=\"parseInt(total) &gt; 100\"&gt;\r\n  ...\r\n&lt;\/div&gt;\r\n<\/pre>\n<\/blockquote>\n<\/li>\n<\/ul>\n<p>Note that the above examples have visibleIf rules inside a <code>tr<\/code> tag, <strong>they can be used in any tag inside an HTML form<\/strong>. <\/p>\n<p>Although the above example is quite simple, you can use visibleIf to make really complex forms &mdash; you can even put visibleIf blocks inside of visibleIf blocks.  To illustrate this I have created <a href=\"\/tests\/visibleIf\/example1.html\">a more interesting form<\/a> that shows what can be done using visibleIf.<\/p>\n<p><a href=\"\/tests\/visibleIf\/example1.html\" class=\"exampleLink\">See a more complex visibleIf form example<\/a><\/p>\n<h2>Hidden Fields &#8211; To Clear Or Not To Clear<\/h2>\n<p>If the user does something that hides some form fields (e.g. clicks on a checkbox) and then reverses that action (in this case clicking on the same checkbox), the fields will reappear with any previously filled-in data erased. Developers can override this default behavior by setting the class of the fields that shouldn&#8217;t be erased to <code>visibleIf-doNotReset<\/code>.  To illustrate this, I have created a page with two identical forms on it &mdash; one that erases the values inside hidden fields, and one that doesn&#8217;t.  Play with the example and you&#8217;ll see what I mean.<\/p>\n<p><a class=\"exampleLink\" href=\"\/tests\/visibleIf\/example2-dotNotReset.html\">See an example of a form with and without <code>visibleIf-doNotReset<\/code> fields.<\/a><\/p>\n<h2>Hidden Fields &#8211; Submit To The Server, Or Not?<\/h2>\n<p>Also note that by default, only the visible form elements are submitted to the server (this is because when a form element is hidden by <code>visibleIf<\/code>, its <code>disabled<\/code> attribute is set to <code>true<\/code> when the form is submitted).  If developers wants to override this behavior, they can simply set the form&#8217;s <code>class<\/code> to <code>visibleIf-submitInvisibleData<\/code>.<\/p>\n<p><a  class=\"exampleLink\"  href=\"\/tests\/visibleIf\/example2-submitInvisibleData.html\">See an example of a form with and without <code>visibleIf-submitInvisibleData<\/code> class set.<\/a><\/p>\n<h2>The Quick &#8220;How-To&#8221; Guide&#8221;<\/h2>\n<p>Setting up your existing forms to use visibleIf is a quick, three-step process:<\/p>\n<ol>\n<li>Get the source from <a href=\"https:\/\/github.com\/zoltan-dulac\/visibleIf\/\">the visibleIf GitHub repo<\/a><\/li>\n<li>Include the visibleIf.css stylesheet and visibleIf.js JavaScript files into your web page:<br \/>\n<blockquote class=\"code\">\n<pre>\r\n   &lt;head&gt;\r\n\r\n      ...\r\n\r\n      &lt;link rel=\"stylesheet\" href=\"\/path\/to\/visibleIf.css\" type=\"text\/css\" \/&gt;\r\n\r\n      ...\r\n\r\n   &lt;\/head&gt;\r\n   &lt;body&gt;\r\n\r\n      ...\r\n\r\n      &lt;!-- This should be as close the bottom of the body as possible --&gt;\r\n      &lt;script type=\"text\/javascript\" src=\"\/path\/to\/visibleIf.js\"&gt;\r\n      &lt;\/script&gt;\r\n   &lt;\/body&gt;\r\n<\/pre>\n<\/blockquote>\n<\/li>\n<li>Use the visibleIf rules as seen in the example above.  Note that <code>&amp;&amp;<\/code>, <code>||<\/code> and other logical operators are allowed in the expressions, as are JavaScript functions (e.g. parseInt, parseFloat, etc).<\/li>\n<\/ol>\n<h2>A Note On The Use Of Custom Data Attributes<\/h2>\n<p>Why did I bother with custom data attributes when making <code>visibleIf<\/code>?  Why did I just use the attribute <code>data-visibleif-rule<\/code> instead of just <code>visibleif-rule<\/code> or just <code>rule<\/code> to place the visibility rule? Wouldn&#8217;t that be simpler?<\/p>\n<ul>\n<li><strong><code>data-<\/code> attributes are HTML compliant: <\/strong>.  Their use ensure that <code>visibleIf<\/code> will be compatible with future versions of HTML since <strong><code>data-<\/code> attributes are reserved to be used for JavaScript libraries<\/strong>.  As long as you use the <a href=\"http:\/\/dev.w3.org\/html5\/spec\/syntax.html#the-doctype\">HTML5 DOCTYPE<\/a>, your forms should also validate.<\/li>\n<li><strong>The <code>data-visibleif-<\/code> prefix will not collide with attributes used in other JavaScript libraries. <\/strong> There is a high chance that <code>data-rule<\/code> could be used by another library.  Using the name of the library in the attribute significantly reduces that possibility.\n<\/ul>\n<h2>Download<\/h2>\n<p><a href=\"https:\/\/github.com\/zoltan-dulac\/visibleIf\/\" class=\"exampleLink\">Get the latest version of <code>visibleIf.js<\/code> from the project&#8217;s GitHub page.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One thing HTML5 forms can&#8217;t do is dynamically show and hide form elements according to the data that the user has already entered.  My new library, <code>visibleIf<\/code> gives you a very easy way to do this using the HTML5 <code>data-<\/code> attributes.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49,50,7],"tags":[],"class_list":["post-1251","post","type-post","status-publish","format-standard","hentry","category-custom-data-attributes","category-forms","category-javascript"],"_links":{"self":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/1251","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/comments?post=1251"}],"version-history":[{"count":14,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/1251\/revisions"}],"predecessor-version":[{"id":7601,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/1251\/revisions\/7601"}],"wp:attachment":[{"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/media?parent=1251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/categories?post=1251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/tags?post=1251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}