├── README.md ├── css ├── component.css ├── demo.css └── normalize.css ├── fonts ├── codropsicons │ ├── codropsicons.eot │ ├── codropsicons.svg │ ├── codropsicons.ttf │ ├── codropsicons.woff │ └── license.txt └── icomoon │ ├── icomoon.eot │ ├── icomoon.svg │ ├── icomoon.ttf │ └── icomoon.woff ├── index.html └── js ├── classie.js ├── modernizr.custom.js └── stepsForm.js /README.md: -------------------------------------------------------------------------------- 1 | Minimal Form Interface 2 | ========= 3 | 4 | A simplistic form with inputs shown one at a time. Inspired by the form seen on the end of the [PageLanes website](http://www.pagelanes.com/). 5 | 6 | [Article on Codrops](http://tympanus.net/codrops/?p=18780) 7 | 8 | [Demo](http://tympanus.net/Development/MinimalForm/) 9 | 10 | Integrate or build upon it for free in your personal or commercial projects. Don't republish, redistribute or sell "as-is". 11 | 12 | Read more here: [License](http://tympanus.net/codrops/licensing/) 13 | 14 | [© Codrops 2013](http://www.codrops.com) -------------------------------------------------------------------------------- /css/component.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-weight: normal; 3 | font-style: normal; 4 | font-family: 'icomoon'; 5 | src:url('../fonts/icomoon/icomoon.eot?-9heso'); 6 | src:url('../fonts/icomoon/icomoon.eot?#iefix-9heso') format('embedded-opentype'), 7 | url('../fonts/icomoon/icomoon.woff?-9heso') format('woff'), 8 | url('../fonts/icomoon/icomoon.ttf?-9heso') format('truetype'), 9 | url('../fonts/icomoon/icomoon.svg?-9heso#icomoon') format('svg'); 10 | } 11 | 12 | .simform { 13 | position: relative; 14 | margin: 0 auto; 15 | padding: 2em 0; 16 | max-width: 860px; 17 | width: 100%; 18 | text-align: left; 19 | font-size: 2.5em; 20 | } 21 | 22 | .simform .submit { 23 | display: none; 24 | } 25 | 26 | /* Question list style */ 27 | .simform ol { 28 | margin: 0; 29 | padding: 0; 30 | list-style: none; 31 | position: relative; 32 | -webkit-transition: height 0.4s; 33 | transition: height 0.4s; 34 | } 35 | 36 | .simform ol:before { 37 | content: ''; 38 | background-color: rgba(0,0,0,0.1); 39 | position: absolute; 40 | left: 0; 41 | bottom: 0; 42 | width: 100%; 43 | height: 2.35em; 44 | } 45 | 46 | .questions li { 47 | z-index: 100; 48 | position: relative; 49 | visibility: hidden; 50 | height: 0; 51 | -webkit-transition: visibility 0s 0.4s, height 0s 0.4s; 52 | transition: visibility 0s 0.4s, height 0s 0.4s; 53 | } 54 | 55 | .questions li.current, 56 | .no-js .questions li { 57 | visibility: visible; 58 | height: auto; 59 | -webkit-transition: none; 60 | transition: none; 61 | } 62 | 63 | /* Labels */ 64 | .questions li > span { 65 | display: block; 66 | overflow: hidden; 67 | } 68 | 69 | .questions li > span label { 70 | display: block; 71 | -webkit-transition: -webkit-transform 0.4s; 72 | transition: transform 0.4s; 73 | -webkit-transform: translateY(-100%); 74 | transform: translateY(-100%); 75 | } 76 | 77 | .questions li.current > span label, 78 | .no-js .questions li > span label { 79 | -webkit-transition: none; 80 | transition: none; 81 | -webkit-transform: translateY(0); 82 | transform: translateY(0); 83 | } 84 | 85 | .show-next .questions li.current > span label { 86 | -webkit-animation: moveUpFromDown 0.4s both; 87 | animation: moveUpFromDown 0.4s both; 88 | } 89 | 90 | @-webkit-keyframes moveUpFromDown { 91 | from { -webkit-transform: translateY(100%); } 92 | to { -webkit-transform: translateY(0); } 93 | } 94 | 95 | @keyframes moveUpFromDown { 96 | from { -webkit-transform: translateY(100%); transform: translateY(100%); } 97 | to { -webkit-transform: translateY(0); transform: translateY(0); } 98 | } 99 | 100 | /* Input field */ 101 | .questions input { 102 | display: block; 103 | margin: 0.3em 0 0 0; 104 | padding: 0.2em 1em 0.5em 0.7em; 105 | width: calc(100% - 2em); 106 | border: none; 107 | background: transparent; 108 | color: rgba(0,0,0,0.8); 109 | font-size: 1em; 110 | line-height: 1; 111 | opacity: 0; 112 | -webkit-transition: opacity 0.3s; 113 | transition: opacity 0.3s; 114 | height: 2.1em; 115 | } 116 | 117 | .questions .current input, 118 | .no-js .questions input { 119 | opacity: 1; 120 | } 121 | 122 | .questions input:focus, 123 | .simform button:focus { 124 | outline: none; 125 | } 126 | 127 | /* Next question button */ 128 | .next { 129 | position: absolute; 130 | right: 0; 131 | bottom: 2.15em; /* padding-bottom of form plus progress bar height */ 132 | display: block; 133 | padding: 0; 134 | width: 2em; 135 | height: 2em; 136 | border: none; 137 | background: none; 138 | color: rgba(0,0,0,0.4); 139 | text-align: center; 140 | opacity: 0; 141 | z-index: 100; 142 | cursor: pointer; 143 | -webkit-transition: -webkit-transform 0.3s, opacity 0.3s; 144 | transition: transform 0.3s, opacity 0.3s; 145 | -webkit-transform: translateX(-20%); 146 | transform: translateX(-20%); 147 | pointer-events: none; 148 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 149 | } 150 | 151 | .next:hover { 152 | color: rgba(0,0,0,0.5); 153 | } 154 | 155 | .next::after { 156 | position: absolute; 157 | top: 0; 158 | left: 0; 159 | width: 100%; 160 | height: 100%; 161 | content: "\e600"; 162 | text-transform: none; 163 | font-weight: normal; 164 | font-style: normal; 165 | font-variant: normal; 166 | font-family: 'icomoon'; 167 | line-height: 2; 168 | speak: none; 169 | -webkit-font-smoothing: antialiased; 170 | -moz-osx-font-smoothing: grayscale; 171 | } 172 | 173 | .next.show { 174 | opacity: 1; 175 | -webkit-transform: translateX(0); 176 | transform: translateX(0); 177 | pointer-events: auto; 178 | } 179 | 180 | /* Progress bar */ 181 | .simform .progress { 182 | width: 0%; 183 | height: 0.15em; 184 | background: rgba(0,0,0,0.3); 185 | -webkit-transition: width 0.4s ease-in-out; 186 | transition: width 0.4s ease-in-out; 187 | } 188 | 189 | .simform .progress::before { 190 | position: absolute; 191 | top: auto; 192 | width: 100%; 193 | height: inherit; 194 | background: rgba(0,0,0,0.05); 195 | content: ''; 196 | } 197 | 198 | /* Number indicator */ 199 | .simform .number { 200 | position: absolute; 201 | right: 0; 202 | overflow: hidden; 203 | margin: 0.4em 0; 204 | width: 3em; 205 | font-weight: 700; 206 | font-size: 0.4em; 207 | } 208 | 209 | .simform .number:after { 210 | position: absolute; 211 | left: 50%; 212 | content: '/'; 213 | opacity: 0.4; 214 | -webkit-transform: translateX(-50%); 215 | transform: translateX(-50%); 216 | } 217 | 218 | .simform .number span { 219 | float: right; 220 | width: 40%; 221 | text-align: center; 222 | } 223 | 224 | .simform .number .number-current { 225 | float: left; 226 | } 227 | 228 | .simform .number-next { 229 | position: absolute; 230 | left: 0; 231 | } 232 | 233 | .simform.show-next .number-current { 234 | -webkit-transition: -webkit-transform 0.4s; 235 | transition: transform 0.4s; 236 | -webkit-transform: translateY(-100%); 237 | transform: translateY(-100%); 238 | } 239 | 240 | .simform.show-next .number-next { 241 | -webkit-animation: moveUpFromDown 0.4s both; 242 | animation: moveUpFromDown 0.4s both; 243 | } 244 | 245 | /* Error and final message */ 246 | .simform .error-message, 247 | .simform .final-message { 248 | position: absolute; 249 | visibility: hidden; 250 | opacity: 0; 251 | -webkit-transition: opacity 0.4s; 252 | transition: opacity 0.4s; 253 | } 254 | 255 | .simform .error-message { 256 | padding: 0.4em 3.5em 0 0; 257 | width: 100%; 258 | color: rgba(0,0,0,0.7); 259 | font-style: italic; 260 | font-size: 0.4em; 261 | } 262 | 263 | .final-message { 264 | top: 50%; 265 | left: 0; 266 | padding: 0.5em; 267 | width: 100%; 268 | text-align: center; 269 | -webkit-transform: translateY(-50%); 270 | transform: translateY(-50%); 271 | } 272 | 273 | .error-message.show, 274 | .final-message.show { 275 | visibility: visible; 276 | opacity: 1; 277 | } 278 | 279 | .final-message.show { 280 | -webkit-transition-delay: 0.5s; 281 | transition-delay: 0.5s; 282 | } 283 | 284 | /* Final hiding of form / showing message */ 285 | .simform-inner.hide { 286 | visibility: hidden; 287 | opacity: 0; 288 | -webkit-transition: opacity 0.3s, visibility 0s 0.3s; 289 | transition: opacity 0.3s, visibility 0s 0.3s; 290 | } 291 | 292 | /* No JS Fallback */ 293 | .no-js .simform { 294 | font-size: 1.75em; 295 | } 296 | 297 | .no-js .questions li { 298 | padding: 0 0 2em; 299 | } 300 | 301 | .no-js .simform .submit { 302 | display: block; 303 | float: right; 304 | padding: 10px 20px; 305 | border: none; 306 | background: rgba(0,0,0,0.3); 307 | color: rgba(0,0,0,0.4); 308 | } 309 | 310 | .no-js .simform .controls { 311 | display: none; 312 | } 313 | 314 | /* Remove IE clear cross */ 315 | input[type=text]::-ms-clear { 316 | display: none; 317 | } 318 | 319 | /* Adjust form for smaller screens */ 320 | @media screen and (max-width: 44.75em) { 321 | .simform { 322 | font-size: 1.8em; 323 | } 324 | } 325 | 326 | @media screen and (max-width: 33.5625em) { 327 | .simform { 328 | font-size: 1.2em; 329 | } 330 | } -------------------------------------------------------------------------------- /css/demo.css: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Lato:400,700,400italic); 2 | @font-face { 3 | font-weight: normal; 4 | font-style: normal; 5 | font-family: 'codropsicons'; 6 | src:url('../fonts/codropsicons/codropsicons.eot'); 7 | src:url('../fonts/codropsicons/codropsicons.eot?#iefix') format('embedded-opentype'), 8 | url('../fonts/codropsicons/codropsicons.woff') format('woff'), 9 | url('../fonts/codropsicons/codropsicons.ttf') format('truetype'), 10 | url('../fonts/codropsicons/codropsicons.svg#codropsicons') format('svg'); 11 | } 12 | 13 | *, *:after, *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } 14 | .clearfix:before, .clearfix:after { content: ''; display: table; } 15 | .clearfix:after { clear: both; } 16 | 17 | body { 18 | background: #26C281; 19 | color: rgba(0,0,0,0.45); 20 | font-size: 100%; 21 | line-height: 1.25; 22 | font-family: 'Lato', Arial, sans-serif; 23 | } 24 | 25 | a { 26 | color: rgba(0,0,0,0.25); 27 | text-decoration: none; 28 | outline: none; 29 | } 30 | 31 | a:hover, a:focus { 32 | color: rgba(0,0,0,0.6); 33 | } 34 | 35 | .codrops-header { 36 | margin: 0 auto; 37 | padding: 3em 1em; 38 | text-align: center; 39 | color: rgba(0,0,0,0.35); 40 | } 41 | 42 | .codrops-header h1 { 43 | margin: 0; 44 | font-weight: 400; 45 | font-size: 2.5em; 46 | } 47 | 48 | .codrops-header h1 span { 49 | display: block; 50 | padding: 0 0 0.6em 0.1em; 51 | font-size: 0.6em; 52 | opacity: 0.7; 53 | } 54 | 55 | /* To Navigation Style */ 56 | .codrops-top { 57 | width: 100%; 58 | text-transform: uppercase; 59 | font-weight: 700; 60 | font-size: 0.69em; 61 | line-height: 2.2; 62 | } 63 | 64 | .codrops-top a { 65 | display: inline-block; 66 | padding: 0 1em; 67 | text-decoration: none; 68 | letter-spacing: 1px; 69 | } 70 | 71 | .codrops-top span.right { 72 | float: right; 73 | } 74 | 75 | .codrops-top span.right a { 76 | display: block; 77 | float: left; 78 | } 79 | 80 | .codrops-icon:before { 81 | margin: 0 4px; 82 | text-transform: none; 83 | font-weight: normal; 84 | font-style: normal; 85 | font-variant: normal; 86 | font-family: 'codropsicons'; 87 | line-height: 1; 88 | speak: none; 89 | -webkit-font-smoothing: antialiased; 90 | } 91 | 92 | .codrops-icon-drop:before { 93 | content: "\e001"; 94 | } 95 | 96 | .codrops-icon-prev:before { 97 | content: "\e004"; 98 | } 99 | 100 | section { 101 | padding: 5em 2em 10em; 102 | background: #2dcb89; 103 | text-align: center; 104 | } 105 | 106 | section.related { 107 | padding: 3em 1em 4em; 108 | background: #465650; 109 | color: rgba(0,0,0,0.4); 110 | font-size: 1.5em; 111 | } 112 | 113 | .related > a { 114 | max-width: 80%; 115 | border: 2px solid rgba(0,0,0,0.3); 116 | display: inline-block; 117 | text-align: center; 118 | margin: 20px 10px; 119 | padding: 25px; 120 | -webkit-transition: color 0.3s, border-color 0.3s; 121 | transition: color 0.3s, border-color 0.3s; 122 | } 123 | 124 | .related a:hover { 125 | border-color: rgba(0,0,0,0.6); 126 | } 127 | 128 | .related a img { 129 | max-width: 100%; 130 | opacity: 0.4; 131 | -webkit-transition: opacity 0.3s; 132 | transition: opacity 0.3s; 133 | } 134 | 135 | .related a:hover img, 136 | .related a:active img { 137 | opacity: 1; 138 | } 139 | 140 | .related a h3 { 141 | margin: 0; 142 | padding: 0.5em 0 0.3em; 143 | max-width: 300px; 144 | font-weight: 400; 145 | font-size: 0.75em; 146 | text-align: left; 147 | } 148 | 149 | @media screen and (max-width: 44.75em) { 150 | section { padding: 1em 2em; } 151 | } 152 | 153 | @media screen and (max-width: 25em) { 154 | .codrops-header { font-size: 0.8em; } 155 | section.related { font-size: 1.2em; } 156 | .codrops-icon span { display: none; } 157 | } -------------------------------------------------------------------------------- /css/normalize.css: -------------------------------------------------------------------------------- 1 | article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;} -------------------------------------------------------------------------------- /fonts/codropsicons/codropsicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/MinimalForm/9ecb888f388eac23e4a20bf795343673f6eb2367/fonts/codropsicons/codropsicons.eot -------------------------------------------------------------------------------- /fonts/codropsicons/codropsicons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This is a custom SVG font generated by IcoMoon. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /fonts/codropsicons/codropsicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/MinimalForm/9ecb888f388eac23e4a20bf795343673f6eb2367/fonts/codropsicons/codropsicons.ttf -------------------------------------------------------------------------------- /fonts/codropsicons/codropsicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/MinimalForm/9ecb888f388eac23e4a20bf795343673f6eb2367/fonts/codropsicons/codropsicons.woff -------------------------------------------------------------------------------- /fonts/codropsicons/license.txt: -------------------------------------------------------------------------------- 1 | Icon Set: Font Awesome -- http://fortawesome.github.com/Font-Awesome/ 2 | License: SIL -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 3 | 4 | 5 | Icon Set: Eco Ico -- http://dribbble.com/shots/665585-Eco-Ico 6 | License: CC0 -- http://creativecommons.org/publicdomain/zero/1.0/ -------------------------------------------------------------------------------- /fonts/icomoon/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/MinimalForm/9ecb888f388eac23e4a20bf795343673f6eb2367/fonts/icomoon/icomoon.eot -------------------------------------------------------------------------------- /fonts/icomoon/icomoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /fonts/icomoon/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/MinimalForm/9ecb888f388eac23e4a20bf795343673f6eb2367/fonts/icomoon/icomoon.ttf -------------------------------------------------------------------------------- /fonts/icomoon/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/MinimalForm/9ecb888f388eac23e4a20bf795343673f6eb2367/fonts/icomoon/icomoon.woff -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Minimal Form Interface 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | Previous Demo 22 | Back to the Codrops Article 23 |
24 |
25 |

Minimal Form Interface Simplistic, single input view form

26 |
27 |
28 |
29 |
30 |
    31 |
  1. 32 | 33 | 34 |
  2. 35 |
  3. 36 | 37 | 38 |
  4. 39 |
  5. 40 | 41 | 42 |
  6. 43 |
  7. 44 | 45 | 46 |
  8. 47 |
  9. 48 | 49 | 50 |
  10. 51 |
  11. 52 | 53 | 54 |
  12. 55 |
56 | 57 |
58 | 59 |
60 | 61 | 62 | 63 | 64 | 65 |
66 |
67 | 68 |
69 |
70 | 81 |
82 | 83 | 84 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /js/classie.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * classie - class helper functions 3 | * from bonzo https://github.com/ded/bonzo 4 | * 5 | * classie.has( elem, 'my-class' ) -> true/false 6 | * classie.add( elem, 'my-new-class' ) 7 | * classie.remove( elem, 'my-unwanted-class' ) 8 | * classie.toggle( elem, 'my-class' ) 9 | */ 10 | 11 | /*jshint browser: true, strict: true, undef: true */ 12 | /*global define: false */ 13 | 14 | ( function( window ) { 15 | 16 | 'use strict'; 17 | 18 | // class helper functions from bonzo https://github.com/ded/bonzo 19 | 20 | function classReg( className ) { 21 | return new RegExp("(^|\\s+)" + className + "(\\s+|$)"); 22 | } 23 | 24 | // classList support for class management 25 | // altho to be fair, the api sucks because it won't accept multiple classes at once 26 | var hasClass, addClass, removeClass; 27 | 28 | if ( 'classList' in document.documentElement ) { 29 | hasClass = function( elem, c ) { 30 | return elem.classList.contains( c ); 31 | }; 32 | addClass = function( elem, c ) { 33 | elem.classList.add( c ); 34 | }; 35 | removeClass = function( elem, c ) { 36 | elem.classList.remove( c ); 37 | }; 38 | } 39 | else { 40 | hasClass = function( elem, c ) { 41 | return classReg( c ).test( elem.className ); 42 | }; 43 | addClass = function( elem, c ) { 44 | if ( !hasClass( elem, c ) ) { 45 | elem.className = elem.className + ' ' + c; 46 | } 47 | }; 48 | removeClass = function( elem, c ) { 49 | elem.className = elem.className.replace( classReg( c ), ' ' ); 50 | }; 51 | } 52 | 53 | function toggleClass( elem, c ) { 54 | var fn = hasClass( elem, c ) ? removeClass : addClass; 55 | fn( elem, c ); 56 | } 57 | 58 | var classie = { 59 | // full names 60 | hasClass: hasClass, 61 | addClass: addClass, 62 | removeClass: removeClass, 63 | toggleClass: toggleClass, 64 | // short names 65 | has: hasClass, 66 | add: addClass, 67 | remove: removeClass, 68 | toggle: toggleClass 69 | }; 70 | 71 | // transport 72 | if ( typeof define === 'function' && define.amd ) { 73 | // AMD 74 | define( classie ); 75 | } else { 76 | // browser global 77 | window.classie = classie; 78 | } 79 | 80 | })( window ); 81 | -------------------------------------------------------------------------------- /js/modernizr.custom.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.7.1 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-csstransitions-shiv-cssclasses-prefixed-testprop-testallprops-domprefixes-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function x(a){j.cssText=a}function y(a,b){return x(prefixes.join(a+";")+(b||""))}function z(a,b){return typeof a===b}function A(a,b){return!!~(""+a).indexOf(b)}function B(a,b){for(var d in a){var e=a[d];if(!A(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function C(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:z(f,"function")?f.bind(d||b):f}return!1}function D(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+n.join(d+" ")+d).split(" ");return z(b,"string")||z(b,"undefined")?B(e,b):(e=(a+" "+o.join(d+" ")+d).split(" "),C(e,b,c))}var d="2.7.1",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m="Webkit Moz O ms",n=m.split(" "),o=m.toLowerCase().split(" "),p={},q={},r={},s=[],t=s.slice,u,v={}.hasOwnProperty,w;!z(v,"undefined")&&!z(v.call,"undefined")?w=function(a,b){return v.call(a,b)}:w=function(a,b){return b in a&&z(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=t.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(t.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(t.call(arguments)))};return e}),p.csstransitions=function(){return D("transition")};for(var E in p)w(p,E)&&(u=E.toLowerCase(),e[u]=p[E](),s.push((e[u]?"":"no-")+u));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)w(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},x(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._domPrefixes=o,e._cssomPrefixes=n,e.testProp=function(a){return B([a])},e.testAllProps=D,e.prefixed=function(a,b,c){return b?D(a,b,c):D(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+s.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f li' ) ); 60 | // total questions 61 | this.questionsCount = this.questions.length; 62 | // show first question 63 | classie.addClass( this.questions[0], 'current' ); 64 | 65 | // next question control 66 | this.ctrlNext = this.el.querySelector( 'button.next' ); 67 | this.ctrlNext.setAttribute( 'aria-label', 'Next' ); 68 | 69 | // progress bar 70 | this.progress = this.el.querySelector( 'div.progress' ); 71 | // set progressbar attributes 72 | this.progress.setAttribute( 'role', 'progressbar' ); 73 | this.progress.setAttribute( 'aria-readonly', 'true' ); 74 | this.progress.setAttribute( 'aria-valuemin', '0' ); 75 | this.progress.setAttribute( 'aria-valuemax', '100' ); 76 | this.progress.setAttribute( 'aria-valuenow', '0' ); 77 | 78 | // question number status 79 | this.questionStatus = this.el.querySelector( 'span.number' ); 80 | // give the questions status an id 81 | this.questionStatus.id = this.questionStatus.id || randomID(); 82 | // associate "x / y" with the input via aria-describedby 83 | for (var i = this.questions.length - 1; i >= 0; i--) { 84 | var formElement = this.questions[i].querySelector( 'input, textarea, select' ); 85 | formElement.setAttribute( 'aria-describedby', this.questionStatus.id ); 86 | }; 87 | // current question placeholder 88 | this.currentNum = this.questionStatus.querySelector( 'span.number-current' ); 89 | this.currentNum.innerHTML = Number( this.current + 1 ); 90 | // total questions placeholder 91 | this.totalQuestionNum = this.questionStatus.querySelector( 'span.number-total' ); 92 | this.totalQuestionNum.innerHTML = this.questionsCount; 93 | 94 | // error message 95 | this.error = this.el.querySelector( 'span.error-message' ); 96 | 97 | // checks for HTML5 Form Validation support 98 | // a cleaner solution might be to add form validation to the custom Modernizr script 99 | this.supportsHTML5Forms = typeof document.createElement("input").checkValidity === 'function'; 100 | 101 | // init events 102 | this._initEvents(); 103 | }; 104 | 105 | stepsForm.prototype._initEvents = function() { 106 | var self = this, 107 | // first input 108 | firstElInput = this.questions[ this.current ].querySelector( 'input, textarea, select' ), 109 | // focus 110 | onFocusStartFn = function() { 111 | firstElInput.removeEventListener( 'focus', onFocusStartFn ); 112 | classie.addClass( self.ctrlNext, 'show' ); 113 | }; 114 | 115 | // show the next question control first time the input gets focused 116 | firstElInput.addEventListener( 'focus', onFocusStartFn ); 117 | 118 | // show next question 119 | this.ctrlNext.addEventListener( 'click', function( ev ) { 120 | ev.preventDefault(); 121 | self._nextQuestion(); 122 | } ); 123 | 124 | // pressing enter will jump to next question 125 | this.el.addEventListener( 'keydown', function( ev ) { 126 | var keyCode = ev.keyCode || ev.which; 127 | // enter 128 | if( keyCode === 13 ) { 129 | ev.preventDefault(); 130 | self._nextQuestion(); 131 | } 132 | } ); 133 | }; 134 | 135 | stepsForm.prototype._nextQuestion = function() { 136 | if( !this._validate() ) { 137 | return false; 138 | } 139 | 140 | // checks HTML5 validation 141 | if ( this.supportsHTML5Forms ) { 142 | var input = this.questions[ this.current ].querySelector( 'input, textarea, select' ); 143 | // clear any previous error messages 144 | input.setCustomValidity( '' ); 145 | 146 | // checks input against the validation constraint 147 | if ( !input.checkValidity() ) { 148 | // Optionally, set a custom HTML5 valiation message 149 | // comment or remove this line to use the browser default message 150 | input.setCustomValidity( 'Whoops, that\'s not an email address!' ); 151 | // display the HTML5 error message 152 | this._showError( input.validationMessage ); 153 | // prevent the question from changing 154 | return false; 155 | } 156 | } 157 | 158 | // check if form is filled 159 | if( this.current === this.questionsCount - 1 ) { 160 | this.isFilled = true; 161 | } 162 | 163 | // clear any previous error messages 164 | this._clearError(); 165 | 166 | // current question 167 | var currentQuestion = this.questions[ this.current ]; 168 | 169 | // increment current question iterator 170 | ++this.current; 171 | 172 | // update progress bar 173 | this._progress(); 174 | 175 | if( !this.isFilled ) { 176 | // change the current question number/status 177 | this._updateQuestionNumber(); 178 | 179 | // add class "show-next" to form element (start animations) 180 | classie.addClass( this.el, 'show-next' ); 181 | 182 | // remove class "current" from current question and add it to the next one 183 | // current question 184 | var nextQuestion = this.questions[ this.current ]; 185 | classie.removeClass( currentQuestion, 'current' ); 186 | classie.addClass( nextQuestion, 'current' ); 187 | } 188 | 189 | // after animation ends, remove class "show-next" from form element and change current question placeholder 190 | var self = this, 191 | onEndTransitionFn = function( ev ) { 192 | if( support.transitions ) { 193 | this.removeEventListener( transEndEventName, onEndTransitionFn ); 194 | } 195 | if( self.isFilled ) { 196 | self._submit(); 197 | } 198 | else { 199 | classie.removeClass( self.el, 'show-next' ); 200 | self.currentNum.innerHTML = self.nextQuestionNum.innerHTML; 201 | self.questionStatus.removeChild( self.nextQuestionNum ); 202 | // force the focus on the next input 203 | nextQuestion.querySelector( 'input, textarea, select' ).focus(); 204 | } 205 | }; 206 | 207 | if( support.transitions ) { 208 | this.progress.addEventListener( transEndEventName, onEndTransitionFn ); 209 | } 210 | else { 211 | onEndTransitionFn(); 212 | } 213 | } 214 | 215 | // updates the progress bar by setting its width 216 | stepsForm.prototype._progress = function() { 217 | var currentProgress = this.current * ( 100 / this.questionsCount ); 218 | this.progress.style.width = currentProgress + '%'; 219 | // update the progressbar's aria-valuenow attribute 220 | this.progress.setAttribute('aria-valuenow', currentProgress); 221 | } 222 | 223 | // changes the current question number 224 | stepsForm.prototype._updateQuestionNumber = function() { 225 | // first, create next question number placeholder 226 | this.nextQuestionNum = document.createElement( 'span' ); 227 | this.nextQuestionNum.className = 'number-next'; 228 | this.nextQuestionNum.innerHTML = Number( this.current + 1 ); 229 | // insert it in the DOM 230 | this.questionStatus.appendChild( this.nextQuestionNum ); 231 | } 232 | 233 | // submits the form 234 | stepsForm.prototype._submit = function() { 235 | this.options.onSubmit( this.el ); 236 | } 237 | 238 | // TODO (next version..) 239 | // the validation function 240 | stepsForm.prototype._validate = function() { 241 | // current question´s input 242 | var input = this.questions[ this.current ].querySelector( 'input, textarea, select' ).value; 243 | if( input === '' ) { 244 | this._showError( 'EMPTYSTR' ); 245 | return false; 246 | } 247 | 248 | return true; 249 | } 250 | 251 | // TODO (next version..) 252 | stepsForm.prototype._showError = function( err ) { 253 | var message = ''; 254 | switch( err ) { 255 | case 'EMPTYSTR' : 256 | message = 'Please fill the field before continuing'; 257 | break; 258 | case 'INVALIDEMAIL' : 259 | message = 'Please fill a valid email address'; 260 | break; 261 | // ... 262 | default : 263 | message = err; 264 | }; 265 | this.error.innerHTML = message; 266 | classie.addClass( this.error, 'show' ); 267 | } 268 | 269 | // clears/hides the current error message 270 | stepsForm.prototype._clearError = function() { 271 | classie.removeClass( this.error, 'show' ); 272 | } 273 | 274 | // add to global namespace 275 | window.stepsForm = stepsForm; 276 | 277 | })( window ); 278 | --------------------------------------------------------------------------------