Currency Textbox

As part of a new UI library, I have created a Currency Textbox in a manner that follows the guidelines found in the Webgrown Solutions UI Manifesto. The Currency 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 CSS and Script stuff are in place on a website, any page can implement the Currency Textbox by simply setting the input element's class attribute to "currencyTextbox" 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="txtUsdCurrency">USD Amount:</label>
    <input type="text" id="txtUsdCurrency" class="currencyTextbox" 
        maxlength="14"
        required 
        placeholder="e.g. 123.45"
        data-currencyIsoCode="USD"
        data-formGroup="formAuthenticate" 
        name="singleItem" />

    <label for="txtEurCurrency">EUR Amount:</label>
    <input type="text" id="txtEurCurrency" class="currencyTextbox" 
        maxlength="14"
        required 
        placeholder="e.g. 123,45"
        data-currencyIsoCode="EUR"
        data-formGroup="formAuthenticate" 
        name="" />     

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

The Script

function formatCurrency(value, currencyIsoCode, 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 formattedCurrency = "";
        var decimalSeparator = ".";
        var decimalPlaceCount = 2;
        switch (currencyIsoCode.toUpperCase()) {
            case "EUR":
                decimalSeparator = ",";
                decimalPlaceCount = 2;
                break;
            default:
                decimalSeparator = ".";
                decimalPlaceCount = 2;
        }

        //Build and assign the "pattern", if not already there.
        if (!isAttrDefined(requestingElement.attr("pattern")) || requestingElement.attr("pattern").length == 0) {
            var patternValue;

            if (decimalSeparator.length > 0) {
                patternValue = "/^((\\d+\\" + decimalSeparator + "\\d{1," + decimalPlaceCount + "})|(\\d+))$/";
            }
            else {
                patternValue = "^\\d+$"; //number only
            }

            requestingElement.attr("pattern", patternValue);
        }

        //Assign a "maxlength", if not already there.
        if (!isAttrDefined(requestingElement.attr("maxlength")) || requestingElement.attr("maxlength").length == 0) {
            requestingElement.attr("maxlength", (20 + decimalPlaceCount)); //some huge amount, just to be safe
        }

        for (var i = 0; i <= value.length; i++) {
            var decimalIndex = -1;
            if (decimalSeparator.length > 0) {
                decimalIndex = formattedCurrency.indexOf(decimalSeparator);
            }
            if (((value.charAt(i) == decimalSeparator && decimalIndex < 0) || value.charAt(i) == "0" || value.charAt(i) == "1" || value.charAt(i) == "2" || value.charAt(i) == "3" || value.charAt(i) == "4" || value.charAt(i) == "5" || value.charAt(i) == "6" || value.charAt(i) == "7" || value.charAt(i) == "8" || value.charAt(i) == "9") && (decimalIndex < 0 || formattedCurrency.length < (decimalIndex + 1 + decimalPlaceCount))) {
                if (value.charAt(i) == decimalSeparator && formattedCurrency.length == 0) {
                    //Add zero before decimal, if the decimal is first valid char in value. 
                    formattedCurrency = 0;
                }
                formattedCurrency += value.charAt(i);
            }
        }

        return formattedCurrency;
    }
    else {
        return value;
    }
}

//Enable Currency Textbox(es)
$(parentElementSelector + " input.currencyTextbox").each(function () {
    $(this).keyup(function (event) {
        var currencyIsoCode = ((!isAttrDefined($(this).attr("data-currencyIsoCode")) || $(this).attr("data-currencyIsoCode").length == 0) ? $("#hfGlobalCurrencyIsoCode").val() : $(this).attr("data-currencyIsoCode"));
        $(this).val(formatCurrency($(this).val(), currencyIsoCode, event));
    });
});

The CSS

 
    Not applicable.