//-----------------------------------------------------------------------
// Module name   : LmooCountrySelect
// Author        : Paul Battersby
// Creation Date : Nov 26/08
//  This takes a country select form field and a province/state select
//  and links them so that changing the country, affects the drop down list
//  of provinces/states. This also fills in both the country and province
//  the country select form fields with option values
//
//  Usage :
//    new LmooCountrySelect("formName");
//
//  $Log: LmooCountrySelect.js $
//  Revision 1.14  2010-05-22 10:20:23-04  Battersby
//  - fixed bug where prov state select was not turned into an textbox
//  when a foreign country was selected
//
//  Revision 1.13  2010-05-13 19:06:16-04  Battersby
//  - world countries now start with a blank line
//
//  Revision 1.12  2010-05-11 23:19:38-04  Battersby
//  - value is now properly preserved when converting input to select
//
//  Revision 1.11  2010-05-04 18:50:12-04  Battersby
//  - alabama was missing from US states
//  - removed Puerto Rico from US states
//  - rewrote _setupCounty to work as well as provState
//
//  Revision 1.10  2010-04-30 20:17:05-04  Battersby
//  - country field can now have a blank entry
//
//  Revision 1.9  2010-04-14 08:22:22-04  Battersby
//  - removed duplicate countries
//  - when converting a text field to a select field, events are now cloned
//    and "data-" properties are copied
//
//  Revision 1.8  2010-03-23 17:40:46-04  Battersby
//  - can now initialize the prov_state with an initially selected value
//
//  Revision 1.7  2010-03-20 22:25:06-04  Battersby
//  - added an onCountryChange event
//
//  Revision 1.6  2009-11-12 10:22:13-04  Battersby
//  - replacing an input with a select box now preserves id, name, class, styles
//
//  Revision 1.5  2009-10-31 15:29:02-04  Battersby
//  - now empties the select options before inserting new options
//
//  Revision 1.4  2009-09-14 09:53:10-04  Battersby
//  - upgraded for use with mootools-1.2.3
//
//  Revision 1.3  2008-12-22 12:24:30-04  Battersby
//  - added usage documentation
//
//  Revision 1.2  2008-12-13 12:14:11-04  Battersby
//  - passes jsLint test
//  - added some documentation
//
//  Revision 1.1  2008-11-26 15:33:34-04  Battersby
//  Initial revision
//
//------------------------------------------------------------------------

//---------------------------- INCLUDE FILES -----------------------------

var LmooCountrySelect = new Class({
  Implements: [Events, Options],

//----------------------------- CONSTANTS --------------------------------


//----------------------------- VARIABLES --------------------------------

  options : {
    provStateElementName : "prov_state", // name field of prov_state select

    currProvState      : "",           // - pretty much only used during initialization
                                       //    this is the value to initially select in the prov_state
                                       //    which is usually $_POST['prov_state'] when the form
                                       //    has been Posted to the page that displayes the prov_state
                                       //    and it's desireable to pre fill the form values

    countryElementName : "country",    // name field of country select
    countryListIndex   : "canUs",      // which country list is to be used
    defaultCountry     : "Canada",     // intially selected country
    inputWidth         : 40,           // max width of input field in characters
    inputMaxChars      : 40,           // max characters that can be entered in an input field

                                       // indicates that if the country has changed,
                                       //  form validation should be told that the
                                       //  province state is now invalid

    // fired when a different country has been chosen
    onCountryChange : Class.empty
  },

  countryObj : null,   // the country drop down select field
  provStatObj : null,  // the provState drop down select field

//----------------------------- FUNCTIONS --------------------------------

  //************************************************************************
  // Name   : _setupCountry
  //  This connects a country select form field to a prov/state form field
  //  so that the selected country affects the contents of the prov state select
  //  or input. The select will become an input for countries without a list of
  //  provinces or states
  //
  //  (obj) formObj - a form object
  //  (string) countryElementName   - name field from the country select form field
  //  (string) provStateElementName - name field from the prov/stsate select or input form field
  //  (string) defaultProvState     - pretty much only used when during initialization
  //                                   this is the value to initially select in the prov_state
  //                                   which is usually $_POST['prov_state'] when the form
  //                                   has been Posted to the page that displayes the prov_state
  //                                   and it's desireable to pre fill the form values
  //
  // Returns : (obj) the country select object
  //************************************************************************
  _setupCountry : function(formObj,countryElementName,countryListIndex,defaultCountry) {
    var countryObj = $(formObj[countryElementName]);
    var country = countryObj.getProperty("value");
    var attrib; // attributes of an element (like "data-verifyRequired")
    var i;

    // if an initially selected country was given use it
    if (defaultCountry && !country) {
      country = defaultCountry;
    } // endif

    // if this is not already a select element
    if (countryObj.get("tag") !== "select") {
      // make it a select object
      newCountryObj = new Element("select",{
        id   : countryObj.getProperty("id"),
        name : countryObj.getProperty("name"),
        "class" : countryObj.getProperty("class"),
        "style" : countryObj.getProperty("style")
      });

      // clone the events
      newCountryObj.cloneEvents(countryObj);

      // get all the attributes (properties) for this form field
      attrib = countryObj.attributes;
      for (var i = 0; i < attrib.length; i++) {

        // if this is a data property, copy it to the new element
        if (attrib[i].nodeName.contains("data-")) {
          newCountryObj.setProperty(attrib[i].nodeName,attrib[i].nodeValue);
        } // endif
      } // end for

      // replace the old with the new
      newCountryObj.replaces(countryObj);
      countryObj = newCountryObj;
    } // endif

    // remove any previous options
    countryObj.options.length = 0;

    // loop through the country list and insert the option values
    for (var i = 0; i < LmooCountrySelect.countryList[countryListIndex].length; i++) {
      countryObj.options[i] = new Option(LmooCountrySelect.countryList[countryListIndex][i],LmooCountrySelect.countryList[countryListIndex][i]);
    } // endfor

    // if there was already a province or state selected, and it's in the list keep it selected
    if (country) {
      countryObj.selectedIndex = LmooCountrySelect.countryList[countryListIndex].indexOf(country);
    } else {
      countryObj.selectedIndex = -1;
    } // endif

    return countryObj;
  },

  //************************************************************************
  // Name   : updateProvState
  //  This connects a country select form field to a prov/state form field
  //  so that the selected country affects the contents of the prov state select
  //  or input. The select will become an input for countries without a list of
  //  provinces or states
  //
  //  (obj) formObj - a form object
  //  (string) countryElementName   - name field from the country select form field
  //  (string) provStateElementName - name field from the prov/stsate select or input form field
  //  (string) defaultProvState     - pretty much only used when during initialization
  //                                   this is the value to initially select in the prov_state
  //                                   which is usually $_POST['prov_state'] when the form
  //                                   has been Posted to the page that displayes the prov_state
  //                                   and it's desireable to pre fill the form values
  //
  // Returns : (obj) the provState object
  //************************************************************************
  _updateProvState : function(formObj,countryElementName,provStateElementName,defaultProvState) {
    var provStateObj = $(formObj[provStateElementName]);
    var countryObj = $(formObj[countryElementName]);
    var country = countryObj.getProperty("value");
    var provState;
    var newProvStateObj;
    var attrib; // attributes of an element (like "data-verifyRequired")
    var i;
    var id;

    // if an intially selected provState was given use it
    if (defaultProvState) {
      provState = defaultProvState;

    // try to read it from the select box
    } else {
      provState = provStateObj.getProperty("value");
    } // endif

    // if there are prov and states for this country
    if (LmooCountrySelect.provStateList[country]) {
      // if this is not already a select element
      if (provStateObj.get("tag") !== "select") {

        id = provStateObj.getProperty("id");

        // make it a select object
        newProvStateObj = new Element("select",{
          name : provStateObj.getProperty("name"),
          "class" : provStateObj.getProperty("class"),
          "style" : provStateObj.getProperty("style")
        });

        newProvStateObj.setProperty("value",provStateObj.getProperty("value"));

        // clone the events
        newProvStateObj.cloneEvents(provStateObj);

        // get all the attributes (properties) for this form field
        attrib = provStateObj.attributes;
        for (var i = 0; i < attrib.length; i++) {

          // if this is a data property, copy it to the new element
          if (attrib[i].nodeName.contains("data-")) {
            newProvStateObj.setProperty(attrib[i].nodeName,attrib[i].nodeValue);
          } // endif
        } // end for

        // replace the old with the new
        newProvStateObj.replaces(provStateObj);
        provStateObj.destroy();
        provStateObj = newProvStateObj;
        provStateObj.setProperty("id",id);
      } // endif

      // remove any previous options
      provStateObj.options.length = 0;

      // loop through the prov/state list and insert the option values
      for (var i = 0; i < LmooCountrySelect.provStateList[country].length; i++) {
        provStateObj.options[i] = new Option(LmooCountrySelect.provStateList[country][i],LmooCountrySelect.provStateList[country][i]);
      } // end for

      // if there was already a province or state selected, and it's in the list keep it selected
      if (provState) {
        provStateObj.selectedIndex = LmooCountrySelect.provStateList[country].indexOf(provState);
      } else {
        provStateObj.selectedIndex = -1;
      } // endif

    // no prov states so allow user to enter a prov state into a text box
    } else {

       // if the country is not blank
       if (country !== "") {
        // if the prov state is currently a select object
        // it needs to become an input
        if (provStateObj.get("tag") == "select") {
          // make an input object
          newProvStateObj = new Element("input",{
            type : "text",
            id   : provStateObj.getProperty("id"),
            name : provStateObj.getProperty("name"),
            "class" : provStateObj.getProperty("class"),
            "style" : provStateObj.getProperty("style")
          });

          // clone the events
          newProvStateObj.cloneEvents(provStateObj);

          // get all the attributes (properties) for this form field
          attrib = provStateObj.attributes;
          for (var i = 0; i < attrib.length; i++) {

            // if this is a data property, copy it to the new element
            if (attrib[i].nodeName.contains("data-")) {
              newProvStateObj.setProperty(attrib[i].nodeName,attrib[i].nodeValue);
            } // endif
          } // end for

          // replace the old with the new
          newProvStateObj.replaces(provStateObj);
        } // endif
      } // endif
    } // endif

    return provStateObj;
  },

  //************************************************************************
  // Name   : initialize (constructor)
  //
  //  (object) options - (optional) configuration options. See options declaration
  //                     above for the available options
  //
  // Returns : (nothing)
  //*************************************************************************
  initialize : function(formName,options) {
    this.formObj = $(document.forms[formName]);

    // do nothing if form doesn's exist (this may happen if presence/absense
    // of the form is dynamic)
    if (this.formObj === null) {
      return ;
    } // endif

    this.setOptions(options);

    // do the initial setup of the country
    this.countryObj = this._setupCountry(this.formObj,this.options.countryElementName,this.options.countryListIndex,this.options.defaultCountry);

    // if the country changes, change the prov/state list
    $(this.formObj[this.options.countryElementName]).addEvent("change",function(event) {
      var provStateObj = this._updateProvState(this.formObj,this.options.countryElementName,this.options.provStateElementName);

      // indicate that the country has changed and thus altered the prov/state select
      this.fireEvent("onCountryChange",$(this.formObj[this.options.provStateElementName]));
    }.bind(this));

    // do the initial setup of the province/state list
    this.provStateObj = this._updateProvState(this.formObj,this.options.countryElementName,this.options.provStateElementName,this.options.currProvState);
  }

});

LmooCountrySelect.countryList = {
  blankCanUs : ["","Canada","United States"],
  canUs : ["Canada","United States"],
  can   : ["Canada"],
  world : [
    "",
    "Afghanistan",
    "Albania",
    "Aleutian Islands",
    "Algeria",
    "American Samoa",
    "Andorra",
    "Angola",
    "Anguilla",
    "Antarctica",
    "Antigua",
    "Arabia",
    "Argentina",
    "Armenia",
    "Aruba",
    "Australia",
    "Austria",
    "Azerbaijan",
    "Bahamas",
    "Bahrain",
    "Bangladesh",
    "Barbados",
    "Barbuda",
    "Belarus",
    "Belgium",
    "Belize",
    "Benin",
    "Bermuda",
    "Bhutan",
    "Bolivia",
    "Bosnia",
    "Botswana",
    "Bouvet Island",
    "Brazil",
    "British Indian Ocean Territory",
    "British Virgin Islands",
    "Brunei Darussalam",
    "Brunei",
    "Bulgaria",
    "Burkina Faso",
    "Burundi",
    "Caicos",
    "Cambodia",
    "Cameroon",
    "Canada",
    "Cape Verde",
    "Cayman Islands",
    "Central African Republic",
    "Chad",
    "Chile",
    "China",
    "Christmas Island",
    "Cocos",
    "Colombia",
    "Comoros",
    "Congo",
    "Cook Islands",
    "Costa Rica",
    "Cote d'Ivoire",
    "Croatia",
    "Croatia",
    "Cuba",
    "Cyprus",
    "Czech Republic",
    "Denmark",
    "Djibouti",
    "Dominican Republic",
    "East Timor",
    "Ecuador",
    "Egypt",
    "El Salvador",
    "Equatorial Guinea",
    "Eritrea",
    "Estonia",
    "Ethiopia",
    "Falkland Islands",
    "Faroe Islands",
    "Fiji",
    "Finland",
    "France",
    "French Guiana",
    "French Polynesia",
    "French Southern Yerritories",
    "French Territories",
    "Gabon",
    "Gambia",
    "Georgia",
    "Germany",
    "Ghana",
    "Gibraltar",
    "Great Britain",
    "Greece",
    "Greenland",
    "Grenada",
    "Grenadines",
    "Grendines",
    "Guadeloupe",
    "Guam",
    "Guatemala",
    "Guernsey",
    "Guinea",
    "Guinea-Bissau",
    "Guyana",
    "Haiti",
    "Heard Island",
    "Herzegovina",
    "Honduras",
    "Hong Kong",
    "Hungary",
    "Iceland",
    "India",
    "Indonesia",
    "Iran",
    "Iraq",
    "Ireland",
    "Isle of Man",
    "Israel",
    "Italy",
    "Ivory Coast",
    "Jamaica",
    "Jan Mayen",
    "Japan",
    "Jersey",
    "Jordan",
    "Kazakhstan",
    "Keeling Islands",
    "Kenya",
    "Kiribati",
    "Kuwait",
    "Kyrgyzstan",
    "Lao",
    "Latvia",
    "Lebanon",
    "Lesotho",
    "Liberia",
    "Libya",
    "Liechtenstein",
    "Lithuania",
    "Luxembourg",
    "Macao",
    "Macedonia",
    "Madagascar",
    "Malawi",
    "Malaysia",
    "Maldives",
    "Mali",
    "Malta",
    "Malvinas",
    "Mariana Islands",
    "Marshall Islands",
    "Martinique",
    "Mauritania",
    "Mauritius",
    "Mayotte",
    "Mcdonald Islands",
    "Mexico",
    "Micronesia",
    "Miquelon",
    "Moldova",
    "Monaco",
    "Mongolia",
    "Montenegro",
    "Montserrat",
    "Morocco",
    "Mozambique",
    "Myanmar",
    "Namibia",
    "Nauru",
    "Nepal",
    "Netherlands Antilles",
    "Netherlands",
    "Nevis",
    "New Caledonia",
    "New Guinea",
    "New Zealand",
    "Nicaragua",
    "Niger",
    "Nigeria",
    "Niue",
    "Norfolk Island",
    "North Korea",
    "Northern Mariana Islands",
    "Norway",
    "Oman",
    "Pakistan",
    "Palau",
    "Palestine",
    "Panama",
    "Papua New Guinea",
    "Paraguay",
    "Peru",
    "Philippines",
    "Pitcairn",
    "Poland",
    "Portugal",
    "Puerto Rico",
    "Qatar",
    "Reunion",
    "Romania",
    "Russia",
    "Rwanda",
    "Saint Helena",
    "Saint Kitts",
    "Saint Lucia",
    "Saint Pierre",
    "Saint Vincent",
    "Samoa",
    "San Marino",
    "Sao Tome",
    "Saudi Arabia",
    "Senegal",
    "Serbia",
    "Seychelles",
    "Sierra Leone",
    "Singapore",
    "Slovakia",
    "Slovenia",
    "Solomon Islands",
    "Somalia",
    "South Africa",
    "South Georgia",
    "South Korea",
    "South Sandwich",
    "Spain",
    "Sri lanka",
    "Sudan",
    "Suriname",
    "Svalbard",
    "Swaziland",
    "Sweden",
    "Switzerland",
    "Syrian Arab Republic",
    "Taiwan",
    "Tanzania",
    "Thailand",
    "Timor-leste",
    "Tobago",
    "Togo",
    "Tokelau",
    "Tonga",
    "Trinidad",
    "Tunisia",
    "Turkey",
    "Turkmenistan",
    "Turks & Caicos",
    "Uganda",
    "Ukraine",
    "United Arab Emirates",
    "United Kingdom",
    "United States",
    "Uruguay",
    "U.S. Virgin Islands",
    "Uzbekistan",
    "Vanuatu",
    "Vatican City",
    "Venezuela",
    "Vietnam",
    "Virgin Islands",
    "Wallis and Futuna",
    "Western Sahara",
    "Yemen",
    "Zambia",
    "Zimbabwe"
  ]
};

LmooCountrySelect.provStateList = {
  "Canada" : [
    "Alberta",
    "British Columbia",
    "Manitoba",
    "New Brunswick",
    "Newfoundland",
    "Nova Scotia",
    "Nunavut",
    "Northwest Territories",
    "Ontario",
    "Prince Edward Island",
    "Quebec",
    "Saskatchewan",
    "Yukon"
  ],

  "United States" : [
    "Alaska",
    "Alabama",
    "Arizona",
    "Arkansas",
    "California",
    "Colorado",
    "Connecticut",
    "District of Columbia",
    "Delaware",
    "Florida",
    "Georgia",
    "Hawaii",
    "Idaho",
    "Illinois",
    "Indiana",
    "Iowa",
    "Kansas",
    "Kentucky",
    "Louisiana",
    "Maine",
    "Maryland",
    "Massachusetts",
    "Michigan",
    "Minnesota",
    "Mississippi",
    "Missouri",
    "Montana",
    "Nebraska",
    "Nevada",
    "New Hampshire",
    "New Jersey",
    "New Mexico",
    "New York",
    "North Carolina",
    "North Dakota",
    "Ohio",
    "Oklahoma",
    "Oregon",
    "Pennsylvania",
    "Rhode Island",
    "South Carolina",
    "South Dakota",
    "Tennessee",
    "Texas",
    "Utah",
    "Vermont",
    "Virginia",
    "Washington",
    "West Virginia",
    "Wisconsin",
    "Wyoming"
  ]
};

