National Identification Textbox (social security, social insurance, etc.)

As part of a new UI library, I have created a National Identification Textbox (social security, social insurance, etc.) in a manner that follows the guidelines found in the Webgrown Solutions UI Manifesto. The National Identification Textbox supports the following features:

The Demo

The Markup

Just a basic input element, with a normal class attribute and some custom data (data-*) attributes to allow feature customization. Once the Script stuff is in place on a website, any page can implement the National Identification Textbox by simply setting the input element's class attribute to "nationalIdentificationTextbox" and setting the desired optional custom data attributes.

That sounds like a DRY solution to me (see UI Manifesto).

 
<div class="form legendLook horizontalFormLayout">
    <div id="hdivFormTest1ConfirmationMessage" class="confirmationMessageWrapper hide"></div>
            
    <label for="txtUsSsn">U.S. Social Security Number:</label>
    <input type="text" id="txtUsSsn" class="nationalIdentificationTextbox" 
        required 
        placeholder="e.g. 123-12-1234"
        data-countryIsoCode="US"
        data-formGroup="formAuthenticate" 
        name="Value" />

    <label for="txtCaSin">Canada Social Insurance Number:</label>
    <input type="text" id="txtCaSin" class="nationalIdentificationTextbox" 
        required 
        placeholder="e.g. 123-123-123"
        data-countryIsoCode="CA"
        data-formGroup="formAuthenticate" 
        name="_" />  

    <label for="txtDoCn">Dominican Republic Cédula Number:</label>
    <input type="text" id="txtDoCn" class="nationalIdentificationTextbox" 
        required 
        placeholder="e.g. 123-1234567-1"
        data-countryIsoCode="DO"
        data-formGroup="formAuthenticate" 
        name="_" />     

    <div class="formButtonWrapper clearFix">
        <input type="submit" class="ajaxFormPost buttonStrong" value="Submit"
            data-formGroup="formAuthenticate" 
            data-serviceRequestUrl="..." 
            data-successFunction="successFormTest1"
            data-confirmActionMessage=""
            data-processingMessage=""
            data-overlayWindowWhileProcessing="true" />
    </div>
</div>

The Script

function formatNationalIdentificationNumber(value, countryIsoCode, event) {
    var requestingElement = $("#" + event.target.id);

    //8  = Backspace
    //9  = Tab (so will stay highlighted)
    //16 = Reverse Tab - Shift+Tab (so will stay highlighted)
    if (getKeycode(event) != 8 && getKeycode(event) != 9 && getKeycode(event) != 16) {
        var unformattedNin = makeNumeric(value, false, null, null);
        var formattedNin = "";
        var section1Count = 3;
        var section2Count = 2;
        var section3Count = 4;

        switch (countryIsoCode.toUpperCase()) {
            case "CA": //123-123-123
                section1Count = 3;
                section2Count = 3;
                section3Count = 3;
                break;
            case "DO": //123-1234567-1
                section1Count = 3;
                section2Count = 7;
                section3Count = 1;
                break;
            default: //123-12-1234 (US)
                section1Count = 3;
                section2Count = 2;
                section3Count = 4;
                break;
        }

        //Build and assign the "pattern", if not already there.
        if (!isAttrDefined(requestingElement.attr("pattern")) || requestingElement.attr("pattern").length == 0) {
            var patternValue = "/^((\\d{" + section1Count + "})-(\\d{" + section2Count + "})-(\\d{" + section3Count + "}))$/";
            requestingElement.attr("pattern", patternValue);
        }

        //Assign the "maxlength", if not already there.
        if (!isAttrDefined(requestingElement.attr("maxlength")) || requestingElement.attr("maxlength").length == 0) {
            requestingElement.attr("maxlength", (section1Count + section2Count + section3Count + 2));
        }

        //Section 1
        var charCount = 0;
        while ((charCount + 1) <= section1Count) { //the (+1 & <=) is needed to not get messed up with Packer 3.1 compression
            formattedNin += unformattedNin.charAt(charCount);
            charCount++;
        }

        if (unformattedNin.length >= section1Count) {
            //Add dash
            formattedNin += "-";

            //Section 2
            charCount = 0;
            while ((charCount + 1) <= section2Count) { //the (+1 & <=) is needed to not get messed up with Packer 3.1 compression
                formattedNin += unformattedNin.charAt(charCount + section1Count);
                charCount++;
            }

            if (unformattedNin.length >= (section1Count + section2Count)) {
                //Add dash
                formattedNin += "-";

                //Section 2
                charCount = 0;
                while ((charCount + 1) <= section3Count) { //the (+1 & <=) is needed to not get messed up with Packer 3.1 compression
                    formattedNin += unformattedNin.charAt(charCount + section1Count + section2Count);
                    charCount++;
                }
            }
        }

        return formattedNin;
    }
    else {
        return value;
    }
}

//Enable National Identification Textbox(es)
$(parentElementSelector + " input.nationalIdentificationTextbox").each(function () {
    $(this).keyup(function (event) {
        var countryIsoCode = ((!isAttrDefined($(this).attr("data-countryIsoCode")) || $(this).attr("data-countryIsoCode").length == 0) ? $("#hfGlobalCountryIsoCode").val() : $(this).attr("data-countryIsoCode"));
        $(this).val(formatNationalIdentificationNumber($(this).val(), countryIsoCode, event));
    });
});

The CSS

 
    Not applicable.