MediaWiki:DonationForm.js

From Donate
Revision as of 12:36, 12 September 2019 by MShaver (WMF) (talk | contribs)
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/** MediaWiki:DonationForm.js - loaded on all donation forms
 * TODO: lots of cleanup
 */

var donationForm = {};

donationForm.loadedTime = Date.now();
donationForm.extraData = {
    'vw' : window.innerWidth,
    'vh' : window.innerHeight
};

donationForm.maxUSD = 12000;
donationForm.minimums = {
    /* From https://github.com/wikimedia/wikimedia-fundraising-SmashPig/blob/master/PaymentData/ReferenceData/CurrencyRates.php */
    'ADF' : 5.65,
    'ADP' : 143,
    'AED' : 3.67,
    'AFA' : 73,
    'AFN' : 73,
    'ALL' : 109,
    'AMD' : 477,
    'ANG' : 1.79,
    'AOA' : 278,
    'AON' : 278,
    'ATS' : 12,
    'AUD' : 1.39,
    'AWG' : 1.78,
    'AZM' : 8486,
    'AZN' : 1.7,
    'BAM' : 1.69,
    'BBD' : 2,
    'BDT' : 83,
    'BEF' : 35,
    'BGL' : 1.69,
    'BGN' : 1.69,
    'BHD' : 0.38,
    'BIF' : 1748,
    'BMD' : 1,
    'BND' : 1.38,
    'BOB' : 6.8,
    'BSD' : 1,
    'BTN' : 72,
    'BWP' : 11,
    'BYR' : 21035,
    'BZD' : 1.98,
    'CAD' : 1.32,
    'CDF' : 1573,
    'CHF' : 0.98,
    'CNY' : 6.83,
    'CRC' : 572,
    'CUC' : 1,
    'CUP' : 25,
    'CVE' : 95,
    'CYP' : 0.51,
    'CZK' : 22,
    'DEM' : 1.69,
    'DJF' : 178,
    'DKK' : 6.42,
    'DOP' : 50,
    'DZD' : 118,
    'ECS' : 24094,
    'EEK' : 13,
    'EGP' : 18,
    'ESP' : 143,
    'ETB' : 27,
    'EUR' : 0.87,
    'FIM' : 5.12,
    'FJD' : 2.1,
    'FKP' : 0.78,
    'FRF' : 5.65,
    'GBP' : 0.78,
    'GEL' : 2.52,
    'GHC' : 47467,
    'GHS' : 4.75,
    'GIP' : 0.78,
    'GMD' : 48,
    'GNF' : 8983,
    'GRD' : 294,
    'GTQ' : 7.5,
    'GYD' : 204,
    'HKD' : 7.85,
    'HNL' : 24,
    'HRK' : 6.4,
    'HTG' : 68,
    'HUF' : 282,
    'IDR' : 14966,
    'IEP' : 0.68,
    'ILS' : 3.61,
    'IQD' : 1178,
    'IRR' : 42000,
    'ISK' : 109,
    'ITL' : 1669,
    'JMD' : 136,
    'JOD' : 0.71,
    'JPY' : 112,
    'KES' : 100,
    'KGS' : 69,
    'KHR' : 4025,
    'KMF' : 424,
    'KPW' : 135,
    'KRW' : 1120,
    'KWD' : 0.31,
    'KYD' : 0.84,
    'KZT' : 369,
    'LAK' : 8393,
    'LBP' : 1508,
    'LKR' : 162,
    'LRD' : 154,
    'LSL' : 15,
    'LTL' : 2.98,
    'LUF' : 35,
    'LVL' : 0.61,
    'LYD' : 1.37,
    'MAD' : 9.39,
    'MDL' : 17,
    'MGA' : 3311,
    'MGF' : 9150,
    'MKD' : 53,
    'MMK' : 1529,
    'MNT' : 2460,
    'MOP' : 8.08,
    'MRO' : 357,
    'MTL' : 0.37,
    'MUR' : 33,
    'MVR' : 15,
    'MWK' : 717,
    'MYR' : 4.15,
    'MZM' : 59754,
    'MZN' : 60,
    'NAD' : 15,
    'NGN' : 359,
    'NIO' : 32,
    'NLG' : 1.9,
    'NOK' : 8.4,
    'NPR' : 114,
    'NZD' : 1.52,
    'OMR' : 0.39,
    'PAB' : 1,
    'PEN' : 3.3,
    'PGK' : 3.26,
    'PHP' : 54,
    'PKR' : 123,
    'PLN' : 3.72,
    'PTE' : 173,
    'PYG' : 5763,
    'QAR' : 3.57,
    'ROL' : 39889,
    'RON' : 3.99,
    'RSD' : 101,
    'RUB' : 68,
    'RWF' : 862,
    'SAR' : 3.75,
    'SBD' : 7.6,
    'SCR' : 13,
    'SDD' : 1795,
    'SDG' : 18,
    'SDP' : 2261,
    'SEK' : 9.08,
    'SGD' : 1.38,
    'SHP' : 0.78,
    'SIT' : 207,
    'SKK' : 26,
    'SLL' : 8430,
    'SOS' : 542,
    'SRD' : 7.41,
    'SRG' : 7408,
    'STD' : 21070,
    'SVC' : 8.75,
    'SYP' : 215,
    'SZL' : 15,
    'THB' : 33,
    'TJS' : 9.36,
    'TMM' : 17050,
    'TMT' : 3.41,
    'TND' : 2.76,
    'TOP' : 2.29,
    'TRL' : 6629223,
    'TRY' : 6.63,
    'TTD' : 6.64,
    'TWD' : 31,
    'TZS' : 2281,
    'UAH' : 28,
    'UGX' : 3749,
    'USD' : 1,
    'UZS' : 7780,
    'VEB' : 6050841136,
    'VEF' : 6050841,
    'VND' : 23150,
    'VUV' : 111,
    'WST' : 2.64,
    'XAF' : 565,
    'XCD' : 2.7,
    'XOF' : 565,
    'XPF' : 103,
    'YER' : 250,
    'YUN' : 101,
    'ZAR' : 15,
    'ZMK' : 5176,
    'ZWD' : 373,
    /* Astropay currencies have higher minimums - 1.50 USD */
    'ARS' : 58.5,
    'BRL' : 6.23,
    'CLP' : 1035,
    'COP' : 4640,
    'MXN' : 28.5,
    'INR' : 108
};

/* Localize the amount errors. Call when initialising form. */
donationForm.localizeErrors = function() {
    var currency  = document.paypalcontribution.currency_code.value;
    var minAmount = donationForm.minimums[ currency ];

    $('.lp-error-smallamount').text( function( index, oldText ) {
        return oldText.replace( '$1', minAmount + ' ' + currency );
    });

    if ( currency === 'USD' ) {
        // we don't need to include the conversion
        $('.lp-error-bigamount').text( function( index, oldText ) {
            return oldText.replace( '($1 $2) ', '' )
                          .replace( '($1 $2) ', '' );
        });
    }

    $('.lp-error-bigamount').text( function( index, oldText ) {
        return oldText.replace( '$1', donationForm.maxUSD * minAmount )
                      .replace( '$2', currency )
                      .replace( '$3', 'benefactors@wikimedia.org' )
                      .replace( '$4', donationForm.maxUSD );
    });
};

function adjustHPC() {
    /* Adjust amounts based on highest previous contribution (hpc)
        or most recent contribution (mrc) parameter. Used for emails.
        TODO: split data out? */

    // Look for 'hpc' parameter, then 'mrc'. If neither, then bail out.
    var hpc = parseFloat( mw.util.getParamValue('hpc') );
    if( isNaN(hpc) ) {
        hpc = parseFloat( mw.util.getParamValue('mrc') );
        if( isNaN(hpc) ) {
            return;
        }
    }

    var hpcSet = mw.util.getParamValue('hpcSet');

    var currency = $("input[name='currency_code']").val();
    var language = mw.config.get('wgUserLanguage');

    var radioAmountsData = {
        'USD' : {
        	'default' : [
                [    0, [   2.75,   5,   10,   20,   25,   35,  50 ] ],
                [    5, [  5,   10,   15,   20,   35,  50,  100 ] ],
                [   10, [  10,   15,   20,   25,   35,  50,  100 ] ],
                [   15, [  15,   20,   25,   35,   50,  75,  100 ] ],
                [   20, [  20,   25,   35,   50,  75,  100,  150 ] ],
                [   25, [  25,   30,   40,   50,  75,  100,  150 ] ],
                [   35, [  35,   50,   75,  100,  200,  300,  500 ] ],
                [   75, [  75,   100,   150,  250,  500,  750,  1000 ] ],
                [  100, [  100,   150,  250,  500,  750,  1000, 2500 ] ],
                [  150, [  150,  200,  300,  500,  750,  1000, 2000 ] ],
                [  200, [ 200,  300,  500,  750,  1000,  2500, 5000 ] ],
                [  500, [ 500,  750,  1000,  2500, 5000, 7500, 10000 ] ],
                [ 1000, [ 1000, 2000, 3000, 4000, 5000, 7500, 10000 ] ]
            ],
            '2018control' : [
                [    0, [   5,   10,   20,   25,   35,   50,  100 ] ],
                [    5, [  10,   15,   20,   35,   50,  100,  150 ] ],
                [   10, [  15,   20,   25,   35,   50,  100,  150 ] ],
                [   15, [  20,   25,   35,   50,   75,  100,  250 ] ],
                [   20, [  25,   35,   50,   75,  100,  150,  250 ] ],
                [   25, [  30,   40,   50,   75,  100,  150,  250 ] ],
                [   35, [  25,   50,   75,  100,  200,  250,  300 ] ],
                [   75, [  25,   50,   75,  100,  200,  300,  500 ] ],
                [  100, [  25,   50,  100,  150,  250,  500, 1000 ] ],
                [  150, [  50,  100,  150,  200,  350,  500, 1000 ] ],
                [  200, [ 100,  150,  200,  300,  400,  500, 1000 ] ],
                [  500, [ 100,  250,  500,  750, 1000, 1500, 2000 ] ],
                [ 1000, [ 500, 1000, 2000, 2500, 3000, 4000, 5000 ] ]
            ],
            'LTLA' : [
                [    0, [   3,   10,   15,   20,   35,   50,  100 ] ],
                [    5, [   5,   10,   20,   35,   50,  100,  150 ] ],
                [   10, [  10,   20,   35,   50,   75,  100,  150 ] ],
                [   15, [  15,   25,   35,   50,   75,  100,  250 ] ],
                [   20, [  20,   30,   50,   75,  100,  150,  250 ] ],
                [   25, [  25,   35,   50,   75,  100,  150,  250 ] ],
                [   35, [  25,   50,   75,  100,  200,  250,  300 ] ],
                [   75, [  25,   50,   75,  100,  200,  300,  500 ] ],
                [  100, [  25,   50,  100,  150,  250,  500, 1000 ] ],
                [  150, [  50,  100,  150,  200,  350,  500, 1000 ] ],
                [  200, [ 100,  150,  200,  300,  400,  500, 1000 ] ],
                [  500, [ 100,  250,  500,  750, 1000, 1500, 2000 ] ],
                [ 1000, [ 500, 1000, 2000, 2500, 3000, 4000, 5000 ] ]
            ],
            'midtier2018' : [
                [    0, [    3,    5,   10,   20,   30,   50,   100 ] ],
                [    5, [    5,   10,   20,   35,   50,  100,   150 ] ],
                [   10, [   10,   15,   20,   35,   50,  100,   150 ] ],
                [   15, [   15,   20,   25,   35,   50,  100,   150 ] ],
                [   20, [   20,   25,   35,   50,   75,  100,   150 ] ],
                [   25, [   35,   50,   75,  100,  150,  250,   500 ] ],
                [   35, [   50,   75,  100,  150,  250,  350,   500 ] ],
                [   50, [   75,  100,  150,  200,  250,  350,   500 ] ],
                [   75, [  100,  150,  200,  300,  400,  500,  1000 ] ],
                [  100, [  150,  200,  250,  300,  400,  500,  1000 ] ],
                [  150, [  200,  250,  300,  400,  500, 1000,  2500 ] ],
                [  200, [  500,  750, 1000, 2000, 3500, 5000,  7500 ] ],
                [  500, [  750, 1000, 1500, 2500, 5000, 7500, 10000 ] ],
                [ 1000, [ 1000, 2000, 3000, 4000, 5000, 7500, 10000 ] ]
            ],
            'LT2018' : [
                [    0, [   5,   10,   20.18,   25,   35,   50,  100 ] ],
                [    5, [  10,   15,   20.18,   35,   50,  100,  150 ] ],
                [   10, [  15,   20.18,   25,   35,   50,  100,  150 ] ],
                [   15, [  20.18,   25,   35,   50,   75,  100,  250 ] ],
                [   20, [  25,   35,   50,   75,  100,  150,  250 ] ],
                [   25, [  30,   40,   50,   75,  100,  150,  250 ] ],
                [   35, [  25,   50,   75,  100,  200,  250,  300 ] ],
                [   75, [  25,   50,   75,  100,  200,  300,  500 ] ],
                [  100, [  25,   50,  100,  150,  250,  500, 1000 ] ],
                [  150, [  50,  100,  150,  200,  350,  500, 1000 ] ],
                [  200, [ 100,  150,  200,  300,  400,  500, 1000 ] ],
                [  500, [ 100,  250,  500,  750, 1000, 1500, 2018 ] ],
                [ 1000, [ 500, 1000, 2018, 2500, 3000, 4000, 5000 ] ]
            ]
        },
        'BRL' : [
            [    0, [   15,   25,   50,   75,   100,   150,   300 ] ],
            [    5, [   25,   35,   50,   75,   100,   200,   300 ] ],
            [   10, [   30,   50,   75,  100,   150,   300,   500 ] ],
            [   15, [   50,   75,  100,  150,   225,   300,   500 ] ],
            [   20, [   50,  100,  150,  225,   300,   400,   500 ] ],
            [   25, [   75,  125,  200,  250,   300,   400,   500 ] ],
            [   35, [  100,  150,  225,  300,   500,   750,  1000 ] ],
            [   75, [  100,  150,  225,  300,   500,  1000,  1500 ] ],
            [  100, [  100,  150,  300,  500,  1000,  1500,  3000 ] ],
            [  150, [  250,  500,  750, 1000,  1500,  3000,  5000 ] ],
            [  200, [  500, 1000, 2000, 3000,  4000,  5000, 10000 ] ],
            [  500, [ 1000, 2500, 5000, 7500, 10000, 12500, 15000 ] ],
            [ 1000, [ 1000, 2500, 5000, 7500, 10000, 12500, 15000 ] ]
        ],
        'JPY' : [
            [   0, [   500,  1000,  2000,  2500,   4000,   5000,  10000 ] ],
            [   5, [  1000,  1500,  2500,  4000,   5000,  10000,  15000 ] ],
            [  10, [  1500,  2000,  3000,  4000,   5000,  10000,  15000 ] ],
            [  15, [  2000,  2500,  3500,  5000,   7500,  10000,  25000 ] ],
            [  20, [  2500,  3500,  5000,  7500,  10000,  15000,  25000 ] ],
            [  25, [  3000,  4000,  5000,  7500,  10000,  15000,  25000 ] ],
            [  35, [  2500,  5000,  7500, 10000,  20000,  30000,  50000 ] ],
            [  75, [  2500,  5000,  7500, 10000,  20000,  50000, 100000 ] ],
            [ 100, [  5000, 10000, 15000, 20000,  35000,  50000, 100000 ] ],
            [ 500, [ 10000, 25000, 50000, 75000, 100000, 150000, 200000 ] ]
        ],
        'SEK' : [
            [   0, [ 20,  50, 100, 200, 300, 500, 1000 ] ],
            [   3, [ 30,  50, 100, 200, 300, 500, 1000 ] ],
            [   5, [ 50, 100, 150, 200, 300, 500, 1000 ] ],
            [  23, [ 50, 100, 200, 300, 500, 750, 1000 ] ]
        ]
    };
    radioAmountsData.AUD = radioAmountsData.USD;
    radioAmountsData.CAD = radioAmountsData.USD;
    radioAmountsData.GBP = radioAmountsData.USD;
    radioAmountsData.NZD = radioAmountsData.USD;
    radioAmountsData.EUR = radioAmountsData.USD;

    var appealAmountsData = {
        'USD' : [
            [   0, [   5,  10,  20 ] ],
            [  10, [  10,  20,  50 ] ],
            [  20, [  20,  30,  50 ] ],
            [  35, [  20,  30,  50 ] ],
            [  50, [  20,  50, 100 ] ],
            [  75, [  50,  75, 100 ] ],
            [ 100, [  75, 100, 150 ] ],
            [ 150, [  75, 100, 200 ] ],
            [ 200, [ 100, 200, 300 ] ]
        ],
        'JPY' : [
            [   0, [  300,   500,  1000 ] ],
            [   3, [  500,  1000,  1500 ] ],
            [   5, [ 1000,  1500,  2000 ] ],
            [  10, [ 1500,  2000,  5000 ] ],
            [  20, [ 2000,  3000,  5000 ] ],
            [  50, [ 2000,  5000, 10000 ] ],
            [ 100, [ 5000, 10000, 15000 ] ]
        ],
        'SEK' : [
            [   0, [  20,  50,  100 ] ],
            [   3, [  30,  50,  100 ] ],
            [   5, [  50, 100,  150 ] ],
            [  15, [ 100, 150,  200 ] ],
            [  23, [ 100, 200,  300 ] ],
            [  38, [ 100, 200,  500 ] ],
            [  75, [ 100, 500,  750 ] ],
            [ 112, [ 100, 500, 1000 ] ]
        ]
    };
    appealAmountsData.AUD = appealAmountsData.USD;
    appealAmountsData.CAD = appealAmountsData.USD;
    appealAmountsData.GBP = appealAmountsData.USD;
    appealAmountsData.NZD = appealAmountsData.USD;
    appealAmountsData.EUR = appealAmountsData.USD;

    var formats = {
        "USD" : "$\t",
        "EUR" : {
            "en" : "€\t",
            "cy" : "€\t",
            "ga" : "€\t",
            "mt" : "€\t",
            "nl" : "€ \t",
            "lv" : "€ \t",
            "tr" : "€ \t",
            "default" : "\t €"
        },
        "AUD" : "$\t",
        "CAD" : {
            "fr" : "\t $",
            "default" : "$\t"
        },
        "GBP" : "£\t",
        "NZD" : "$\t",
        "JPY" : "¥\t",
        "SEK" : "\t kr",
        "BRL" : "R$\t"
    };

    var format = formats[currency][language] || formats[currency]["default"] || formats[currency] || '\t';

    // Radio button amounts
    var radioAmounts = pickAmountArray( radioAmountsData, currency, hpc, hpcSet );
    if ( radioAmounts.length ) {
        // Change buttons
        for (var j = 0; j < radioAmounts.length; j++) {
            var $radio = $("#input_amount_" + j);
            var $label = $("label[for='input_amount_" + j + "']");
            $radio.val( radioAmounts[j] );
            $label.text( format.replace('\t', radioAmounts[j]) );
        }
    }

    // Appeal amounts
    var appealAmounts = pickAmountArray( appealAmountsData, currency, hpc, hpcSet );
    if ( appealAmounts.length ) {
        // Build string
        var appealAmountString = '';
        for( var k = 0; k < appealAmounts.length; k++ ) {
            appealAmountString += format.replace('\t', appealAmounts[k]) + ', ';
        }
        appealAmountString = appealAmountString.trim();

        $('.consider-amounts').html(appealAmountString);
    }

}

function pickAmountArray( data, currency, hpc, hpcSet ) {
    /**
     * Choose the amounts for radio buttons / appeal based on hpc
     * @param {Object} data
     * @param {String} currency
     * @param {Number} hpc
     * @param {String} hpcSet
     * @return {Array} Array of amounts (as numbers)
     */

    var set, amounts;

    if ( !(currency in data) ) {
        return [];
    }

    if ( $.isArray(data[currency]) ) {
        // No variant sets
        set = data[currency];
    } else {
        // We need to go deeper. Check the variants.
        if ( hpcSet in data[currency] ) {
            set = data[currency][hpcSet];
        } else {
            set = data[currency]['default'];
        }
    }

    // Find correct amount array for this hpc
    for (var i = 0; i < set.length; i++) {
        if ( set[i][0] > hpc ) {
            break;
        }
        amounts = set[i][1];
    }

    return amounts;

}

function preSelect() {
    /* Check for a 'preSelect' url parameter, and select that option.
       If there isn't an option, add it to the "Other" box and select that */
    var preSelectAmount = mw.util.getParamValue('preSelect');
    if ( preSelectAmount > 0 ) {
        $preSelectOption = $('input[name="amount"][value="' + preSelectAmount + '"]');
        if ( $preSelectOption.length ) {
            // Select existing input
            $preSelectOption.prop('checked', true);
        } else {
            $('#input_amount_other_box').val( preSelectAmount );
            $('#input_amount_other').prop('checked', true);
        }
        donationForm.updateFeeDisplay();
    }
}

function addCardTypesClass(country) {
    /**
     * Add card types class to credit card button, so we can show correct logos
     * Banner equivalent: https://meta.wikimedia.org/wiki/MediaWiki:FundraisingBanners/LocalizeJS-2017.js
     * @param {String} country ISO code
     */
    var cardTypes = {
        // Big 6
        'US' : 'vmad',
        'CA' : 'vma',
        'GB' : 'vmaj',
        'IE' : 'vmaj',
        'AU' : 'vmaj',
        'NZ' : 'vma',
        // Euro countries
        'AT' : 'vmaj',
        'BE' : 'vmaj',
        'ES' : 'vmaj',
        'FR' : 'CBvma', // Adyen
        'IT' : 'vmaj',
        'LU' : 'vmaj',
        'LV' : 'vma',
        'NL' : 'vmaj',
        'PT' : 'vmaj',
        'SK' : 'vmaj',
        // Others
        'DK' : 'vma',
        'HU' : 'vma',
        'IL' : 'vmad', // Adyen
        'JP' : 'vmaj',
        'MY' : 'vmaj',
        'NO' : 'vma',
        'PL' : 'vma',
        'RO' : 'vma',
        'SE' : 'vma',
        'UA' : 'vma', // Adyen
        'ZA' : 'vm'
    };
    if ( cardTypes[country] ) {
        $('.paymentmethod-cc').addClass('cctypes-' + cardTypes[country] );
    }
}

/* Form functions */
function clearOther(box) {
    document.getElementById("input_amount_other").checked = true;
    box.value = "";
}

function selectOther() {
    document.getElementById("input_amount_other").checked = true;
}

function selectAmount() {
    $('#input_amount_other_box').val('');
    $('input[name="amountGiven"]').val('');
}

/* -- Moved from Template:2012FR/Form-section/Processing/Default -- */
/**
 * Validate form, and if it looks good submit to payments
 * 
 * @param  {string} paymentMethod        - method e.g. 'cc', 'paypal'
 * @param  {string} paymentSubMethod     - submethod e.g. 'rtbt_ideal' (a submethod of 'rtbt')
 * @param  {string} skipAmountValidation - skip validating amount for PayPal forced to USD
 */
donationForm.redirectPayment = function( paymentMethod, paymentSubMethod, skipAmountValidation ) {

    var form = document.paypalcontribution; // we should really change this some day

    if ( donationForm.validate( skipAmountValidation ) ) {

        if (typeof paymentSubMethod == 'undefined') {
            paymentSubMethod = '';
        }
        var paymentsURL = 'https://payments.wikimedia.org/index.php/Special:GatewayFormChooser';

        form.action = paymentsURL;

        if (typeof paymentSubMethod == 'undefined') {
            paymentSubMethod = '';
        }

        // WorldPay override for cc
        if ( paymentMethod === 'cc-wp' ) {
            paymentMethod = 'cc';
            form.payment_method.value = 'cc';
            form.gateway.value = 'worldpay';
            form.ffname.value = 'worldpay';
        }

        // Adyen override for cc
        if ( paymentMethod === 'cc-adyen' ) {
            paymentMethod = 'cc';
            form.payment_method.value = 'cc';
            form.gateway.value = 'adyen';
            form.ffname.value = 'adyen';
        }
        
        // dLocal override for cc
        if ( paymentMethod === 'cc-dlocal' ) {
            paymentMethod = 'cc';
            form.payment_method.value = 'cc';
            form.gateway.value = 'astropay';
        }

        var frequency = $("input[name='frequency']:checked").val();
        if( frequency !== 'monthly' ){
            frequency = 'onetime';
            form.recurring.value = 'false';
        } else {
            form.recurring.value = 'true';
        }

        form.payment_method.value = paymentMethod;
        form.payment_submethod.value = paymentSubMethod;

        var full_dotted_payment_method = paymentMethod;
        if ( form.recurring.value == 'true' ) {
            full_dotted_payment_method = 'r' + full_dotted_payment_method;
        }
        if ( paymentSubMethod ) {
            full_dotted_payment_method = form.payment_method.value + '.' + paymentSubMethod;
        }

        // PTF - TODO: clean up form so we only use 'amount' and not 'amountGiven'
        if ( $('#ptf-checkbox').prop('checked') ) {
            var amount1 = donationForm.getAmount();
            document.getElementById('input_amount_other').checked = true;
            form.amountGiven.value = amount1 + donationForm.calculateFee( amount1 );
            donationForm.extraData.ptf = 1;
        }

        donationForm.extraData.time = Math.round( (Date.now() - donationForm.loadedTime)/1000 );

        form.utm_medium.value   = mw.util.getParamValue( 'utm_medium' );
        form.utm_campaign.value = mw.util.getParamValue( 'utm_campaign' );
        form.utm_source.value   = donationForm.buildUtmSource() + '.' + full_dotted_payment_method;
        form.utm_key.value      = donationForm.buildUtmKey( donationForm.extraData );

        form.method = 'GET';
        form.submit();
        
    } else {
        donationForm.extraData.validateError = 1; // Flag they had an error, even if fixed later
    }

    return false; // don't submit if called by a button
};

/**
 * Build a utm_source value, including the landing page info.
 *
 * Note this doesn't include payment method, that's added in redirectPayment method
 *
 * @return {string} utm_source
 */
donationForm.buildUtmSource = function() {

    var utm_source = mw.util.getParamValue( 'utm_source' ) + '.';

    var getParam = function( param, removeText, dflt ) {
        if ( mw.util.getParamValue( param ) ) {
            return mw.util.getParamValue( param ).replace( removeText, '' );
        } else {
            return dflt;
        }
    };

    /* The landing page info, separated by ~. This mostly exists for legacy reasons */
    utm_source += getParam( 'template'            , 'Lp-layout'            , 'default' ) + '~';
    utm_source += getParam( 'appeal-template'     , 'Appeal-template-'     , 'default' ) + '~';
    utm_source += getParam( 'appeal'              , 'Appeal-'              , 'default' ) + '~';
    utm_source += getParam( 'form-template'       , 'Form-template-'       , 'default' ) + '~';
    utm_source += getParam( 'form-countryspecific', 'Form-countryspecific-', 'control' );

    return utm_source;

};

/**
 * Build a string for utm_key from extra tracking data
 *
 * @param  {Object} data
 * @return {string} utm_key
 */
donationForm.buildUtmKey = function(data) {
    var dataArray = [];
    for (var key in data) {
        if (data.hasOwnProperty(key)) {
            dataArray.push( key + '_' + data[key] );
        }
    }
    return dataArray.join('.');
};

/* Return amount selected or input */
donationForm.getAmount = function() {
    var form = document.paypalcontribution;
    var amount = null;
    donationForm.extraData.otherAmt = 0;

    // If there are some amount radio buttons, then look for the checked one
    if ( form.amount ) {
        for ( var i = 0; i < form.amount.length; i++ ) {
            if ( form.amount[i].checked ) {
                amount = form.amount[i].value;
            }
        }
    }

    // Check the "other" amount box
    if ( form.input_amount_other_box.value !== '' ) {
        var otherAmount = form.input_amount_other_box.value;
        otherAmount = otherAmount.replace(/[,.](\d)$/, '\:$10');
        otherAmount = otherAmount.replace(/[,.](\d)(\d)$/, '\:$1$2');
        otherAmount = otherAmount.replace(/[\$£€¥,.]/g, '');
        otherAmount = otherAmount.replace(/:/, '.');
        form.amountGiven.value = otherAmount; // TODO: change this
        amount = otherAmount;
        donationForm.extraData.otherAmt = 1;
    }

    amount = parseFloat(amount);

    if ( isNaN(amount) ) {
        return 0;
    } else {
        return amount;
    }

};


/**
 * Validate the form.
 */
donationForm.validate = function( skipAmountValidation ) {

    var error = false;
    var form = document.paypalcontribution;

    // Reset all errors
    $('.lp-haserror').removeClass('lp-haserror');
    $('.lp-error').hide();

    if ( !skipAmountValidation && !donationForm.validateAmount() ) {
        error = true;
    }

    if ( form.opt_in ) {
        if ( $("input[name='opt_in']:checked").val() === undefined ) {
            $('#error-optin').show();
            error = true;
        } else {
            $('#error-optin').hide();
        }
    }

    return !error;
};

/**
 * Check if selected amount is valid i.e. a positive number, between minimum and maximum.
 * If not, show an error and return false.
 */
donationForm.validateAmount = function() {

    var amount = donationForm.getAmount();
    var currency = document.paypalcontribution.currency_code.value;
    var minAmount = donationForm.minimums[ currency ] || 1;

    if ( amount === null || isNaN(amount) || amount <= 0 || amount < minAmount ) {
        $('.amount-options').addClass('lp-haserror');
        $('.lp-error-bigamount').hide();
        $('.lp-error-smallamount').show();
        return false;
    } else if ( amount > donationForm.maxUSD * minAmount ) {
        $('.amount-options').addClass('lp-haserror');
        $('.lp-error-bigamount').show();
        return false;
    } else {
        $('.amount-options').removeClass('lp-haserror');
        $('.lp-error-smallamount, .lp-error-bigamount').hide();
        return true;
    }

};

donationForm.toggleMonthly = function(monthly) {
    if (monthly) {
        $('#form-wrapper').addClass('form-monthly');
    } else {
        $('#form-wrapper').removeClass('form-monthly');
    }
};

donationForm.updateFeeDisplay = function() {
    var feeAmount = donationForm.calculateFee( donationForm.getAmount() );
    if ( feeAmount % 1 !== 0 ) { // Not a whole number
        feeAmount = feeAmount.toFixed(2);
    } else {
        feeAmount = feeAmount.toString();
    }
    $('.ptf label span').text( feeAmount );
    $('.ptf').slideDown();
};

/**
 * Calculate approximate transaction fee on given amount
 * @param  {number} amount
 * @return {number}        Rounded to 2 decimal places
 */
donationForm.calculateFee = function( amount ) {

    // Minimum fee/PTF amounts. Default is 0.35.
    // Updated 2019-05-21 to approx 0.35 USD equivalent
    var feeMinimums = {
        'DKK' : 2,
        'HUF' : 100,
        'ILS' : 1.2,
        'MYR' : 1,
        'NOK' : 3,
        'PLN' : 1.35,
        'RON' : 1.5,
        'SEK' : 3,
        'UAH' : 10,
        'ZAR' : 5,
        // Latin America
        'BRL' : 1.5,
        'ARS' : 15,
        'CLP' : 250,
        'COP' : 1000,
        'PEN' : 1.2,
        'MXN' : 6,
        'UYU' : 12
    };

    var feeMultiplier = 0.04,
        feeMinimum = feeMinimums[document.paypalcontribution.currency_code.value] || 0.35,
        feeAmount = amount * feeMultiplier;

    if ( feeAmount < feeMinimum ) {
      feeAmount = feeMinimum;
    }
    return parseFloat( feeAmount.toFixed(2) );
};

/* End form functions */

$(document).ready(function() {

    mw.loader.using( ['mediawiki.util'] ).done( function() {

        // Block typing symbols in input field, otherwise Safari allows them and then chokes
        // https://phabricator.wikimedia.org/T118741, https://phabricator.wikimedia.org/T173431

        var amountOtherInput = document.getElementById('input_amount_other_box');
        if ( amountOtherInput ) {
            amountOtherInput.onkeypress = function(e) {
                // Allow special keys in Firefox
                if ((e.code == 'ArrowLeft') || (e.code == 'ArrowRight') ||
                    (e.code == 'ArrowUp') || (e.code == 'ArrowDown') ||
                    (e.code == 'Delete') || (e.code == 'Backspace')) {
                    return;
                }
                var chr = String.fromCharCode(e.which);
                if ("0123456789., ".indexOf(chr) === -1) {
                    return false;
                }
            };
        }

        // Validate amount and update fee when selected/entered
        $('.amount-options').on( 'input change', function() {
            donationForm.validateAmount();
            donationForm.updateFeeDisplay();
        });

        // Disable submitting form with Enter key
        $('form[name="paypalcontribution"]').on('keypress', function(e) {
            var code = ( e.keyCode ? e.keyCode : e.which );
            if ( code == 13 ) {
                e.preventDefault();
            }
        });

        // But allow Enter on buttons
        $('.payment-method-button').keyup(function(e) {
            if (event.keyCode === 13) {
                e.target.click();
            }
        });

        if ( document.paypalcontribution ) {
            document.paypalcontribution.utm_medium.value   = mw.util.getParamValue( 'utm_medium' );
            document.paypalcontribution.utm_campaign.value = mw.util.getParamValue( 'utm_campaign' );
            document.paypalcontribution.utm_key.value      = mw.util.getParamValue( 'utm_key' );

            // Strip protocol to stop firewall throwing fits
            document.paypalcontribution.referrer.value = document.referrer.replace(/https?:\/\//i, "");

            // hide frequency options in India, where we can only handle one-time donations
            if (document.paypalcontribution.country.value === 'IN') {
                $("#frequency_onetime").prop('checked', true);
                $(".frequency-options").hide();
                $("#cancel-monthly").hide();
            }

            addCardTypesClass(document.paypalcontribution.country.value);
        }

        // Links open in new tab
        $('.links-in-new-tab a').attr('target', '_blank');

        // Disable logo link
        $("#p-logo a").attr("href", "#");
        $("#p-logo a").attr("title", "");

        // These don't need to be tabbable on the landing page
        $('#searchInput, .mw-jump-link').attr('tabindex', '-1');

        $(".input_amount_other").click(function() {
            $("#input_amount_other_box").focus();
        });

        // Allow preselecting monthly
        if( mw.util.getParamValue('monthly') ) {
            $('#frequency_monthly').click();
        }

        // If the optin section has some javascript to run, do that
        if ( typeof initOptin === 'function' ) {
            initOptin();
        }

        try {
            adjustHPC();
            preSelect(); // Make sure to do this *after* other fiddling with values
            donationForm.localizeErrors();
        }
        finally {
            $('.ptf').appendTo('.amount-options');
            $('.optin-options').insertAfter('.amount-options');
            $('.consider-amounts').show();
            $('#actual-form').show();
            $('#actual-form-loading').hide();
        }

    });

});