{"version":3,"file":"validate.js","names":[],"sources":["../resources/javascript/validate.js"],"sourcesContent":["/********************\n    example:\n\n    <form class-\"js-validation\">\n        <fieldset class=\"js-validate\" data-validate=\"required\">\n            <h2>Your details</h2>\n            <div class=\"field required\">\n                <input name=\"full_name\">\n            </div>\n        </fieldset>\n    </form>\n*********************/\n\nconst VALIDATE = {\n    okay: false,\n    $first: false,\n    debug: false,\n    _asyncRequests: {},\n    asyncIdCounter: 0,\n    loqateErrors: [],\n    scrollTimer: null,\n\n    checkable: function ($el) {\n        if (!$el.is(':visible')) {\n            return false;\n        }\n\n        if ($el.is(':disabled')) {\n            return false;\n        }\n\n        let collapsed = false;\n        const $parents = $el.parents('div');\n        $parents.each(function () {\n            if ($(this).data('collapsed') == 'Y') {\n                collapsed = true;\n            }\n        });\n\n        return !collapsed;\n    },\n\n    loqateFields: function ($form) {\n        const $els = $form.find('[data-validate^=\"loqate\"]');\n\n        let $list = $();\n        $els.each(function () {\n            const $el = $(this);\n\n            if (VALIDATE.checkable($el)) {\n                $list = $list.add($el);\n            }\n        });\n\n        return $list;\n    },\n\n    addError: function ($el, error) {\n        VALIDATE.okay = false;\n\n        if (!VALIDATE.$first) {\n            const $input = $el.find('input, select, textarea');\n            if ($input.length > 0) {\n                VALIDATE.$first = $input.eq(0);\n            } else {\n                VALIDATE.$first = $el;\n            }\n        }\n\n        const $field = $el.closest('.field');\n        $field.addClass('field--error');\n\n        const custom_error = $el.data('validationmsg');\n        if (custom_error !== undefined) {\n            error = custom_error;\n        }\n\n        if (error == undefined) {\n            error = '### is a required field';\n        }\n\n        if (error.indexOf('###') > -1) {\n            let label = $field.data('label');\n            if (label === undefined) {\n                const $label = $field.find('label:first');\n                label = $label.text().replace(/ ?\\* ?/, '');\n            }\n            error = error.replace('###', label);\n        }\n\n        let $message = $field.find('.error');\n        if ($message.length == 0) {\n            $message = $('<p class=\"error\"></p>').appendTo($field);\n        }\n\n        if (VALIDATE.debug) {\n            console.log('VALIDATE; error:', error);\n        }\n\n        $message.html(error);\n    },\n\n    cardNumber: function ($el) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        const cardnum = $el.val();\n        let result = true;\n        const re = /^(x){12}\\d{4}$/;\n\n        if (cardnum == '') {\n            result = false;\n            VALIDATE.addError($el);\n        } else {\n            if (!re.test(cardnum)) {\n                if (cardnum.length < 12 || cardnum.length > 19) {\n                    result = false;\n                }\n\n                if (result) {\n                    const v = '0123456789';\n                    let w = '';\n                    let x = null;\n                    let a = null;\n\n                    for (let i = 0; i < cardnum.length; i++) {\n                        x = cardnum.charAt(i);\n                        if (v.indexOf(x, 0) != -1) {\n                            w += x;\n                        }\n                    }\n\n                    let l = w.length;\n                    let p = l % 2;\n                    let c = 0;\n                    for (let i = 0; i < l; i++) {\n                        a = parseInt(w.charAt(i));\n                        if (i % 2 == p) {\n                            a = a * 2;\n                            if (a > 9) {\n                                a -= 9;\n                            }\n                        }\n                        c += a;\n                    }\n\n                    if (c % 10 !== 0) {\n                        result = false;\n                    }\n                }\n            }\n\n            if (!result) {\n                VALIDATE.addError($el, 'Please enter a valid ###');\n            }\n        }\n\n        if (result) {\n            let cardType = $('#payment_type').val();\n            if (cardType == 'delta') {\n                cardType = 'visa';\n            }\n\n            if (cardType != '') {\n                const cards = [\n                    {\n                        type: 'maestro',\n                        numbers: [\n                            '5018',\n                            '5020',\n                            '5038',\n                            '5612',\n                            '5893',\n                            '6304',\n                            '6759',\n                            '6761',\n                            '6762',\n                            '6763',\n                            '0604',\n                            '6390',\n                        ],\n                        length: 16,\n                    },\n                    {\n                        type: 'amex',\n                        numbers: ['34', '37'],\n                        length: 15,\n                    },\n                    {\n                        type: 'visa',\n                        numbers: ['4'],\n                        length: 16,\n                    },\n                    {\n                        type: 'mc',\n                        numbers: ['50', '51', '52', '53', '54', '55'],\n                        length: 16,\n                    },\n                ];\n\n                let matched = false;\n                let length = true;\n\n                $.each(cards, function (i, card) {\n                    if (card.type == cardType) {\n                        if (card.length != cardnum.length) {\n                            length = false;\n                        }\n                    }\n\n                    $.each(card.numbers, function (k, val) {\n                        if (cardnum.substring(0, val.length) == val) {\n                            matched = card.type;\n                        }\n                    });\n                });\n\n                if (\n                    $('body').hasClass('local') ||\n                    $('body').hasClass('staging')\n                ) {\n                    length = true; // visa test number is the wrong length!\n                }\n\n                if (matched != cardType) {\n                    VALIDATE.addError(\n                        $el,\n                        'Card type does not match card number'\n                    );\n                    result = false;\n                } else if (!length) {\n                    VALIDATE.addError($el, '### is the wrong length');\n                    result = false;\n                }\n            }\n        }\n\n        return result;\n    },\n\n    cardCV2: function ($el) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        const code = $el.val();\n        let result = false;\n        const re = /^\\d{3,4}$/;\n\n        if (code == '') {\n            VALIDATE.addError($el);\n        } else {\n            result = re.test(code);\n\n            if (!result) {\n                VALIDATE.addError($el, 'Please enter a valid ###');\n            }\n        }\n\n        return result;\n    },\n\n    cardStart: function ($el) {\n        const $mm = $el.find('#payment_start_month');\n        const $yy = $el.find('#payment_start_year');\n\n        if (!VALIDATE.checkable($mm)) {\n            return true;\n        }\n\n        let mm = $mm.val();\n        let yy = $yy.val();\n\n        if (mm == '') {\n            return true;\n        }\n\n        let result = true;\n        if (mm == '' || yy == '') {\n            result = false;\n            VALIDATE.addError($el);\n        } else {\n            mm -= 1; // month is zero based\n            yy = 2000 + Number(yy);\n            const start = new Date(yy, mm, 1);\n            const now = new Date();\n            if (start > now) {\n                result = false;\n                VALIDATE.addError($el, '### must be in the past');\n            }\n        }\n\n        return result;\n    },\n\n    cardExpiry: function ($el) {\n        const $mm = $el.find('#payment_expiry_month');\n        const $yy = $el.find('#payment_expiry_year');\n\n        if (!VALIDATE.checkable($mm)) {\n            return true;\n        }\n\n        let mm = $mm.val();\n        let yy = $yy.val();\n\n        let result = true;\n        if (mm == '' || yy == '') {\n            result = false;\n            VALIDATE.addError($el);\n        } else {\n            mm -= 1; // month is zero based\n            yy = 2000 + Number(yy);\n            const expiry = new Date(yy, mm + 1, 1);\n            const now = new Date();\n            if (expiry < now) {\n                result = false;\n                VALIDATE.addError($el, '### must be in the future');\n            }\n        }\n\n        return result;\n    },\n\n    card: function ($el) {\n        let result = true;\n\n        if (!VALIDATE.cardNumber($el.find('#payment_number'))) {\n            result = false;\n        }\n\n        if (!VALIDATE.cardCV2($el.find('#payment_cv2'))) {\n            result = false;\n        }\n\n        if (!VALIDATE.cardStart($el.find('#payment_start_wrap'))) {\n            result = false;\n        }\n\n        if (!VALIDATE.cardExpiry($el.find('#payment_expiry_wrap'))) {\n            result = false;\n        }\n\n        return result;\n    },\n\n    required: function ($el) {\n        if (!$el.hasClass('required')) {\n            $el = $el.find('.required');\n        }\n\n        let result = true;\n        $el.each(function () {\n            const $field = $(this);\n\n            if (VALIDATE.checkable($field)) {\n                const $input = $field.find('input, select, textarea');\n                const errMsg =\n                    $field.data('validationmsg') ||\n                    $input.data('validationmsg');\n                const disabled = $input.closest('.js-disabled').length > 0;\n                if ($input.length > 0 && !$input.is(':disabled') && !disabled) {\n                    if ($input.eq(0).is(':checkbox, :radio')) {\n                        if ($input.filter(':checked').length == 0) {\n                            VALIDATE.addError($field, errMsg);\n                            result = false;\n                        }\n                    } else if ($input.val().trim() == '') {\n                        VALIDATE.addError($input, errMsg);\n                        result = false;\n                    }\n                }\n            }\n        });\n\n        return result;\n    },\n\n    gtcheck: function ($el) {\n        if (!$el.hasClass('gtcheck')) {\n            $el = $el.find('.gtcheck');\n        }\n\n        let result = true;\n        $el.each(function () {\n            const $field = $(this);\n            const $input = $field.find('input, select, textarea');\n            const errMsg = $input.data('validationgtmsg');\n            const cmpField = $input.data('gtfield');\n            const $cmpField = $(cmpField);\n\n            if ($cmpField.length > 0) {\n                const $cmpVal = $cmpField.val();\n\n                if (\n                    isNaN($cmpVal) ||\n                    parseInt($input.val()) > parseInt($cmpVal)\n                ) {\n                    VALIDATE.addError($input, errMsg);\n                    result = false;\n                }\n            }\n        });\n\n        return result;\n    },\n\n    range: function ($el) {\n        if (!$el.hasClass('range')) {\n            $el = $el.find('.range');\n        }\n\n        let result = true;\n        $el.each(function () {\n            const $field = $(this);\n\n            const $input = $field.find('input');\n            const minimum = $field.data('minimum') || $input.data('minimum');\n            const maximum = $field.data('maximum') || $input.data('maximum');\n            const prefix = $field.data('prefix') || $input.data('prefix') || '';\n            const units = $field.data('units') || $input.data('units') || '';\n            let message =\n                $field.data('validationmsg') ||\n                $input.data('validationmsg') ||\n                false;\n            const checkboxes = $input.eq(0).is(':checkbox');\n            const type = $input.data('rangetype');\n\n            let t = 0;\n            if (minimum !== undefined) {\n                t += 1;\n            }\n\n            if (maximum !== undefined) {\n                t += 2;\n            }\n\n            if (!checkboxes && $input.val() == '') {\n                t = 0; // ignore blank text values\n            }\n\n            if (minimum !== undefined && minimum == maximum) {\n                t = 4;\n            }\n\n            if (t > 0) {\n                if (!message) {\n                    const ranges = [\n                        'no limits',\n                        'at least {minimum}',\n                        'no more than {maximum}',\n                        'between {minimum} and {maximum}',\n                        'exactly {minimum}',\n                    ];\n\n                    if (checkboxes) {\n                        message =\n                            'Please select ' + ranges[t] + ' items for ###';\n                    } else {\n                        if (minimum == 1 && maximum === undefined) {\n                            message = 'Please enter a value for ###';\n                        } else {\n                            message =\n                                'Please enter a value which is ' +\n                                ranges[t] +\n                                ' for ###';\n                        }\n                    }\n                }\n\n                const disabled = $input.closest('.js-disabled').length > 0;\n                if (\n                    $input.length > 0 &&\n                    VALIDATE.checkable($input) &&\n                    !disabled\n                ) {\n                    let count;\n\n                    if (checkboxes) {\n                        count = $input.filter(':checked').length;\n                    } else {\n                        if (type == 'length') {\n                            count = $input.val().length;\n                        } else {\n                            count = $input.val();\n                        }\n                    }\n\n                    const params = {\n                        minimum: prefix + parseInt(minimum) + units,\n                        maximum: prefix + parseInt(maximum) + units,\n                    };\n\n                    message = message._moustache(params);\n\n                    if (type != 'length' || count > 0) {\n                        // don't do a range check if its empty, leave that to required\n                        if (\n                            (minimum != undefined &&\n                                parseFloat(count) < parseFloat(minimum)) ||\n                            (maximum != undefined &&\n                                parseFloat(count) > parseFloat(maximum))\n                        ) {\n                            VALIDATE.addError($input, message);\n                            result = false;\n                        }\n                    }\n                }\n            }\n        });\n\n        return result;\n    },\n\n    email: function ($el) {\n        // Only needed for browsers with no HTML5 validation\n        if ($el.prop('type') != 'EMAIL') {\n            $el = $el.find('[data-type=\"email\"]');\n        }\n\n        let result = true;\n        $el.each(function () {\n            const $input = $(this);\n            const v = $input.val();\n            let okay = true;\n\n            if (v === '') {\n                okay = false;\n            } else if (!$input.is(':disabled') && v != '') {\n                if (\n                    v.match(\n                        /^[\\.\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~0-9A-Za-z]+\\@[A-Za-z0-9\\-\\_\\.]+\\.[A-Za-z]{2,4}$/\n                    ) == null\n                ) {\n                    okay = false;\n                }\n            }\n\n            if (!okay) {\n                VALIDATE.addError($input, '### requires a valid email address');\n                result = false;\n            } else {\n                const method = VALIDATE[$el.data('validate')];\n\n                if (method) {\n                    method($input);\n                }\n            }\n        });\n\n        return result;\n    },\n\n    phone: function ($el) {\n        // Only needed for browsers with no HTML5 validation\n        if ($el.prop('type') != 'TEL') {\n            $el = $el.find('[data-type=\"tel\"]');\n        }\n\n        $el.each(function () {\n            const $input = $(this);\n            const v = $input.val();\n            let okay = true;\n\n            if (v === '') {\n                okay = false;\n            } else if (!$input.is(':disabled') && v != '') {\n                if (v.match(/^[0-9 \\+]+$/) == null) {\n                    okay = false;\n                }\n            }\n\n            if (!okay) {\n                VALIDATE.addError(\n                    $input,\n                    '### requires a valid telephone number'\n                );\n                return false;\n            } else {\n                const method = VALIDATE[$el.data('validate')];\n\n                if (method) {\n                    method($input);\n                }\n            }\n        });\n\n        return true;\n    },\n\n    mobile: function ($el) {\n        // Only needed for browsers with no HTML5 validation\n        if ($el.prop('type') != 'TEL') {\n            $el = $el.find('[type=\"tel\"]');\n        }\n\n        $el.each(function () {\n            const $input = $(this);\n            const v = $input.val().replace(' ', '');\n\n            if (v == '') {\n                return true;\n            }\n\n            if (!$input.is(':disabled') && v != '') {\n                if (v.match(/^07/) == null) {\n                    VALIDATE.addError($input, '### should begin with 07');\n                    return false;\n                }\n\n                if (v.match(/^[0-9]{11}$/) == null) {\n                    VALIDATE.addError($input, '### should contain 11 digits');\n                    return false;\n                }\n            }\n        });\n\n        return true;\n    },\n\n    address: function ($el) {\n        let result = true;\n\n        $el.find('.js-address_fields').each(function () {\n            const $address = $(this);\n            if (VALIDATE.checkable($address)) {\n                const $lookup = $el.find('.js-lookup_fields');\n                const $manual = $el.find('.js-manual_fields');\n                let check_manual = true;\n\n                // if lookup is open\n                if ($lookup.prop('data-expanded') == 'Y') {\n                    if (!VALIDATE.required($lookup)) {\n                        // and they haven't entered a postcode\n                        result = false;\n                        check_manual = false;\n                    } else {\n                        // open up manual and check fields\n                        $lookup._collapse();\n                        $manual._expand();\n                    }\n                }\n\n                if (check_manual) {\n                    if (!VALIDATE.required($manual)) {\n                        result = false;\n                    }\n                }\n\n                const $lines = $address.find('input[name*=\"line\"]');\n\n                $lines.each(function () {\n                    const $el = $(this);\n                    if ($el.val().length > 30) {\n                        VALIDATE.addError(\n                            $el,\n                            'Maximum length for ### is 30 characters'\n                        );\n                    }\n                });\n\n                if (\n                    $lines.eq(0).val() != '' &&\n                    $lines.eq(0).val() == $lines.eq(1).val()\n                ) {\n                    VALIDATE.addError(\n                        $lines.eq(1),\n                        'Line 1 and 2 should not be the same'\n                    );\n                }\n            }\n        });\n\n        return result;\n    },\n\n    postcode: function ($el) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        if ($el.data('type') != 'postcode') {\n            $el = $el.find('[data-type=\"postcode\"]');\n        }\n\n        let okay = true;\n        $el.each(function () {\n            const $input = $(this);\n\n            const method = VALIDATE[$input.data('validate')];\n            if (method) {\n                if (!method($input)) {\n                    okay = false;\n                }\n            }\n        });\n\n        return okay;\n    },\n\n    uk: function ($el) {\n        const $country = $el.find('.field__country');\n        const country = $country.val();\n        if ('GB' !== country) {\n            VALIDATE.addError($country, $el.data('uk-error'));\n            return false;\n        }\n\n        return true;\n    },\n\n    loqateEmail: function ($el, trigger) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        const url =\n            'https://api.addressy.com/EmailValidation/Interactive/Validate/v2.00/json3.ws';\n        const value = $el.prop('value');\n\n        const data = {\n            Key: $el.data('loqate-api-key'),\n            Email: value,\n        };\n\n        VALIDATE.loqateValidate(\n            $el,\n            value,\n            trigger,\n            url,\n            data,\n            'Email',\n            function (result) {\n                if (VALIDATE.debug) {\n                    console.log('VALIDATE; result:', result);\n                }\n\n                // If the result is malformed, assume that the value is valid.\n                if (!result.Items) {\n                    return true;\n                }\n\n                return result.Items[0].ResponseCode !== 'Invalid';\n            }\n        );\n    },\n\n    loqateTelephone: function ($el, trigger) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        const url =\n            'https://api.addressy.com/PhoneNumberValidation/Interactive/Validate/v2.2/json3.ws';\n        const value = $el.prop('value');\n\n        const data = {\n            Key: $el.data('loqate-api-key'),\n            Phone: value,\n        };\n\n        if (value.trim().slice(0, 1) !== '+') {\n            data.Country = 'GB';\n        }\n\n        VALIDATE.loqateValidate(\n            $el,\n            value,\n            trigger,\n            url,\n            data,\n            'Telephone',\n            function (result) {\n                if (VALIDATE.debug) {\n                    console.log('VALIDATE; result:', result);\n                }\n\n                // If the result is malformed, assume that the value is valid.\n                if (!result.Items) {\n                    return true;\n                }\n\n                return result.Items[0].IsValid !== 'No';\n            }\n        );\n    },\n\n    loqatePostcode: function ($el, trigger) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        const url =\n            'https://api.addressy.com/Cleansing/International/Batch/v1.00/json4.ws';\n\n        const $form = $el.closest('form');\n        let prefix = $el.data('prefix');\n\n        if (!prefix) {\n            const name = $el.prop('name');\n            prefix = name.slice(0, name.indexOf('postcode'));\n        }\n\n        const address = {};\n        const raw = $form.serializeArray();\n        for (let i in raw) {\n            const pair = raw[i];\n            const key = pair.name.replace(prefix, '').replace(']', '');\n\n            address[key] = pair.value;\n        }\n\n        const data = {\n            Key: $el.data('loqate-api-key'),\n            Geocode: false,\n            Addresses: [\n                {\n                    Address1: address.line_1,\n                    Address2: address.line_2,\n                    Address3: address.town,\n                    Address4: address.county,\n                    PostalCode: address.postcode,\n                    Country: address.country,\n                },\n            ],\n        };\n\n        VALIDATE.loqateValidate(\n            $el,\n            address.postcode,\n            trigger,\n            url,\n            data,\n            'Postcode',\n            function (result) {\n                if (VALIDATE.debug) {\n                    console.log('VALIDATE; result:', result);\n                }\n\n                if (result[0].Matches.length == 0) {\n                    return false;\n                }\n\n                const entered = address.postcode\n                    .toString()\n                    .toUpperCase()\n                    .replace(' ', '');\n\n                let suggested = '';\n                if (result[0].Matches[0].PostalCode) {\n                    suggested = result[0].Matches[0].PostalCode.toString()\n                        .toUpperCase()\n                        .replace(' ', '');\n                    $el.data('suggested', suggested);\n                }\n\n                if (VALIDATE.debug) {\n                    console.log(\n                        'VALIDATE; suggested vs entered:',\n                        suggested,\n                        entered\n                    );\n                }\n\n                return suggested == entered;\n            }\n        );\n    },\n\n    loqateError: function (mode, $el) {\n        let name = $el.data('loqate-error');\n        if (name === undefined) {\n            name = '#loqate-' + mode.toLowerCase() + '-template';\n        }\n\n        const data = {};\n        data[mode.toLowerCase()] = $el.data('suggested');\n\n        const $template = $(name);\n        const template = Handlebars.compile($template[0].outerHTML);\n        const message = $(template(data)).html();\n\n        VALIDATE.loqateErrors.push(mode);\n\n        VALIDATE.addError($el, message);\n\n        clearTimeout(VALIDATE.scrollTimer);\n        VALIDATE.scrollTimer = setTimeout(function () {\n            NAVIGATION.scrollTo(NAVIGATION.scrollPos($el) - 100, function () {\n                $el.focus();\n            });\n        }, 100);\n    },\n\n    loqateValidate: function (\n        $el,\n        value,\n        trigger,\n        url,\n        data,\n        mode,\n        checkResult\n    ) {\n        if (!VALIDATE.checkable($el)) {\n            return true;\n        }\n\n        // Don't attempt to validate the same value again.\n        if (value !== null && $el.data('loqate-validation-value') === value) {\n            if ($el.attr('loqate-validated')) {\n                return;\n            }\n\n            if ($el.data('loqate-validation-result') !== 'invalid') {\n                $el.closest('.field').removeClass('field--error');\n                return;\n            }\n\n            // Make sure the error message is still being displayed and fail\n            // validation.\n\n            VALIDATE.loqateError(mode, $el);\n\n            return;\n        }\n\n        $el.addClass('js-busy');\n\n        // Abort any previous requests for this field.\n        let previousRequest = VALIDATE.getAsyncRequestForField($el);\n        if (previousRequest) {\n            previousRequest.abort();\n            previousRequest = null;\n        }\n\n        const params = {\n            url: url,\n            data: data,\n            type: 'post',\n            dataType: 'json',\n        };\n\n        if (mode == 'Postcode') {\n            params.contentType = 'application/json; charset=utf-8';\n            params.data = JSON.stringify(params.data);\n        }\n\n        let valid = true;\n        const $ajax = $.ajax(params);\n\n        $ajax.done(function (result, status, xhr) {\n            valid = checkResult(result);\n        });\n\n        $ajax.always(function () {\n            $el.attr('loqate-validated', valid);\n            $el.attr('data-loqate-is-validated', valid);\n            $el.removeClass('js-busy');\n\n            VALIDATE.unregisterAsyncRequest($el, $ajax);\n\n            if (value !== null) {\n                $el.data('loqate-validation-value', value);\n                $el.data(\n                    'loqate-validation-result',\n                    valid ? 'valid' : 'invalid'\n                );\n            }\n\n            if (!valid) {\n                VALIDATE.loqateError(mode, $el);\n            }\n        });\n\n        VALIDATE.registerAsyncRequest($el, $ajax);\n    },\n\n    loqateReset: function ($el, useSuggested) {\n        const $field = $el.closest('.field');\n        const $input = $field.find('input');\n        const index = VALIDATE.loqateErrors.indexOf($el.data('mode'));\n\n        VALIDATE.loqateErrors.splice(index, 1);\n\n        if ($input.length > 0) {\n            $field.removeClass('field--error');\n\n            $input.attr('loqate-validated', true);\n            $input.attr('data-loqate-is-validated', true);\n\n            if (useSuggested) {\n                $input.val($input.data('suggested'));\n            }\n        }\n    },\n\n    asyncId: function ($el) {\n        let id = $el.data('loaf-validate-id');\n        if (!id) {\n            id = VALIDATE.asyncIdCounter;\n            VALIDATE.asyncIdCounter++;\n            $el.data('loaf-validate-id', id);\n        }\n        return id;\n    },\n\n    registerAsyncRequest: function ($el, request) {\n        const formAsyncId = VALIDATE.asyncId($el.closest('form'));\n        const fieldAsyncId = VALIDATE.asyncId($el);\n\n        if (!(formAsyncId in VALIDATE._asyncRequests)) {\n            VALIDATE._asyncRequests[formAsyncId] = {};\n        }\n\n        VALIDATE._asyncRequests[formAsyncId][fieldAsyncId] = request;\n    },\n\n    unregisterAsyncRequest: function ($el, request) {\n        const formAsyncId = VALIDATE.asyncId($el.closest('form'));\n        const fieldAsyncId = VALIDATE.asyncId($el);\n\n        if (!(formAsyncId in VALIDATE._asyncRequests)) {\n            return;\n        }\n\n        if (!(fieldAsyncId in VALIDATE._asyncRequests[formAsyncId])) {\n            return;\n        }\n\n        if (VALIDATE._asyncRequests[formAsyncId][fieldAsyncId] === request) {\n            delete VALIDATE._asyncRequests[formAsyncId][fieldAsyncId];\n        }\n    },\n\n    getAsyncRequestForField: function ($el) {\n        const formAsyncId = VALIDATE.asyncId($el.closest('form'));\n        if (!(formAsyncId in VALIDATE._asyncRequests)) {\n            return null;\n        }\n\n        const fieldAsyncId = VALIDATE.asyncId($el);\n        if (!(fieldAsyncId in VALIDATE._asyncRequests[formAsyncId])) {\n            return null;\n        }\n        return VALIDATE._asyncRequests[formAsyncId][fieldAsyncId];\n    },\n\n    isAyncRequestPendingForForm: function ($form) {\n        const formAsyncId = VALIDATE.asyncId($form);\n\n        const requests = VALIDATE._asyncRequests[formAsyncId];\n        if (requests == undefined) {\n            return false;\n        }\n\n        return !$.isEmptyObject(requests);\n    },\n\n    validate: function ($el, trigger) {\n        const validators = $el.data('validate').split(/, ?/);\n        for (let v in validators) {\n            const method = VALIDATE[validators[v]];\n            if (method != undefined) {\n                method($el, trigger);\n            }\n        }\n    },\n\n    updateCheck: function ($el) {\n        clearTimeout($el.data('validate-timer'));\n        $el.data(\n            'validate-timer',\n            setTimeout(function () {\n                VALIDATE.validate($el);\n            }, 800)\n        );\n    },\n\n    check: function ($form, scroll) {\n        if (VALIDATE.isAyncRequestPendingForForm($form)) {\n            return false;\n        }\n\n        const $loqateFields = VALIDATE.loqateFields($form).filter(\n            '[data-loqate-is-validated=\"false\"]'\n        );\n        if ($loqateFields.length > 0) {\n            return false;\n        }\n\n        VALIDATE.okay = true;\n        VALIDATE.$first = false;\n\n        if (scroll == undefined) {\n            scroll = true;\n        }\n\n        $form.find('.field--error').removeClass('field--error');\n\n        $form.find('.js-validate').each(function () {\n            VALIDATE.validate($(this));\n\n            if (scroll && VALIDATE.$first) {\n                clearTimeout(VALIDATE.scrollTimer);\n                VALIDATE.scrollTimer = setTimeout(function () {\n                    const pos = NAVIGATION.scrollPos(VALIDATE.$first) - 100;\n                    NAVIGATION.scrollTo(pos, function () {\n                        VALIDATE.$first.focus();\n                    });\n                }, 0);\n            }\n        });\n\n        return VALIDATE.okay;\n    },\n\n    checkPostcode: function ($el) {\n        // this method is intended to be called standalone, rather than via check\n        const postcode = $el.val();\n        const $field = $el.closest('.field');\n\n        $field.removeClass('field--error');\n        $el.data('valid', true);\n\n        if (postcode !== '') {\n            $el.addClass('js-busy');\n            const $ajax = $.ajax({\n                type: 'get',\n                url: '/basket/postcode',\n                data: { action: 'postcode', value: postcode },\n                dataType: 'json',\n            });\n\n            $ajax.done(function (data) {\n                if (data.result) {\n                    return true;\n                } else {\n                    $el.data('valid', false);\n                    VALIDATE.addError($el, 'Please enter a valid postcode');\n                    return false;\n                }\n            });\n\n            $ajax.always(function (data) {\n                $el.removeClass('js-busy');\n            });\n        } else {\n            VALIDATE.addError($el, 'Please enter a valid postcode');\n            $el.data('valid', false);\n            return false;\n        }\n    },\n\n    custom: function ($el) {\n        const methodName = $el.data('method');\n\n        let method;\n        if (methodName.indexOf('.') > -1) {\n            const parts = methodName.split('.');\n            let ns = parts[0];\n            let mn = parts[1];\n            method = window[ns][mn];\n        } else {\n            method = window[methodName];\n        }\n\n        return method();\n    },\n\n    loadHandlers: function (scope) {\n        const $scope = $(scope);\n\n        $(document).on('click', '.js-override-loqate', function (e) {\n            e.preventDefault();\n\n            const $button = $(e.target);\n            VALIDATE.loqateReset($button, false);\n        });\n\n        $(document).on('click', '.js-use-loqate', function (e) {\n            e.preventDefault();\n\n            const $button = $(this);\n            VALIDATE.loqateReset($button, true);\n        });\n\n        $scope.find('.js-validation').each(function () {\n            const $form = $(this);\n\n            $form\n                .find('input, textarea, select')\n                .on('change input _update', function (e) {\n                    const $input = $(this);\n\n                    $input\n                        .closest('.field')\n                        .removeClass('field--error')\n                        .removeAttr('loqate-validated');\n                    $input.closest('.field').find('.error').remove();\n\n                    if (\n                        e.type == 'change' &&\n                        $input.data('validate') !== undefined\n                    ) {\n                        VALIDATE.validate($input);\n                    }\n                });\n\n            $form.find('.js-validate').each(function () {\n                const $el = $(this);\n\n                if ($el.data('update-check') !== undefined) {\n                    $el.find('input, textarea, select').on(\n                        'input',\n                        function () {\n                            VALIDATE.updateCheck($el);\n                        }\n                    );\n                }\n            });\n\n            $form.on('submit', function (e) {\n                $(this).prop('validateLoqateOnChange', false);\n\n                let okay = VALIDATE.check($form);\n                if (okay) {\n                    const $loqateFields = VALIDATE.loqateFields($form).not(\n                        '[data-loqate-is-validated=\"true\"]'\n                    );\n                    $loqateFields.each(function () {\n                        var $el = $(this);\n\n                        if (VALIDATE.checkable($el)) {\n                            okay = false;\n                        }\n                    });\n                }\n\n                if (!okay) {\n                    e.preventDefault();\n                    e.stopImmediatePropagation();\n                    $form.trigger('invalid');\n\n                    setTimeout(function () {\n                        $form.find('.js-submit_button').trigger('_reset');\n                    }, 20);\n\n                    return false;\n                }\n            });\n\n            $form.on('invalid', function (e) {\n                // HTML5 validation failed\n                setTimeout(function () {\n                    $form.find('.js-submit_button').trigger('_reset');\n                }, 20);\n            });\n        });\n\n        $scope.find('.js-checkout-validation').each(function () {\n            const $form = $(this);\n\n            $form\n                .find('input, textarea, select')\n                .on('change _update', function () {\n                    $(this).closest('.field').removeClass('field--error');\n\n                    if ($(this).data('validate')) {\n                        if ($(this).data('validate').indexOf('loqate') > -1) {\n                            const mode = $(this)\n                                .data('validate')\n                                .replace('loqate', '');\n                            const index = VALIDATE.loqateErrors.indexOf(mode);\n\n                            if (index > -1) {\n                                VALIDATE.loqateErrors.splice(index, 1);\n                            }\n                        }\n                    }\n                });\n        });\n\n        $scope.find('input').on('invalid', function () {\n            // create our own bubble for HTML5 validation\n            $(this).closest('form').trigger('invalid');\n        });\n    },\n};\n\n$(function () {\n    // eg $('#simplemodal-container').trigger('_loadHandlers');\n    $(document).on('_loadHandlers', function (e) {\n        VALIDATE.loadHandlers(e.target);\n    });\n\n    VALIDATE.loadHandlers(document);\n});\n"],"mappings":"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"}