Skip to content

Instantly share code, notes, and snippets.

@craigmdennis
Last active December 24, 2015 05:09
Show Gist options
  • Save craigmdennis/6748093 to your computer and use it in GitHub Desktop.
Save craigmdennis/6748093 to your computer and use it in GitHub Desktop.
Dynamically combine form fields for progressive enhancement. TODO - Add a function to add up the maxlengths and minlengths for the new input
<fieldset>
<legend class="section-title">Direct Debit Details</legend>
<div class="form-row">
<fieldset>
<legend>Sort Code</legend>
<div class="input-wrap input-type-text js-combine-trigger">
<label for="q13-1">First 2 digits of sort code</label>
<input type="text" id="q13-1" minlength="2" maxlength="2" pattern="[0-9]" required aria-required="true">
</div>
<div class="input-wrap input-type-text js-combine-trigger">
<label for="q13-2">Second 2 digits of sort code</label>
<input type="text" id="q13-2" minlength="2" maxlength="2" pattern="[0-9]" required aria-required="true">
</div>
<div class="input-wrap input-type-text js-combine-trigger">
<label for="q13-3">Last 2 digits of sort code</label>
<input type="text" id="q13-3" minlength="2" maxlength="2" pattern="[0-9]" required aria-required="true">
</div>
</fieldset>
</div>
</fieldset>
var combine;
(function ($, window, document, undefined) {
"use strict";
combine = {
wrapClass: ".js-combine",
triggerClass: ".js-combine-trigger",
dataPrefix: "data-input-type-",
successString: "combine-complete",
constructed: [],
init: function(){
var $wrap, $inputGroup;
$wrap = $(combine.wrapClass);
$inputGroup = $wrap.find(combine.triggerClass);
// Build all the things
return combine.construct();
},
getData: function(classes){
var expression, data, type;
// RegExp which data class is being used
expression = new RegExp(combine.dataPrefix + "[\\S]+");
// Return classes that match the data prefix
data = classes.match(expression);
if ( data ) {
type = data[0].replace(combine.dataPrefix,"");
}
// Return type without data prefix
return type;
},
funnelData: function($generatedInput, wrap) {
// Track the value and update the inputs that need to be by regex
},
convert: function(oldElement, newElement){
// Convert legends within input groups to labels for the new input
},
changeID: function($generatedInput){
var text;
text = $generatedInput.attr("id");
return $generatedInput.attr("id", text + "-combined");
},
calculate: function($generatedInput, attribute){
// Get the max of all inputs and add them up for the new input
},
placeholder: function($generatedInput, wrap){
var $meta, placeholderText;
// Get the .input-meta value and use it as the placeholder
$meta = $(wrap).find(".input-meta","legend");
if ( $meta.length ) {
// Get the placeholder text from the legend
placeholderText = $meta.text();
// Replace any brackets
placeholderText = placeholderText.replace("(", "").replace(")","");
$generatedInput.attr("placeholder", placeholderText);
}
return $generatedInput;
},
wrap: function($generatedInput) {
var $container, type;
// Add the correct class
type = $generatedInput.attr("type");
// Wrap it in the classes to match
$container = $("<div class='input-wrap input-type-" + type + " input-wrap-combined' />" ).html( $generatedInput );
// Add the element to the constructed array so we can keep track of it
combine.constructed.push($container[0]);
return $container;
},
construct: function(){
var $wrap, length, collectedAttributes, $generatedInput, $input;
$wrap = $(combine.wrapClass);
length = $wrap.length;
// Loop through all combine wrappers
for (var i = 0; i < length; i++) {
// Get the first input within the current wrap being checked
$input = $( $wrap[i] )
.find("input", combine.triggerClass)
.removeAttr("required") // Remove required as they are hidden
.removeAttr("aria-required")
.first();
// Clone the first input
$generatedInput = $input.clone();
// Allow overrides of the inputs before wrapping
$generatedInput = combine.rules( $generatedInput, $wrap[i] );
// Wrap the input
$generatedInput = combine.wrap( $generatedInput );
// Insert the new element into the page
combine.insert( $generatedInput, $wrap[i] );
// Add a class to the wrapper making it complete
$( $wrap[i] ).addClass(combine.successString);
// After the last loop has run, fire the callback
if ( i === length-1 ) {
combine.callback( );
}
}
},
updateType: function($generatedInput, wrap){
var $input, type;
// Get the type string from the class
type = combine.getData( $(wrap).attr("class") );
if ( type !== undefined ) {
$input = $generatedInput.attr("type", type);
}
return $generatedInput;
},
rules: function($generatedInput, wrap){
combine.updateType( $generatedInput, wrap );
combine.placeholder( $generatedInput, wrap );
combine.changeID( $generatedInput );
// combine.calculate( $generatedInput );
/* Custom Rules Can Go Here */
return $generatedInput;
},
insert: function($object, $location){
// Add the new input to the page
return $object.appendTo( $location );
},
callback: function($generatedInput, wrap){
console.log("Complete");
},
destroy: function(){
// Show the groups that were hidden at the start
$(combine.wrapClass).removeClass(combine.successString);
// Remove all new inputs and event handlers
return $(combine.constructed).remove();
},
};
})(jQuery, window, document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment