Template talk:2011FR/lp-form-extrainfo

Please add all comments about this template and the explanation of this template to the bottom of this page so that we can keep the explanation clean

CSS
This first section contains all the new CSS styling info. Once the layout is set all this should be moved to lp-layout.  /* All this css must be moved to "lp-layout" once it is set in stone */

JavaScript tool functions
This block of JS contains utility functions such as grabbing info from the URL and converting arrays to objects.  //-new jquery junk---

function spaceAmts{ var max_width = $('#radio-box').width; var amts = $('.div_amount_radio'); console.log( "Max width: " + max_width ); console.log( "Num amounts: " + amts.length ); var linewidth = 0 for (i=0; i max_width){ $(amts[i]).css('clear','left'); linewidth = $(amts[i]).width; }       else{ linewidth += $(amts[i]).width; }   } }

//--- Utility Functions--- function arrayToObject(variable) //This is a helper function: converts an array to object literal with keys // then it can be used for quick "in" tests { var obj = {};

for (var i=0; i<variable.length; i++) {   obj[variable[i]]=''; }

return obj; }

function getQuerystring( key ) // This function to parse the information passed by central notice { key = key.replace( /[\[]/, '\\\[' ).replace( /[\]]/, '\\\]' ); var regex = new RegExp( '[\\?&]' + key + '=([a-zA-Z0-9\_\-]*)' ); var qs = regex.exec( window.location.search ); return qs == null ? '' : qs[1]; }

function getLandingPage //This function returns the path to the landing page. { var path = "  ";

if ( path == "default" ) {   pathArray = window.location.pathname.split( '/' ); return pathArray[2]; } else return path; }

function checkZip(elem) //This function checks zip codes and makes sure they are all numbers { var numberCharacter = /^[0-9]+$/;

if(elem.value.match(numberCharacter)) return true; else return false; }

function checkEmail(elem) //This function checks emails makes sure they are formatted in a generally valid way { var emailFormat = /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-Z0-9\.]+$/;

if(elem.value.match(emailFormat)) return true; else return false; }

function flagError(elem) //This function changes the border and text of "elem" to bright red. { elem.style.borderColor = '#ff0000'; elem.style.color = '#ff0000'; }

function recolorThis(elem) //This function changes the border and text of "elem" to grey and black respectively. { elem.style.color = "#000000"; elem.style.borderColor = '#C0C0C0'; }

function clearThis(elem,initialString) //This function changes the border and text of "elem" to grey and black respectively //and sets the value of "elem" to "initialString" { elem.style.color = "#000000"; elem.style.borderColor = '#C0C0C0'

if(elem.value == initialString) elem.value = ""; }

function resetThis(elem,resetString) //This function changes the border and text of "elem" to greys //and sets the value of "elem" to "resetString" { if(elem.value == "") {   elem.style.color = "#999999"; elem.value = resetString; } elem.style.borderColor = '#C0C0C0'; }

Independent arrays
These arrays are set for all forms and when creating a clone form these should not change.

//--Template Independent Arrays--- var country2currency = { } //This array uses "countryCode" to get the official "currencyCode" for that country.

var currency2country = { } //This array uses "currencyCode" to get the "countryCode" for the country that uses this currency //EXCEPT FOR "USD" and "EUR" those inputs just return themselves.

var currencyPositions = { }; //This array uses "currencyCode" to get the position of the symbol when using that curency. //EXCEPT FOR "EUR"

var euroPositions = { }; //This array uses "languageCode" to get the position of the Euro symbol.

var currencySymbols = { }; //This array uses "currencyCode" to get the symbol of this currency.

var currencyMinimums = { }; //This array uses "currencyCode" to get the minimum allowed donation for this currency.

var acceptedCC = arrayToObject([ ]); //This array uses "currencyCode" to return whether or not this payment type is accepted for this currency. var acceptedPayPal = arrayToObject([ ]); //This array uses "currencyCode" to return whether or not this payment type is accepted for this currency.

var stateList = [ ]; //This array is used to populate the state dropdown in the extra info fields

LP dependent arrays
// Calling Template Defined Arrays var currencyTypes = new Array ; //This array sets which currencies are to be made available. //REQUIRES to be passed from "lp-layout"

var currencyDonationAmounts = { }; //This array uses "countryCode" to return the donation options for that country. //REQUIRES to be passed from "lp-layout"

var currencyDisplay = new Array ; //This array determines which of the ten options are to be displayed. //REQUIRES to be passed from "lp-layout"

Template passed varibables
// Calling Template Defined Variables var toggleCurrency = ; //This variable sets whether or not the dropdown currency should be used

var toggleInfo = ; //This variable set whether or not the the extra info fields should be used

var optionWrap = ; //This variable sets after how many donation options per line there are //$('.div_amount_radio').width = Math.floor(100/(optionWrap+1)) + "%"; //$('#div_amount_other').width = Math.floor(100/(optionWrap+1)) + "%";

Local page wide varibables
//-Variables var countryCode = getQuerystring ('country'); //This variable stores the current country. //REQUIRES 'country' to be passed from "Central Notice" if(countryCode == '') countryCode = 'US';

var languageCode = getQuerystring ('language'); //This variable stores the current language. //REQUIRES 'language' to be passed from "Central Notice" if(languageCode == '') languageCode = 'en';

var currencyCode = country2currency[countryCode]; //This variable stores the current currency. //REQUIRES 'country' to be passed from "Central Notice" if(typeof(currencyCode) == 'undefined') {   currencyCode = 'USD'; countryCode = 'US'; }

var paymentType; //This variable stores the payment type selected by the user.

var maxRadioLength; //This variable stores the length of the longest donation option to be presented.

JavaScript body changing functions
This block of JS contains the payment processing, symbol switching code, and option changing code. //- Body functions --- function updateButtons //This function determines what buttons are displayed for each currency. { document.getElementById('cc-donate-button').style.display = "none"; document.getElementById('paypal-donate-button').style.display = "none"; if ( currencyCode in acceptedCC ) {   //is this template still needed? document.getElementById('cc-donate-button').style.display = " "; } if (currencyCode in acceptedPayPal ) {   //why not this? document.getElementById('paypal-donate-button').style.display = "block"; } }

function updateSymbol //This function displays the correct currency symbol based on currency selected and language { $('.amount-label-symbol').remove;

if (typeof(currencySymbols[currencyCode]) == 'undefined') return;

if (currencyPositions[currencyCode] == 'after') {   $('.amount-label').append(' ' + currencySymbols[currencyCode] + ' '); } else if(currencyPositions[currencyCode] == 'euro') {   if(euroPositions[languageCode] == 'before') {     $('.amount-label').prepend(' ' + currencySymbols[currencyCode] + ' '); }   else {     $('.amount-label').append(' ' + currencySymbols[currencyCode] + ' '); } }  else {   $('.amount-label').prepend(' ' + currencySymbols[currencyCode] + ' '); } }

function updateValue //This function updates the asking amounts based on country and currency. { var amountLength; for(i=0; i<10; i++) {   if(typeof(currencyDonationAmounts[countryCode][i]) == 'undefined') {     break; }

if(currencyDisplay[i] != 0) {     document.getElementById("input_amount_" + i).value = currencyDonationAmounts[countryCode][i]; document.getElementById("input_amount_label_" + i).innerHTML = currencyDonationAmounts[countryCode][i]; amountLength = currencyDonationAmounts[countryCode][i]; } }

//This code is to make the donation options resize NOT WORKING YET maxRadioLength = currencySymbols[currencyCode].length + (amountLength + "").length; //alert(maxRadioLength); //$('.div_amount_radio').width(maxRadioLength*12 + "px"); //$('.div_amount_radio').width(maxRadioLength*0.95 + "em");

if(maxRadioLength > 3) {   //$('.div_amount_radio').width("20%"); //$('#input_amount_other_box').width("18%"); } else {   //$('.div_amount_radio').width("20%"); //$('#input_amount_other_box').width("18%"); } }

function updateMenuChange(temp) //This function manages the updating when the drop down menu changes. { currencyCode = temp; countryCode = currency2country[currencyCode];

updateButtons; updateValue; updateSymbol; resetOtherBox; //spaceAmts; }

Form processing functions
//--form junk function validateCardInfo //This function is used to check that the extra info fields are filled in correctly { var generalError = false; var individualError =false;

testElem = document.getElementById('card_name_first'); if(testElem.value == 'First' || testElem.value == '') {   flagError(testElem); generalError = true; }

testElem = document.getElementById('card_name_last'); if(testElem.value == "Last" || testElem.value == '') {   flagError(testElem); generalError = true; }

testElem = document.getElementById('card_address_street_1'); if(testElem.value == "Street" || testElem.value == '') {   flagError(testElem); generalError = true; }

testElem = document.getElementById('card_address_city'); if(testElem.value == "City" || testElem.value == '') {   flagError(testElem); generalError = true; }

testElem = document.getElementById('card_address_state'); if(testElem.value == "" || testElem.value == '') {   flagError(testElem); generalError = true; }

testElem = document.getElementById('card_address_zip'); if(testElem.value == "Zip" || testElem.value == '') {   flagError(testElem); generalError = true; }  else if(!checkZip(testElem)) {   flagError(testElem); alert('Invalid zip code.'); individualError = true; }

testElem = document.getElementById('card_email'); if(testElem.value == "Email Address" || testElem.value == '') {   flagError(testElem); generalError = true; } else if(!checkEmail(testElem)) {   flagError(testElem); alert('Invalid email address.'); individualError = true; }

if(individualError) {   return false; }

if(generalError) {   alert('All fields must be filled in to process your donation.'); return false; } }

function validateForm( form ) //This function checks the validity of the form. {

//This piece of code checks the extra form info if necessary if(toggleInfo) {   if(paymentType == 'cc') {     if(validateCardInfo==false) {       return false; }   }  }

//This piece of code grabs the amount of the donation from where ever it was set var amount = null; for ( var i = 0; i < form.amount.length; i++ ) {   if(form.amount[i].checked) {     amount = form.amount[i].value; } }  if ( form.amountGiven.value != "") {   var otherAmount = form.amountGiven.value; otherAmount = otherAmount.replace(/[,.](\d)$/, '\:$10'); otherAmount = otherAmount.replace(/[,.](\d)(\d)$/, '\:$1$2'); otherAmount = otherAmount.replace(/[,.]/g, ''); otherAmount = otherAmount.replace(/:/, '.'); form.amountGiven.value = otherAmount; amount = otherAmount; }

//This piece of code checks to make sure the donation amount chosen is a valid donation amount var amountError = true;

// Check amount is a real number amountError = ( amount == null || isNaN( amount ) || amount.value <= 0 );

// Check amount is at least the minimum if ( typeof(currencyMinimums[currencyCode]) == 'undefined' ) {   currencyMinimums[currencyCode] = 1; } if ( amount < currencyMinimums[currencyCode] || amountError ) {   alert( '  '.replace('$1', currencyMinimums[currencyCode] + ' ' + currencyCode ) ); amountError = true; } return !amountError; }

function DefaultSubmit(formfield, Action) //This function manages the submit action of the form. { var keycode; if (window.event) {   keycode = window.event.keyCode; } else if (Action) {   keycode = Action.which; } else return true;

if (keycode == 13) {   if (document.getElementById('cc-donate-button').style.display == "block") {     redirectPayment('cc'); }   else if (document.getElementById('paypal-donate-button').style.display == "block") {     redirectPayment('pp'); }   return false; } else return true; }

function redirectPayment(button) //This function directs the payment to the proper method. { paymentType = button;

if (paymentType == 'cc') {   var paymentType = 'cc'; var action_url = "https://payments.wikimedia.org/index.php/Special:PayflowProGateway?uselang= \x26masthead=\x26form_name=\x26text_template=\x26language=\x26ffname= "; //TESLA TESTING //var action_url = "https://test-payments.tesla.usability.wikimedia.org/index.php/Special:PayflowProGateway?uselang= \x26masthead=\x26form_name=\x26text_template=\x26language=\x26ffname= " ; //Staging //var action_url = "https://payments4.wikimedia.org/index.php/Special:PayflowProGateway?uselang= \x26masthead=\x26form_name=\x26text_template=\x26language=\x26ffname= " ; } if (paymentType == 'pp') {   action_url = "https://wikimediafoundation.org/wiki/Special:ContributionTracking/  "; } document.paypalcontribution.action = action_url; document.paypalcontribution.utm_source.value = getQuerystring( 'utm_source' ) + '.' + getLandingPage + '.' + paymentType; if(validateForm(document.paypalcontribution)) {   if(paymentType == 'cc') {     if(toggleInfo == true) {       document.paypalcontribution.fname.value = document.paypalcontribution.card_name_first.value; document.paypalcontribution.lname.value = document.paypalcontribution.card_name_last.value;

document.paypalcontribution.street.value = document.paypalcontribution.card_address_street_1.value; document.paypalcontribution.address1.value = document.paypalcontribution.card_address_street_1.value;

document.paypalcontribution.city.value = document.paypalcontribution.card_address_city.value; document.paypalcontribution.state.value = document.paypalcontribution.card_address_state.value;

document.paypalcontribution.zip.value = document.paypalcontribution.card_address_zip.value;

document.paypalcontribution.email.value = document.paypalcontribution.card_email.value; document.paypalcontribution.emailAdd.value = document.paypalcontribution.card_email.value; }   }

if(typeof(OWA) !== 'undefined') {     OWATracker.shareStateByPost( document.paypalcontribution ); }   document.paypalcontribution.submit; } }

HTML
This secion has the actual form and HTML with some JavaScript dotted in it.

Form inputs




      

  

 <input type="hidden" name="address1" value="" />

<input type="hidden" name="city" value="" /> <input type="hidden" name="state" value="" /> <input type="hidden" name="zip" value="" /> <input type="hidden" name="country" id="country" value="" />

<input type="hidden" name="email" value="" /> <input type="hidden" name="emailAdd" value="" />

Radio options box code
This piece of code relies currencyDonationAmounts, countryCode, optionWrap and currencyDisplay being defined.

<script type="text/javascript" language="javascript">

//This script auto populates the radio buttons with the right values for the users country

var items=0;

for(i=0; i<10; i++) { if(typeof(currencyDonationAmounts[countryCode][i]) == 'undefined' ) {   break; } //This adds the radio options according to the flags passed to the template. if(currencyDisplay[i] != 0) {   //this is a hack to add spacing the why creative wants it. if(items == optionWrap) {     document.getElementById("radio-box").innerHTML += "<div class='div_amount_radio' style='clear: left;'>" + "<input type='radio' class='input_amount_radio' name='amount' id='input_amount_" + i     + "' onclick='resetOtherBox;'" + "value='" + currencyDonationAmounts[countryCode][i] + "'/><label for='input_amount_" + i + "' class='amount-label' id='input_amount_label_" + i + "'> " + currencyDonationAmounts[countryCode][i] + " "; }   else {     document.getElementById("radio-box").innerHTML += "<div class='div_amount_radio'>" + "<input type='radio' class='input_amount_radio' name='amount' id='input_amount_" + i     + "' onclick='resetOtherBox;'" + "value='" + currencyDonationAmounts[countryCode][i] + "'/><label for='input_amount_" + i + "' class='amount-label' id='input_amount_label_" + i + "'> " + currencyDonationAmounts[countryCode][i] + " "; }   items++; } }

<div id="div_amount_other"> <input type="radio" name="amount" id="input_amount_other" value="" /><label for="input_amount_other">Other <input type="text" class="input-text" name="amountGiven" id="input_amount_other_box" onclick="this.value=''; clearOtherBox;" onfocus="this.form.input_amount_other.checked=true;" onKeyPress="return DefaultSubmit(this,event)" />

Currency select dropdown
This code relies on currencySymbols, currencyCode and currencyTypes being defined.

<select name="currency_code" id="input_currency_code" size="1" onchange="resetOtherBox; updateMenuChange(this.value);">

<script type="text/javascript" language="javascript">

//This script fills the currency drop down with the currency options that are enabled //It defaults to the proper currency for the users country

var opt = document.createElement("option"); opt.selected = true; opt.text = currencyCode + " – " + currencySymbols[currencyCode]; opt.value = currencyCode; document.getElementById("input_currency_code").options.add(opt); // var opt = document.createElement("option"); opt.text = "---"; opt.value = "USD"; document.getElementById("input_currency_code").options.add(opt)

for(i=0; i<currencyTypes.length; i++) {   opt = document.createElement("option"); opt.text = currencyTypes[i] + " – " + currencySymbols[currencyTypes[i]]; opt.value = currencyTypes[i];

document.getElementById("input_currency_code").options.add(opt); }

"Extra info" fields
This code relies on stateList being defined. Name <div class="card-input-field" id="card_name_first_div"> <input type="text" class="card-input" id="card_name_first" value="" onfocus="clearThis(this,'First');" onblur="resetThis(this,'First');" /> <div class="card-input-field" id="card_name_last_div"> <input type="text" class="card-input" id="card_name_last" value="" onfocus="clearThis(this,'Last');" onblur="resetThis(this,'Last');" /> Address <div class="card-input-field" id="card_address_street_1_div"> <input type="text" class="card-input" id="card_address_street_1" value="" onfocus="clearThis(this,'Street');" onblur="resetThis(this,'Street');" /> <div class="card-input-field" id="card_address_city_div"> <input type="text" class="card-input" id="card_address_city" value="" onfocus="clearThis(this,'City');" onblur="resetThis(this,'City');" /> <div class="card-input-field" id="card_address_state_div"> <select id="card_address_state" size="1" onclick="recolorThis(this);">

<script type="text/javascript">

var opt = document.createElement("option"); opt.selected = true; opt.text = ""; opt.value = ""; document.getElementById("card_address_state").options.add(opt);

for(i=0; i<stateList.length; i++) {   opt = document.createElement("option"); opt.text = stateList[i]; opt.value = stateList[i]; document.getElementById("card_address_state").options.add(opt); }

<div class="card-input-field" id="card_address_zip_div"> <input type="text" class="card-input" id="card_address_zip" value="" onfocus="clearThis(this,'Zip');" onblur="resetThis(this,'Zip');" /> E-mail <div class="card-input-field" id="card_email_div"> <input type="text" class="card-input" id="card_email" value="" onfocus="clearThis(this,'Email Address');" onblur="resetThis(this,'Email Address');" /> <input type="button" value="Reset Payment Options" class="donate-button" onclick="resetMoreInfo"; /> <input type="button" id="cc-info-button" value=" " class="donate-button" onclick="getMoreInfo;" /> <input type="button" id="cc-process-button" value="Continue" class="donate-button" onclick="paymentType='cc'; redirectPayment('cc')"; /> <input type="button" value=" " class="donate-button" onclick="paymentType='pp';redirectPayment('pp');" />

    *  *  *

More JavaScript
<script type="text/javascript">

//These commands make changes based on the flags passed from the calling template if( toggleCurrency ) document.getElementById("currency-select-block").style.display = 'block';

//This block is only needed if the extra info form is optional in the future if(toggleInfo == false) { document.getElementById('cc-info-div').style.display = 'none';

document.getElementById('cc-process-button').value = ' '; document.getElementById('cc-process-div').style.display = 'block';

document.getElementsByName("address_override")[0].value = 0; document.getElementsByName("fname")[0].value = ""; document.getElementsByName("lname")[0].value = ""; document.getElementsByName("street")[0].value = ""; document.getElementsByName("city")[0].value = ""; document.getElementsByName("state")[0].value = ""; document.getElementsByName("zip")[0].value = ""; document.getElementsByName("email")[0].value = ""; }

function getMoreInfo { if(toggleInfo) {   document.getElementsByName("address_override")[0].value = 1; document.getElementById("card_name_first").value = "First"; document.getElementById("card_name_last").value = "Last"; document.getElementById("card_address_street_1").value = "Street"; document.getElementById("card_address_city").value = "City"; document.getElementById("card_address_zip").value = "Zip"; document.getElementById("card_email").value = "Email Address";

document.getElementById('cc-info-div').style.display = 'none'; document.getElementById('cc-process-div').style.display = 'block';

//These commands provide the animated form $('#paypal-donate-button').animate({height: 'toggle'}, 1500, function {}); $('#card-info-block').animate({height: 'toggle'}, 1500, function {});

//non animated //$("#donate-button-block").style.display = "none"; //$("#card-info-block").style.display = "table";

//$("#donate-button-block").toggle; //$("#card-info-block").toggle; } }

function resetMoreInfo { document.getElementById('cc-info-div').style.display = 'block'; document.getElementById('cc-process-div').style.display = 'none'; $('#paypal-donate-button').animate({height: 'toggle'}, 1500, function {}); $('#card-info-block').animate({height: 'toggle'}, 1500, function {});

document.getElementsByName("address_override")[0].value = 0; document.getElementsByName("fname")[0].value = ""; document.getElementsByName("lname")[0].value = ""; document.getElementsByName("street")[0].value = ""; document.getElementsByName("city")[0].value = ""; document.getElementsByName("state")[0].value = ""; document.getElementsByName("zip")[0].value = ""; document.getElementsByName("email")[0].value = ""; //document.getElementById('card-info-block').style.display = 'none'; //document.getElementById('donate-button-block').style.display = 'block';

//$("#card-info-block").style.display = "none"; //$("#donate-button-block").style.display = "block"; }

function resetOtherBox //This function resets the "Other" Box to the default values. { document.getElementsByName("amountGiven")[0].style.color = "#999999"; document.getElementsByName("amountGiven")[0].value = ""; }

function clearOtherBox //This function empties the "Other" Box. { document.getElementsByName("amountGiven")[0].style.color = "#000000"; document.getElementsByName("amountGiven")[0].value = ""; }

document.paypalcontribution.utm_medium.value = getQuerystring( 'utm_medium' ); document.paypalcontribution.utm_campaign.value = getQuerystring( 'utm_campaign' ); //document.paypalcontribution.country.value = getQuerystring ( 'country' ); document.paypalcontribution.referrer.value = document.referrer;

( function( $ ) { $(document).ready(function{ updateButtons; updateValue; updateSymbol; resetOtherBox; //spaceAmts; }) } )( jQuery );