
/*  new/common/js/error_handler.js  */
if (typeof tracking !== 'undefined' && tracking.cid !== 17923 && tracking.cid !== 17924) {
    if ('undefined' !== typeof Raven) {
        jQuery.ajax({
            dataType: "script",
            cache: true,
            url: '/new/common/js/raven-config.js.php',
        }).done(function (script, textStatus) {
            Raven.config(RAVEN_DSN, {
                whitelistUrls: [
                    /(.*)\.avaaz\.org/
                ],
                ignoreUrls: [/(.*)\.facebook\.com/i, /(.*)\.facebook\.net/i],
                includePaths: [
                    /https?:\/\/(.*)\.avaaz\.org/
                ]
            }).install();
        });
    } else { //using old error handler for not republished campaigns
        //Raven dummy
        var Raven = {
            captureException: function () {
            },
            captureMessage: function () {
            },
            context: function () {
            },
            wrap: function () {
            },
            setUser: function () {
            }
        };
        var gOldOnError = window.onerror;

        // Override previous handler.
        window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
            //its same as $.browser.msie && $.browser.version < 7 - but jquery can be not loaded in this time - so need use direct check
            var vIE = -1;
            if (navigator.appName === 'Microsoft Internet Explorer')
                vIE = (new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})")).exec(navigator.userAgent)[1];
            if (vIE > 0 && vIE < 7)
                return false;

            var l = document.location;
            var host = 'secure.avaaz.org';
            if (l.host.indexOf('avaaz.org') == -1 ||
                l.host.indexOf('code.avaaz.org') >= 0 ||
                l.host.indexOf('team.avaaz.org') >= 0 ||
                l.host.indexOf('preview.avaaz.org') >= 0) {
                host = l.host;
            }
            var img = new Image();
            var newErrMsg = errorMsg;
            if (newErrMsg.length > 200) {
                newErrMsg = newErrMsg.substring(0, 197);
                newErrMsg += '...';
            }
            img.src = '//' + host + '/act/error_handler_js.php?err=' + escape(newErrMsg) + '&file=' + escape(url) + '&line=' + escape(lineNumber);

            //not show errors in not chrome browsers
            if (navigator.appVersion.indexOf('Mac') != -1 || $.browser.safari || l.host == host) {
                if (typeof(console) != 'undefined' && console) {
                    if (typeof(console.log) == "function") {
                        console.log("Msg:" + newErrMsg + "\n file: " + url + ":" + lineNumber);
                    }
                }
            }
            if (gOldOnError) {
                // Call previous handler.
                return gOldOnError(errorMsg, url, lineNumber);
            }
            // Just let default handler run.
            return false;
        };
    }
}


/*  new/common/js/track.js  */
/*
var w = window, d = document, l = d.location;
if (w.addEventListener) // Normal browsers
    w.addEventListener('load', track, false);
else if (w.attachEvent) // Stupid IE
    w.attachEvent('onload', track);
else if (window.$) // Houston, we have a problem
    $(track);
*/

(function(w, d, l) {
    var track = function(need_load, undef) {
        if (need_load == undef) {
            var getLast = function(collection) {
                    for (var i = collection.length; i > 0; i--) {
                        if (collection[i].tagName == 'input' && collection[i].type == 'hidden') {
                            return collection[i].value;
                        }
                    }
                    return '';
                };
            w.tracking = {
                cid : getLast(d.getElementsByName('cid')),
                lang : getLast(d.getElementsByName('last'))
            };
        }
        var params = [
            'ref=' + (encodeURIComponent(d.referrer) || ''),
            'rnd=' + new Date().getTime(),
            'url=' + escape(l.href)
        ];
        for (var i in w.tracking) {
            params.push(i + '=' + w.tracking[i]);
        }

        var host = 'stats.avaaz.org';
        var img = new Image();
        img.src = 'https://' + host + '/act/open/track.php?' + params.join('&');
        return;
    };

    if (!w.tracking) {
        if (w.addEventListener) {
            // Normal browsers
            w.addEventListener('load', track, false);
        } else if (w.attachEvent) {
            // Stupid IE
            w.attachEvent('onload', track);
        } else if (window.$) {
            // Houston, we have a problem
            $(track);
        }
    } else {
        track(1);
    }
})(window, document, document.location);

/*  common/js/SocialHistory.js  */
/*
 * Added cache for result and check for current page
 *
 *
 * Social Limit - Only the social you care about.
 *
 * Enables your site to know which social bookmarking badges to display to your
 * visitors. It tells you all social sites the user has gone to, or you can
 * query for a specific one.
 *
 * For example:
 *
 *    var sl = SocialHistory();
 *    alert( sl.doesVisit("Digg") ); // Returns true/false, -1 if unknown.
 *    var listOfVisitedSites = sl.visitedSites();
 *    var checkedSites = sl.checkedSites();
 *
 * If you want to add more sites to check, you can pass that in as a dictionary
 * to History:
 *
 *    var more = { "Humanized": "http://humanized.com",
 *                 "Azarask.in": ["http://azarask.in", "http://azarask.in/blog"]
 *               };
 *    var sl = SocialHistory(more);
 *    alert( sl.doesVisit("Humanized") );
 *
 * For a list of built-in sites, see the sites variable below.
 *
 * Copyright (c) 2008 Aza Raskin (http://azarask.in/blog)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

var SocialHistory = function( moreSites ){
  var sites = {
    "Orkut": ["http://www.orkut.com/", "http://www.orkut.com/Main#Home"],
    "Twitter": ["http://twitter.com/", "http://twitter.com/login"],
    "Digg": ["http://digg.com", "http://digg.com/login"],
    "Reddit": ["http://reddit.com", "http://reddit.com/new/", "http://reddit.com/controversial/", "http://reddit.com/top/", "http://reddit.com/r/reddit.com/", "http://reddit.com/r/programming/"],
    "StumbleUpon": ["http://stumbleupon.com"],
    "Yahoo Buzz": ["http://buzz.yahoo.com"],
    "Facebook": ["http://facebook.com/home.php", "http://facebook.com", "https://login.facebook.com/login.php"],
    "Del.icio.us": ["https://secure.del.icio.us/login", "http://del.icio.us/"],
    "MySpace": ["http://www.myspace.com/"],
    "Technorati": ["http://www.technorati.com"],
    "Newsvine": ["https://www.newsvine.com", "https://www.newsvine.com/_tools/user/login"],
    "Songza": ["http://songza.com"],
    "Slashdot": ["http://slashdot.org/"],
    "Ma.gnolia": ["http://ma.gnolia.com/"],
    "Blinklist": ["http://www.blinklist.com"],
    "Furl": ["http://furl.net", "http://furl.net/members/login"],
    "Mister Wong": ["http://www.mister-wong.com"],
    "Current": ["http://current.com", "http://current.com/login.html"],
    "Menaeme": ["http://meneame.net", "http://meneame.net/login.php"],
    "Oknotizie": ["http://oknotizie.alice.it", "http://oknotizie.alice.it/login.html.php"],
    "Diigo": ["http://www.diigo.com/", "https://secure.diigo.com/sign-in"],
    "Funp": ["http://funp.com", "http://funp.com/account/loginpage.php"],
    "Blogmarks": ["http://blogmarks.net"],
    "Yahoo Bookmarks": ["http://bookmarks.yahoo.com"],
    "Xanga": ["http://xanga.com"],
    "Blogger": ["http://blogger.com"],
    "Last.fm": ["http://www.last.fm/", "https://www.last.fm/login/"],
    "N4G": ["http://www.n4g.com"],
    "Faves": ["http://faves.com", "http://faves.com/home", "https://secure.faves.com/signIn"],
    "Simpy": ["http://www.simpy.com", "http://www.simpy.com/login"],
    "Yigg": ["http://www.yigg.de"],
    "Kirtsy": ["http://www.kirtsy.com", "http://www.kirtsy.com/login.php"],
    "Fark": ["http://www.fark.com", "http://cgi.fark.com/cgi/fark/users.pl?self=1"],
    "Mixx": ["https://www.mixx.com/login/dual", "http://www.mixx.com"],
    "Google Bookmarks": ["http://www.google.com/bookmarks", "http://www.google.com/ig/add?moduleurl=bookmarks.xml&hl=en"],
    "Subbmitt": ["http://subbmitt.com/"],
    "GoogleMail": ["https://mail.google.com/mail/?tab=om", "https://mail.google.com/mail/", "https://mail.google.com/mail/?shva=1#inbox"]
  };

  for( var site in moreSites ) {
    // If we don't have the site, create the URL list.
    if( typeof( sites[site] ) == "undefined" ) sites[site] = [];

    // If the value is string, just push that onto the URL list.
    if( typeof( moreSites[site] ) == "string" )
      sites[site].push( moreSites[site] );
    else
      sites[site] = sites[site].concat( moreSites[site] );
  }

  function checkSites(sites) {
      var visited = {};

      function getStyle(el, scopeDoc,styleProp) {
        if (el.currentStyle)
          var y = el.currentStyle[styleProp];
        else if (window.getComputedStyle)
          var y = scopeDoc.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
        return y;
      }

      function remove( el ) {
        el.parentNode.removeChild( el );
      }

      // Code inspired by:
      // bindzus.wordpress.com/2007/12/24/adding-dynamic-contents-to-iframes
      function createIframe() {
        var iframe = document.createElement("iframe");
        iframe.style.position = "absolute";
        iframe.style.visibility = "hidden";

        document.body.appendChild(iframe);

        // Firefox, Opera
        if(iframe.contentDocument) iframe.doc = iframe.contentDocument;
        // Internet Explorer
        else if(iframe.contentWindow) iframe.doc = iframe.contentWindow.document;

        // Magic: Force creation of the body (which is null by default in IE).
        // Also force the styles of visited/not-visted links.
        iframe.doc.open();
            iframe.doc.write('<style>');
            iframe.doc.write("a{color: #000000; display:none;}");
            iframe.doc.write("a:visited {color: #FF0000; display:inline;}");
            iframe.doc.write('</style>');
        iframe.doc.close();

        // Return the iframe: iframe.doc contains the iframe.
        return iframe;
      }

      var iframe = createIframe();

      function embedLinkInIframe( href, text ) {
        var a = iframe.doc.createElement("a");
        a.href = href;
        a.innerHTML = site;
        iframe.doc.body.appendChild( a );
      }

      for( var site in sites ) {
        var urls = sites[site];
        for( var i=0; i<urls.length; i++ ) {
          // You have to create elements in the scope of the iframe for IE.
          embedLinkInIframe( urls[i], site );

          // Automatically try variations of the URLS with and without the "www"
          if( urls[i].match(/www\./) ){
            var sansWWW = urls[i].replace(/www\./, "");
            embedLinkInIframe( sansWWW, site );
          } else {
            // 2 = 1 for length of string + 1 for slice offset
            var httpLen = urls[i].indexOf("//") + 2;
            var withWWW = urls[i].substring(0, httpLen ) + "www." + urls[i].substring( httpLen );
            embedLinkInIframe( withWWW, site );
          }

        }
      }

      var links = iframe.doc.body.childNodes;
      for( var i=0; i<links.length; i++) {
        // Handle both Firefox/Safari, and IE (respectively)
        var displayValue = getStyle(links[i], iframe.doc, "display");
        var didVisit = displayValue != "none";

        if( didVisit ){
          visited[ links[i].innerHTML ] = true;
        }
      }

      remove( iframe );
      return visited;
  }

  var visited = checkSites({
    "current": [document.location.href]
  });

  // if visited == {} - magic will not work any more
  if (visited["current"]) {
    visited = checkSites(sites);
  }

  return new (function(){

    var usedSites = [];
    for( var site in visited ){
      usedSites.push( site );
    }

    // Return an array of visited sites.
    this.visitedSites = function() {
      return usedSites;
    }

    // Return true/false. If we didn't check the site, return -1.
    this.doesVisit = function( site ) {
      if( typeof( sites[site] ) == "undefined" )
        return -1;
      return typeof( visited[site] ) != "undefined";
    }

    var checkedSites = [];
    for( var site in sites ){
      checkedSites.push( site );
    }
    // Return a list of the sites checked.
    this.checkedSites = function(){
      return checkedSites;
    }
  })();
}


/*  new/common/js/cookie.js  */
/*
Script Name: Javascript Cookie Script
Author: Public Domain, with some modifications
Script Source URI: http://techpatterns.com/downloads/javascript_cookies.php
Version 1.1.2
Last Update: 5 November 2009

Changes:
1.1.2 explicitly declares i in Get_Cookie with var
1.1.1 fixes a problem with Get_Cookie that did not correctly handle case
where cookie is initialized but it has no "=" and thus no value, the
Get_Cookie function generates a NULL exception. This was pointed out by olivier, thanks
1.1.0 fixes a problem with Get_Cookie that did not correctly handle
cases where multiple cookies might test as the same, like: site1, site
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

// this fixes an issue with the old method, ambiguous values
// with this test document.cookie.indexOf( name + "=" );

// To use, simple do: Get_Cookie('cookie_name');
// replace cookie_name with the real cookie name, '' are required
function Get_Cookie( check_name ) {
	// first we'll split this cookie up into name/value pairs
	// note: document.cookie only returns name=value, not the other components
	var a_all_cookies = '';
	try {
		a_all_cookies = document.cookie.split( ';' );
	} catch(err) {
	};
	var a_temp_cookie = '';
	var cookie_name = '';
	var cookie_value = '';
	var b_cookie_found = false; // set boolean t/f default f
	var i = '';

	for ( i = 0; i < a_all_cookies.length; i++ )
	{
		// now we'll split apart each name=value pair
		a_temp_cookie = a_all_cookies[i].split( '=' );


		// and trim left/right whitespace while we're at it
		cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');

		// if the extracted name matches passed check_name
		if ( cookie_name == check_name )
		{
			b_cookie_found = true;
			// we need to handle case where cookie has no value but exists (no = sign, that is):
			if ( a_temp_cookie.length > 1 )
			{
				cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
			}
			// note that in cases where cookie is initialized but no value, null is returned
			return cookie_value;
			break;
		}
		a_temp_cookie = null;
		cookie_name = '';
	}
	if ( !b_cookie_found )
	{
		return null;
	}
}

/*
only the first 2 parameters are required, the cookie name, the cookie
value. Cookie time is in milliseconds, so the below expires will make the
number you pass in the Set_Cookie function call the number of days the cookie
lasts, if you want it to be hours or minutes, just get rid of 24 and 60.

Generally you don't need to worry about domain, path or secure for most applications
so unless you need that, leave those parameters blank in the function call.
*/
function Set_Cookie( name, value, expires, path, domain, secure ) {
	// set time, it's in milliseconds
	var today = new Date();
	today.setTime( today.getTime() );
	// if the expires variable is set, make the correct expires time, the
	// current script below will set it for x number of days, to make it
	// for hours, delete * 24, for minutes, delete * 60 * 24
	if ( expires )
	{
		expires = expires * 1000 * 60 * 60 * 24;
	}
	//alert( 'today ' + today.toGMTString() );// this is for testing purpose only
	var expires_date = new Date( today.getTime() + (expires) );
	//alert('expires ' + expires_date.toGMTString());// this is for testing purposes only

	document.cookie = name + "=" +escape( value ) +
		( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) + //expires.toGMTString()
		( ( path ) ? ";path=" + path : "" ) +
		( ( domain ) ? ";domain=" + domain : "" ) +
		( ( secure ) ? ";secure" : "" );
}

// this deletes the cookie when called
function Delete_Cookie( name, path, domain ) {
	if ( Get_Cookie( name ) ) document.cookie = name + "=" +
			( ( path ) ? ";path=" + path : "") +
			( ( domain ) ? ";domain=" + domain : "" ) +
			";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

/**
 * Global variable that contains domain for cookies
 *
 * @type {String}
 */
var sCookieDomain = '.avaaz.org';
/*  new/common/js/global.js  */
/**
 * This file used for miscellaneous functions, need entire all all project
 */

/**
 * Get image src according to current page port (80|443). #566 bug in IE
 * @param string input SRC of need image in amazon
 */
function get_secure_src(input) {
    // trim string (IE - burn in the hell!)
    return (
        document.location.protocol === 'https:' &&
            input.indexOf('amazonaws.com') !== -1
        ) ? input.replace(/\s*((\S+\s*)*)/, "$1").replace(/((\s*\S+)*)\s*/, "$1").replace(/^http:\/\//, "https://") : input;
}

function SetEmailDomain(email) {
    var domain, my_email, ind;

    if (email) {
        my_email = email;
        ind = my_email.indexOf("@");
        domain = my_email.substr((ind + 1));
        domain = domain.split('.')[0];
    }
    domain = domain || 'other';
    Set_Cookie('lastusedemail', domain, "", "/", sCookieDomain);
}

function SetDomain(domain) {
    Set_Cookie('lastusedemail', domain, 180, "/", sCookieDomain);
}

function GetEmailDomain() {
    var domain = Get_Cookie('lastusedemail');
    if (!domain) {
        return 'other';
    }
    return domain;
}

function formSpreadGetUserHashFromUrl() {
    var aUrlParams = window.location.search.replace('?', '').split('&'),
        sEntry = '';
    for (var i = 0; i < aUrlParams.length; i++) {
        sEntry = aUrlParams[i];
        if (sEntry.indexOf('=') === -1 && !/^\d+$/.test(sEntry) && sEntry.length >= 6) {
            return sEntry.substring(1);
        }
    }
    return '';
}


function setLocalCountry(element) {
    var $element = $(element);
    var callback = function (data) {
        $element.val(data.COUNTRY);
        $element.trigger('change');
    };
    detectLocalInformation(callback);
}

function detectLocalInformation(callback) {
    if ('undefined' !== typeof detectLocalInformation.localData) {
        if ('function' === typeof callback) {
            callback(detectLocalInformation.localData);
        }
    } else {
        $.post('/new/common/js/localsettings.js.php',
            function (response) {
                detectLocalInformation.localData = response;
                if ('function' === typeof callback) {
                    callback(response);
                }
            }, 'json');
    }
}

function pushStateOnPostaction(sUrlHash) {
    if (supportsHistoryApi()) {
        if ('' !== sUrlHash) {
            window.history.pushState({hash: sUrlHash}, 'hash ' + sUrlHash, '?' + sUrlHash);
        }
    }
}

function initSocialHistory() {
    // leaving stub for all old published pages that try to call this function
}

function getArgs(query) {
    var args = {};
    query = query ? query : location.search.substring(1);     // Get query string
    var pairs = query.split("&");                 // Break at ampersand
    for (var i = 0; i < pairs.length; i++) {
        var pos = pairs[i].indexOf('=');          // Look for "name=value"
        if (pos === -1) {
            continue;                  // If not found, skip
        }
        var argname = pairs[i].substring(0, pos);  // Extract the name
        var value = pairs[i].substring(pos + 1);    // Extract the value
        value = decodeURIComponent(value);        // Decode it, if needed
        args[argname] = value;                    // Store as a property
    }
    return args;                                  // Return the object
}

function getArgsWithHash() {
    var query = location.search.substring(1);
    query += '&';
    query += location.hash.substring(1);
    return getArgs(query);
}

/**
 * Replaces tokens in text
 *
 * @param oData tokens with prelacements
 * @param sText text to parse
 *
 * @return {String}
 */
function getEdgeData(oData, sText) {
    if (sText) {
        for (var sKey in oData) {
            if (oData.hasOwnProperty(sKey)) {
                var oRegEx = RegExp('{' + sKey + '}', 'ig');
                sText = sText.replace(oRegEx, oData[sKey]);

                oRegEx = RegExp('tag_open' + sKey + 'tag_close', 'ig');
                sText = sText.replace(oRegEx, oData[sKey]);
            }
        }
    }
    return sText;
}

function hashing(no_cookies) {
    var args = {};
    var userhash = null;
    var value;
    var argname;
    // Get uneascped query string. we do unescape in order toi convert values like this bwPewdb%26v%3D18633
    var query = unescape(location.search.substring(1));
    // Break at ampersand
    var pairs = query.split("&");
    for (var i = 0; i < pairs.length; i++) {
        // Look for "name=value"
        var pos = pairs[i].indexOf('=');
        if (pos === -1) {
            argname = pairs[i];
            args[argname] = null;
            // If not found, skip
        } else {
            argname = pairs[i].substring(0, pos);  // Extract the name
            value = pairs[i].substring(pos + 1);    // Extract the value
            value = decodeURIComponent(value);        // Decode it, if needed
            args[argname] = value;                    // Store as a property
        }
    }
    var cnt = 0;

    for (var h in args) {
        if (args.hasOwnProperty(h)) {
            var name = false;
            cnt++;
            if (h === 'v') {
                name = 'blast_version';
                value = parseInt(args[h], 10);
            } else if (h.length > 6 && args[h] === null) {
                name = 'hash';
                value = h;
            }
            if (name) {
                if (name === 'hash') {
                    // remove all characters after space
                    if (value.indexOf(' ') > 0) {
                        value = value.substr(0, value.indexOf(' '));
                    }

                    var aMatches = value.match(/https?:\/\//i);
                    if (aMatches) {
                        value = value.substr(0, value.indexOf(aMatches[0]));
                    }

                    // and replace all non letters, digits or hyphens with empty string
                    value = value.replace(/[^a-z\-0-9]+/ig, '');
                    userhash = value;
                }
                if (true !== no_cookies) {
                    Set_Cookie(name, value, null, "/", '.avaaz.org');
                    $('form').each(function () {
                        $(this).append('<input type="hidden" name="' + name + '" value="' + value + '"/>');
                    });
                }
            }
        }
    }
    return userhash;
}

function getUserHash(no_prefix) {
    var userhash = hashing(true);
    if (userhash && true === no_prefix) {
        userhash = userhash.substr(-6);
    }
    return userhash;
}

function count(mixed_var, mode) {
    var key, cnt = 0;
    if (mixed_var === null) {
        return 0;
    } else if (mixed_var.constructor !== Array && mixed_var.constructor !== Object) {
        return 1;
    }
    if (mode === 'COUNT_RECURSIVE') {
        mode = 1;
    }
    if (mode !== 1) {
        mode = 0;
    }
    for (key in mixed_var) {
        if (mixed_var.hasOwnProperty(key)) {
            cnt++;
            if (mode === 1 && mixed_var[key] && (mixed_var[key].constructor === Array || mixed_var[key].constructor === Object)) {
                cnt += this.count(mixed_var[key], 1);
            }
        }
    }
    return cnt;
}

function get_country_list(options, callback) {
    var def_opt = {
            'pp': false,
            'lang': 'en',
            'cid': 0,
            'group': 0
        },
        options = $.extend(def_opt, options),
        request_url = '/stat/act/ajaxGetCountry.php/type=json&lang=';

    if (options.lang) {
        request_url += options.lang;
    }
    if (options.pp) {
        request_url += ('&pp=true');
    }
    if (options.cid && options.cid !== "0") {
        request_url += ('&cid=' + options.cid);
    }
    if (options.group && options.group !== "0") {
        request_url += ('&group=' + options.group);
    }
    if (get_country_list.cachedData && get_country_list.cachedData[request_url]) {
        if ('function' === typeof callback) {
            callback(get_country_list.cachedData[request_url], options);
        }
        return true;
    }
    return $.ajax({
        url: request_url,
        success: function (data) {
            if ('function' === typeof callback) {
                callback(data, options);
            }
        },
        dataType: 'json'
    });
}

function update_country_by_ajax(options, callback) {
    return get_country_list(options, function (data, options) {
        var html = '';
        options = $.extend({'context': ''}, options);
        if (options.empty) {
            html += ('<option value="">' + options.empty + '</option>');
        }
        for (var i = 0; i < data.length; i++) {
            if (data[i].id !== '') {
                html += ("<option value='" + data[i].id + "'>" + data[i].value + "</option>");
            }
        }
        $(options.el, options.context).html(html);
        if (options.val) {
            $(options.el, options.context).val(options.val);
        }
        if (options.cb) {
            options.cb();
        }

        if (options.trigger_change) {
            $(options.el, options.context).trigger('change');
        }
    });
}

function createModalLoadingOverlay(options) {
    if ($("#modalLoadingOverlay").length === 0) {
        // create the modal window
        $('<div id="modalLoadingOverlay" style="display:none;"><div style="margin: 200px auto;"><img src="/images/ajax-loader3.gif" width="130" height="130"/></div></div>').appendTo('body');

        if (!options || options.click !== false) {
            $("#modalLoadingOverlay").click(function () {
                hideModalLoadingOverlay();
            });
        }

        if (!options || options.escape !== false) {
            $(document).keyup(function (e) {
                if (e.keyCode === 27) {
                    hideModalLoadingOverlay();
                }
            });
        }
    }
}
function showModalLoadingOverlay() {
    createModalLoadingOverlay();
    $("#modalLoadingOverlay").css('z-index', '9999').fadeIn();
}

function hideModalLoadingOverlay() {
    $('#modalLoadingOverlay').fadeOut();
}

/*Add Validation for History Support*/
function supportsHistoryApi() {
    return (window.history && 'pushState' in history);
}

function trackGAEvent(category, action, label) {
    _gaq.push(['_trackEvent', category, action, label]);
}

function get_standard_language_code(lang) {
    switch (lang) {
        case 'po': lang = 'pt'; break;
        case 'jp': lang =  'ja'; break;
    }

    return lang;
}

(function ($) {
    var fbReady = $.Deferred();
    $.fn.facebookReady = function (fn) {
        $.fbready.promise().done(fn);
        return this;
    };
    jQuery.extend({
        fbready: function () {
            fbReady.resolveWith(document, [ jQuery ]);
        }
    });
    $.fbready.promise = function (obj) {
        return fbReady.promise(obj);
    };
    $(document).bind("facebook:ready", function () {
        $.fbready();
    });
})(jQuery);
(function ($) {
    var taggingReady = $.Deferred();
    $.fn.taggingReady = function (fn) {
        $.taggingready.promise().done(fn);
        return this;
    };
    jQuery.extend({
        taggingready: function () {
            taggingReady.resolveWith(document, [ jQuery ]);
        }
    });
    $.taggingready.promise = function (obj) {
        return taggingReady.promise(obj);
    };
    $(document).bind("tagging_tool:ready", function () {
        $.taggingready();
    });
})(jQuery);

$(document).facebookReady(function () {
    $(document).ready(function () {
        $('.fb_image_upload').each(function () {
            var that = this;
            $(this).click(function (e) {
                var wnd = window.open('', "fb_upload_name", "width=20,height=20");
                window.focus();
                function uploadImageToFacebook() {
                    FB.api('/photos', 'post', {
                        message: $(that).data('image_description'),
                        access_token: FB.getAccessToken(),
                        url: $(that).data('image')
                    }, function (response) {
                        if (!response || response.error) {
                            console.log(response);
                            wnd.close();
                        } else {
                            wnd.location.href = 'http://www.facebook.com/photo.php?fbid=' + response.id + '&type=1&makeprofile=1&makeuserprofile=1';
                            wnd.resizeTo(900, 900);
                            wnd.focus();
                        }
                    });
                }

                FB.getLoginStatus(function (response) {
                    if (response.status === 'unknown') {
                        FB.login(function () {
                            uploadImageToFacebook();
                        });
                    } else {
                        uploadImageToFacebook();
                    }
                });
                e.preventDefault();
            });
        });
    });
});
$(document).ready(function () {
    if (!Get_Cookie('original_referrer')) {
        Set_Cookie('original_referrer', document.referrer, null, "/", '.avaaz.org');
    }

    var supports_history_api = supportsHistoryApi();
    $('form').each(
        function () {
            if (supports_history_api) {
                $(this).append("<input name=\"supports_history_api\" type=\"hidden\" value=\"" + supports_history_api + "\" />");
            }
        }
    );
    var resize_fix_footer = function () {
        $('.bg-blue-big, .bg-blue, #footer, .bg-blue-slidshow-controls, .bg-blue-middle, .bg_blue-manage').css('width', '100%');
        var elements = ['.bg-blue-big', '.bg-blue', '#footer', '.bg-blue-slidshow-controls', '.bg-blue-middle', '.bg_blue-manage'];
        var width = $(document).width();
        for (var i = 0; i < elements.length; i++) {
            if ($(elements[i]).length) {
                if (width > $(elements[i]).width()) {
                    $(elements[i]).css('width', width);
                }
            }
        }
    };

    $(window).resize(resize_fix_footer);
    resize_fix_footer();
    hashing();
    $('img[securesrc]').each(function () {
        var el = $(this);
        el.attr('src', get_secure_src(el.attr('securesrc')));
    });

    // Traffic split - change HOME links to traffic split source
    var sSplitOrigin = Get_Cookie('split_origin');
    if (sSplitOrigin) {
        $('#logo > a, #nav > .links > .first > a').attr('href', sSplitOrigin);
    }

    $('a.form-submit').on('click', function (e) {
        $(this).closest("form").submit();
        e.preventDefault();
    });
});

window.bFacebookReady = false;
$(document).facebookReady(function () {
    window.bFacebookReady = true;
});

/*  new/common/js/jquery.toggleval.js  */
/* -------------------------------------------------- *
 * ToggleVal 3.0
 * Updated: 01/15/2010
 * -------------------------------------------------- *
 * Author: Aaron Kuzemchak
 * URL: http://aaronkuzemchak.com/
 * Copyright: 2008-2010 Aaron Kuzemchak
 * License: MIT License
** -------------------------------------------------- */

(function($) {
	// main plugin function
	$.fn.toggleVal = function(theOptions) {
		// check whether we want real options, or to destroy functionality
		if(!theOptions || typeof theOptions == 'object') {
			theOptions = $.extend({}, $.fn.toggleVal.defaults, theOptions);
		}
		else if(typeof theOptions == 'string' && theOptions.toLowerCase() == 'destroy') {
			var destroy = true;
		}

		return this.each(function() {
			// unbind everything if we're destroying, and stop executing the script
			if(destroy) {
				$(this).unbind('focus.toggleval').unbind('blur.toggleval').removeData('defText');
				return false;
			}

			// define our variables
			var defText = '';

			// let's populate the field, if not default
			switch(theOptions.populateFrom) {
				case 'title':
					if($(this).attr('title')) {
						defText = $(this).attr('title');
						$(this).val(defText);
					}
					break;
				case 'label':
					if($(this).attr('id')) {
						defText = $('label[for="' + $(this).attr('id') + '"]').text();
						$(this).val(defText);
					}
					break;
				case 'custom':
					defText = theOptions.text;
					$(this).val(defText);
					break;
				default:
					defText = $(this).val();
			}

			// let's give this field a special class, so we can identify it later
			// also, we'll give it a data attribute, which will help jQuery remember what the default value is
			$(this).addClass('toggleval').data('defText', defText);

			// now that fields are populated, let's remove the labels if applicable
			if(theOptions.removeLabels == true && $(this).attr('id')) {
				$('label[for="' + $(this).attr('id') + '"]').remove();
			}

			// on to the good stuff... the focus and blur actions
			$(this).bind('focus.toggleval', function() {
				if($(this).val() == $(this).data('defText')) { $(this).val(''); }

				// add the focusClass, remove changedClass
				$(this).addClass(theOptions.focusClass);
			}).bind('blur.toggleval', function() {
				if($(this).val() == '' && !theOptions.sticky) { $(this).val($(this).data('defText')); }

				// remove focusClass, add changedClass if, well, different
				$(this).removeClass(theOptions.focusClass);
				if($(this).val() != '' && $(this).val() != $(this).data('defText')) { $(this).addClass(theOptions.changedClass); }
					else { $(this).removeClass(theOptions.changedClass); }
			});
		});
	};

	// default options
	$.fn.toggleVal.defaults = {
		focusClass: 'tv-focused', // class during focus
		changedClass: 'tv-changed', // class after focus
		populateFrom: 'title', // choose from: default, label, custom, or title
		text: null, // text to use in conjunction with populateFrom: custom
		removeLabels: false, // remove labels associated with the fields
		sticky: false // if true, default text won't reappear
	};

	// create custom selectors
	// :toggleval for affected elements
	// :changed for changed elements
	$.extend($.expr[':'], {
		toggleval: function(elem) {
			return $(elem).data('defText') || false;
		},
		changed: function(elem) {
			if($(elem).data('defText') && $(elem).val() != $(elem).data('defText')) {
				return true;
			}
			return false;
		}
	});
})(jQuery);
/*  new/common/js/jquery.infieldlabel.js  */
/*
 * jquery.infieldlabel
 * A simple jQuery plugin for adding labels that sit over a form field and fade away when the fields are populated.
 *
 * Copyright (c) 2009 - 2013 Doug Neiner <doug@dougneiner.com> (http://code.dougneiner.com)
 * Source: https://github.com/dcneiner/In-Field-Labels-jQuery-Plugin
 * Dual licensed MIT or GPL
 *   MIT (http://www.opensource.org/licenses/mit-license)
 *   GPL (http://www.opensource.org/licenses/gpl-license)
 *
 * @version 0.1.4
 */
(function ($) {

    $.InFieldLabelsSetPosition = function() {
        $('.set-label-position').filter(':visible').each(function(){
            $(this).trigger('setLabelPosition');
        }).removeClass('set-label-position');
    }

  $.InFieldLabels = function (label, field, options) {
    // To avoid scope issues, use 'base' instead of 'this'
    // to reference this class from internal events and functions.
    var base = this;

    // Access to jQuery and DOM versions of each element
    base.$label = $(label);
    base.label  = label;

    base.$field = $(field);
    base.field  = field;

    base.$label.data("InFieldLabels", base);
    base.showing = true;

    base.init = function () {
      var initialSet;

      // Merge supplied options with default options
      base.options = $.extend({}, $.InFieldLabels.defaultOptions, options);

      // Add provided class name to the label, if set
      if ( base.options.className ) {
        base.$label.addClass(base.options.className);
      }

      // Check if the field is already filled in
      // add a short delay to handle autocomplete
      setTimeout(function() {
        if (base.$field.val() !== "") {
          base.$label.hide();
          base.showing = false;
        } else {
          base.$label.show();
          base.showing = true;
        }
      }, 200);
      if (base.$label.data('context')) {
          base.$label.click(function (e) {
              e.preventDefault();
              base.$field.trigger('focus');
          });
      }
      base.$field.focus(function () {
        base.fadeOnFocus();
      }).blur(function () {
        base.checkForEmpty(true);
      }).bind('keydown.infieldlabel', function (e) {
        // Use of a namespace (.infieldlabel) allows us to
        // unbind just this method later
        base.hideOnChange(e);
      }).bind('paste', function () {
        // Since you can not paste an empty string we can assume
        // that the field is not empty and the label can be cleared.
        base.setOpacity(0.0);
      }).change(function () {
        base.checkForEmpty();
      }).bind('onPropertyChange', function () {
        base.checkForEmpty();
      }).bind('keyup.infieldlabel', function () {
        base.checkForEmpty();
      });

      if ( base.options.pollDuration > 0 ) {
        initialSet = setInterval( function () {
        if (base.$field.val() !== "") {
          base.$label.hide();
          base.showing = false;
          clearInterval( initialSet );
        }
      }, base.options.pollDuration );

      }
    };

    // If the label is currently showing
    // then fade it down to the amount
    // specified in the settings
    base.fadeOnFocus = function () {
      if (base.showing) {
        base.setOpacity(base.options.fadeOpacity);
      }
    };

    base.setOpacity = function (opacity) {
      base.$label.stop().animate({ opacity: opacity }, base.options.fadeDuration);
      base.showing = (opacity > 0.0);
    };

    // Checks for empty as a fail safe
    // set blur to true when passing from
    // the blur event
    base.checkForEmpty = function (blur) {
      if (base.$field.val() === "") {
        base.prepForShow();
        base.setOpacity(blur ? 1.0 : base.options.fadeOpacity);
      } else {
        base.setOpacity(0.0);
      }
    };

    base.prepForShow = function () {
      if (!base.showing) {
        // Prepare for a animate in...
        base.$label.css({opacity: 0.0}).show();

        // Reattach the keydown event
        base.$field.bind('keydown.infieldlabel', function (e) {
          base.hideOnChange(e);
        });
      }
    };

    base.hideOnChange = function (e) {
      if (
          (e.keyCode === 16) || // Skip Shift
          (e.keyCode === 9) // Skip Tab
        ) {
        return;
      }

      if (base.showing) {
        base.$label.hide();
        base.showing = false;
      }

      // Remove keydown event to save on CPU processing
      base.$field.unbind('keydown.infieldlabel');
    };

    // Run the initialization method
    base.init();
  };

  $.InFieldLabels.defaultOptions = {
    fadeOpacity: 0.5, // Once a field has focus, how transparent should the label be
    fadeDuration: 300, // How long should it take to animate from 1.0 opacity to the fadeOpacity
    pollDuration: 0, // If set to a number greater than zero, this will poll until content is detected in a field
    enabledInputTypes: [ "text", "search", "tel", "url", "email", "password", "number", "textarea" ],
    className: false // Class assigned to enhanced labels
  };


  $.fn.inFieldLabels = function (options) {
    var allowed_types = options && options.enabledInputTypes || $.InFieldLabels.defaultOptions.enabledInputTypes;

    return this.each(function () {
      // Find input or textarea based on for= attribute
      // The for attribute on the label must contain the ID
      // of the input or textarea element
      var for_attr = $(this).attr('for'), field, restrict_type, context;
      if (!for_attr) {
        return; // Nothing to attach, since the for field wasn't used
      }
      // Find the referenced input or textarea element
      if ($(this).data('context')) {
          field = $('#' + for_attr, $(this).data('context')).get(0);
      } else {
          field = document.getElementById( for_attr );
      }

      if ( !field ) {
        return; // No element found
      }

      // Restrict input type
      restrict_type = $.inArray( field.type, allowed_types );

      if ( restrict_type === -1 && field.nodeName !== "TEXTAREA" ) {
        return; // Again, nothing to attach
      }

      // Only create object for matched input types and textarea
      (new $.InFieldLabels(this, field, options));
    });
  };

}(jQuery));

/*  new/common/js/actions.js  */
$(document).ready(function()
{
    /* adjust styling for macosx-based browsers */
    if (navigator.appVersion.indexOf('Mac') != -1 || $.browser.safari) {
        var timestamp = Math.round((new Date()).getTime() / (1000 * 3600));
        /* use timestamp exported with tracking */
        if(window['tracking'] && window['tracking'].stamp) {
            timestamp = window['tracking'].stamp;
        }
        $('head').append('<link type="text/css" rel="stylesheet" media="all" href="/stat/new/css/css.php/s=macosx.less_'+ timestamp + '&fe=%252Fnew%252Fcss%252Fblue%252Fmacosx.less&h=macosx.less_' + timestamp + '" />');
    }

    if ($('html').attr('dir')=='rtl' && (navigator.appVersion.indexOf('Mac') != -1 || $.browser.safari)) {
        $('.title-ribbon, .photo-ribbon').wrap('<div class="rtlwrap">');
    }

    if (typeof jQuery.fn.toggleVal == 'function') {
        $('.form-text').toggleVal();
    }

    // onrollover link for #focus-photo-feature
    $("#focus-photo-feature .content a").hover(
        function () {
            $(this).find('img').attr('src', function() {
                return this.src.replace('.png', '_ovr.png');
            });
        },
        function () {
            $(this).find('img').attr('src', function() {
                return this.src.replace('_ovr', '');
            });
        }
    );
});

$(document).ready(function(){
    if ('function' === typeof $('label').inFieldLabels) {
        $("label.labeloverlay").inFieldLabels();
    }

    $('form').each(function(){
        var input_js = document.createElement('input');
            input_js.setAttribute('type', 'hidden');
            input_js.setAttribute('name', 'secure_validation');
            input_js.value = new Date();
        this.appendChild(input_js);
        var used_js = document.createElement('input');
            used_js.setAttribute('type', 'hidden');
            used_js.setAttribute('name', 'used_js');
            used_js.value = new Date();
        this.appendChild(used_js);
    });

    if (typeof signup_button_text != "undefined") {
        $oSignupPlaceholder = $('.form-sign .form-broken-js');
        replacePlaceholderWith($oSignupPlaceholder, signup_button_text);
    }

    if (typeof donate_button_text != "undefined") {
        $oDonatePlaceholder = $('.form-donate .form-broken-js');
        replacePlaceholderWith($oDonatePlaceholder, donate_button_text);
    }

});

function replacePlaceholderWith(oPlaceholder, mData) {

    if (typeof mData == 'object') {
        for (i = 0; i < mData.length; ++i) {
            $(oPlaceholder[i]).replaceWith(mData[i]);
        }
    } else {
        oPlaceholder.replaceWith(mData)
    }

}

/*  common/js/jquery.validate.js  */
/**
 * jQuery Validation Plugin 1.9.0
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2011 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

(function($) {

    $.extend($.fn, {
        // http://docs.jquery.com/Plugins/Validation/validate
        validate: function( options ) {

            // if nothing is selected, return nothing; can't chain anyway
            if (!this.length) {
                options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
                return;
            }

            // check if a validator for this form was already created
            var validator = $.data(this[0], 'validator');
            if ( validator ) {
                return validator;
            }

            // Add novalidate tag if HTML5.
            try {
                this.attr('novalidate', 'novalidate');
            } catch (e) {
                this[0].setAttribute('novalidate', 'novalidate');
            }

            validator = new $.validator( options, this[0] );
            $.data(this[0], 'validator', validator);

            if ( validator.settings.onsubmit ) {

                var inputsAndButtons = this.find("input, button");

                // allow suppresing validation by adding a cancel class to the submit button
                inputsAndButtons.filter(".cancel").click(function () {
                    validator.cancelSubmit = true;
                });

                // when a submitHandler is used, capture the submitting button
                if (validator.settings.submitHandler) {
                    inputsAndButtons.filter(":submit").click(function () {
                        validator.submitButton = this;
                    });
                }

                // validate the form on submit
                this.submit( function( event ) {
                    if ( validator.settings.debug )
                    // prevent form submit to be able to see console output
                        event.preventDefault();

                    function handle() {
                        if ( validator.settings.submitHandler ) {
                            if (validator.submitButton) {
                                // insert a hidden input as a replacement for the missing submit button
                                var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
                            }
                            validator.settings.submitHandler.call( validator, validator.currentForm );
                            if (validator.submitButton) {
                                // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
                                hidden.remove();
                            }
                            return false;
                        }
                        return true;
                    }

                    // prevent submit for invalid forms or custom submit handlers
                    if ( validator.cancelSubmit ) {
                        validator.cancelSubmit = false;
                        return handle();
                    }
                    if ( validator.form() ) {
                        if ( validator.pendingRequest ) {
                            validator.formSubmitted = true;
                            return false;
                        }
                        return handle();
                    } else {
                        validator.focusInvalid();
                        return false;
                    }
                });
            }

            return validator;
        },
        // http://docs.jquery.com/Plugins/Validation/valid
        valid: function() {
            if ( $(this[0]).is('form')) {
                return this.validate().form();
            } else {
                var valid = true;
                var validator = $(this[0].form).validate();
                this.each(function() {
                    valid &= validator.element(this);
                });
                return valid;
            }
        },
        // attributes: space seperated list of attributes to retrieve and remove
        removeAttrs: function(attributes) {
            var result = {},
                $element = this;
            $.each(attributes.split(/\s/), function(index, value) {
                result[value] = $element.attr(value);
                $element.removeAttr(value);
            });
            return result;
        },
        // http://docs.jquery.com/Plugins/Validation/rules
        rules: function(command, argument) {
            var element = this[0];

            if (command) {
                var settings = $.data(element.form, 'validator').settings;
                var staticRules = settings.rules;
                var existingRules = $.validator.staticRules(element);
                switch(command) {
                    case "add":
                        $.extend(existingRules, $.validator.normalizeRule(argument));
                        staticRules[element.name] = existingRules;
                        if (argument.messages)
                            settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
                        break;
                    case "remove":
                        if (!argument) {
                            delete staticRules[element.name];
                            return existingRules;
                        }
                        var filtered = {};
                        $.each(argument.split(/\s/), function(index, method) {
                            filtered[method] = existingRules[method];
                            delete existingRules[method];
                        });
                        return filtered;
                }
            }

            var data = $.validator.normalizeRules(
                $.extend(
                    {},
                    $.validator.metadataRules(element),
                    $.validator.classRules(element),
                    $.validator.attributeRules(element),
                    $.validator.staticRules(element)
                ), element);

            // make sure required is at front
            if (data.required) {
                var param = data.required;
                delete data.required;
                data = $.extend({required: param}, data);
            }

            return data;
        }
    });

// Custom selectors
    $.extend($.expr[":"], {
        // http://docs.jquery.com/Plugins/Validation/blank
        blank: function(a) {return !$.trim("" + a.value);},
        // http://docs.jquery.com/Plugins/Validation/filled
        filled: function(a) {return !!$.trim("" + a.value);},
        // http://docs.jquery.com/Plugins/Validation/unchecked
        unchecked: function(a) {return !a.checked;}
    });

// constructor for validator
    $.validator = function( options, form ) {
        this.settings = $.extend( true, {}, $.validator.defaults, options );
        this.currentForm = form;
        this.init();
    };

    $.validator.format = function(source, params) {
        if ( arguments.length == 1 )
            return function() {
                var args = $.makeArray(arguments);
                args.unshift(source);
                return $.validator.format.apply( this, args );
            };
        if ( arguments.length > 2 && params.constructor != Array  ) {
            params = $.makeArray(arguments).slice(1);
        }
        if ( params.constructor != Array ) {
            params = [ params ];
        }
        $.each(params, function(i, n) {
            source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
        });
        return source;
    };

    $.extend($.validator, {

        defaults: {
            messages: {},
            groups: {},
            rules: {},
            errorClass: "error",
            validClass: "valid",
            errorElement: "label",
            focusInvalid: true,
            errorContainer: $( [] ),
            errorLabelContainer: $( [] ),
            onsubmit: true,
            ignore: ":hidden",
            ignoreTitle: false,
            onfocusin: function(element, event) {
                this.lastActive = element;

                // hide error label and remove error class on focus if enabled
                if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
                    this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
                    this.addWrapper(this.errorsFor(element)).hide();
                }
            },
            onfocusout: function(element, event) {
                if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
                    this.element(element);
                }
            },
            onkeyup: function(element, event) {
                if ( element.name in this.submitted || element == this.lastElement ) {
                    this.element(element);
                }
            },
            onclick: function(element, event) {
                // click on selects, radiobuttons and checkboxes
                if ( element.name in this.submitted )
                    this.element(element);
                // or option elements, check parent select in that case
                else if (element.parentNode.name in this.submitted)
                    this.element(element.parentNode);
            },
            highlight: function(element, errorClass, validClass) {
                if (element.type === 'radio') {
                    this.findByName(element.name).addClass(errorClass).removeClass(validClass);
                } else {
                    $(element).addClass(errorClass).removeClass(validClass);
                }
            },
            unhighlight: function(element, errorClass, validClass) {
                if (element.type === 'radio') {
                    this.findByName(element.name).removeClass(errorClass).addClass(validClass);
                } else {
                    $(element).removeClass(errorClass).addClass(validClass);
                }
            }
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
        setDefaults: function(settings) {
            $.extend( $.validator.defaults, settings );
        },

        messages: {
            required: "This field is required.",
            remote: "Please fix this field.",
            email: "Please enter a valid email address.",
            url: "Please enter a valid URL.",
            //date: "Please enter a valid date.",
            dateISO: "Please enter a valid date (ISO).",
            number: "Please enter a valid number.",
            digits: "Please enter only digits.",
            creditcard: "Please enter a valid credit card number.",
            equalTo: "Please enter the same value again.",
            accept: "Please enter a value with a valid extension.",
            maxlength: $.validator.format("Please enter no more than {0} characters."),
            minlength: $.validator.format("Please enter at least {0} characters."),
            rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
            range: $.validator.format("Please enter a value between {0} and {1}."),
            max: $.validator.format("Please enter a value less than or equal to {0}."),
            min: $.validator.format("Please enter a value greater than or equal to {0}.")
        },

        autoCreateRanges: false,

        prototype: {

            init: function() {
                this.labelContainer = $(this.settings.errorLabelContainer);
                this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
                this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
                this.submitted = {};
                this.valueCache = {};
                this.pendingRequest = 0;
                this.pending = {};
                this.invalid = {};
                this.reset();

                var groups = (this.groups = {});
                $.each(this.settings.groups, function(key, value) {
                    $.each(value.split(/\s/), function(index, name) {
                        groups[name] = key;
                    });
                });
                var rules = this.settings.rules;
                $.each(rules, function(key, value) {
                    rules[key] = $.validator.normalizeRule(value);
                });

                function delegate(event) {
                    var validator = $.data(this[0].form, "validator"),
                        eventType = "on" + event.type.replace(/^validate/, "");
                    validator.settings[eventType] && validator.settings[eventType].call(validator, this[0], event);
                }
                $(this.currentForm)
                    .validateDelegate("[type='text'], [type='password'], [type='file'], select, textarea, " +
                    "[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
                    "[type='email'], [type='datetime'], [type='date'], [type='month'], " +
                    "[type='week'], [type='time'], [type='datetime-local'], " +
                    "[type='range'], [type='color'] ",
                    "focusin focusout keyup", delegate)
                    .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate);

                if (this.settings.invalidHandler)
                    $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
            },

            // http://docs.jquery.com/Plugins/Validation/Validator/form
            form: function() {
                this.checkForm();
                $.extend(this.submitted, this.errorMap);
                this.invalid = $.extend({}, this.errorMap);
                if (!this.valid())
                    $(this.currentForm).triggerHandler("invalid-form", [this]);
                this.showErrors();
                return this.valid();
            },

            checkForm: function() {
                this.prepareForm();
                for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
                    this.check( elements[i] );
                }
                return this.valid();
            },

            // http://docs.jquery.com/Plugins/Validation/Validator/element
            element: function( element ) {
                element = this.validationTargetFor( this.clean( element ) );
                this.lastElement = element;
                this.prepareElement( element );
                this.currentElements = $(element);
                var result = this.check( element );
                if ( result ) {
                    delete this.invalid[element.name];
                } else {
                    this.invalid[element.name] = true;
                }
                if ( !this.numberOfInvalids() ) {
                    // Hide error containers on last error
                    this.toHide = this.toHide.add( this.containers );
                }
                this.showErrors();
                return result;
            },

            // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
            showErrors: function(errors) {
                if(errors) {
                    // add items to error list and map
                    $.extend( this.errorMap, errors );
                    this.errorList = [];
                    for ( var name in errors ) {
                        this.errorList.push({
                            message: errors[name],
                            element: this.findByName(name)[0]
                        });
                    }
                    // remove items from success list
                    this.successList = $.grep( this.successList, function(element) {
                        return !(element.name in errors);
                    });
                }
                this.settings.showErrors
                    ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
                    : this.defaultShowErrors();
            },

            // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
            resetForm: function() {
                if ( $.fn.resetForm )
                    $( this.currentForm ).resetForm();
                this.submitted = {};
                this.lastElement = null;
                this.prepareForm();
                this.hideErrors();
                this.elements().removeClass( this.settings.errorClass );
            },

            numberOfInvalids: function() {
                return this.objectLength(this.invalid);
            },

            objectLength: function( obj ) {
                var count = 0;
                for ( var i in obj )
                    count++;
                return count;
            },

            hideErrors: function() {
                this.addWrapper( this.toHide ).hide();
            },

            valid: function() {
                return this.size() == 0;
            },

            size: function() {
                return this.errorList.length;
            },

            focusInvalid: function() {
                if( this.settings.focusInvalid ) {
                    try {
                        $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
                            .filter(":visible")
                            .focus()
                            // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
                            .trigger("focusin");
                    } catch(e) {
                        // ignore IE throwing errors when focusing hidden elements
                    }
                }
            },

            findLastActive: function() {
                var lastActive = this.lastActive;
                return lastActive && $.grep(this.errorList, function(n) {
                    return n.element.name == lastActive.name;
                }).length == 1 && lastActive;
            },

            elements: function() {
                var validator = this,
                    rulesCache = {};

                // select all valid inputs inside the form (no submit or reset buttons)
                return $(this.currentForm)
                    .find("input, select, textarea")
                    .not(":submit, :reset, :image, [disabled]")
                    .not( this.settings.ignore )
                    .filter(function() {
                        !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

                        // select only the first element for each name, and only those with rules specified
                        if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
                            return false;

                        rulesCache[this.name] = true;
                        return true;
                    });
            },

            clean: function( selector ) {
                return $( selector )[0];
            },

            errors: function() {
                return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
            },

            reset: function() {
                this.successList = [];
                this.errorList = [];
                this.errorMap = {};
                this.toShow = $([]);
                this.toHide = $([]);
                this.currentElements = $([]);
            },

            prepareForm: function() {
                this.reset();
                this.toHide = this.errors().add( this.containers );
            },

            prepareElement: function( element ) {
                this.reset();
                this.toHide = this.errorsFor(element);
            },

            check: function( element ) {
                element = this.validationTargetFor( this.clean( element ) );

                var rules = $(element).rules();
                var dependencyMismatch = false;
                for (var method in rules ) {
                    var rule = { method: method, parameters: rules[method] };
                    try {
                        var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );

                        // if a method indicates that the field is optional and therefore valid,
                        // don't mark it as valid when there are no other rules
                        if ( result == "dependency-mismatch" ) {
                            dependencyMismatch = true;
                            continue;
                        }
                        dependencyMismatch = false;

                        if ( result == "pending" ) {
                            this.toHide = this.toHide.not( this.errorsFor(element) );
                            return;
                        }

                        if( !result ) {
                            this.formatAndAdd( element, rule );
                            return false;
                        }
                    } catch(e) {
                        this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
                            + ", check the '" + rule.method + "' method", e);
                        throw e;
                    }
                }
                if (dependencyMismatch)
                    return;
                if ( this.objectLength(rules) )
                    this.successList.push(element);
                return true;
            },

            // return the custom message for the given element and validation method
            // specified in the element's "messages" metadata
            customMetaMessage: function(element, method) {
                if (!$.metadata)
                    return;

                var meta = this.settings.meta
                    ? $(element).metadata()[this.settings.meta]
                    : $(element).metadata();

                return meta && meta.messages && meta.messages[method];
            },

            // return the custom message for the given element name and validation method
            customMessage: function( name, method ) {
                var m = this.settings.messages[name];
                return m && (m.constructor == String
                    ? m
                    : m[method]);
            },

            // return the first defined argument, allowing empty strings
            findDefined: function() {
                for(var i = 0; i < arguments.length; i++) {
                    if (arguments[i] !== undefined)
                        return arguments[i];
                }
                return undefined;
            },

            defaultMessage: function( element, method) {
                return this.findDefined(
                    this.customMessage( element.name, method ),
                    this.customMetaMessage( element, method ),
                    // title is never undefined, so handle empty string as undefined
                    !this.settings.ignoreTitle && element.title || undefined,
                    $.validator.messages[method],
                    "<strong>Warning: No message defined for " + element.name + "</strong>"
                );
            },

            formatAndAdd: function( element, rule ) {
                var message = this.defaultMessage( element, rule.method ),
                    theregex = /\$?\{(\d+)\}/g;
                if ( typeof message == "function" ) {
                    message = message.call(this, rule.parameters, element);
                } else if (theregex.test(message)) {
                    message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
                }
                this.errorList.push({
                    message: message,
                    element: element
                });

                this.errorMap[element.name] = message;
                this.submitted[element.name] = message;
            },

            addWrapper: function(toToggle) {
                if ( this.settings.wrapper )
                    toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
                return toToggle;
            },

            defaultShowErrors: function() {
                for ( var i = 0; this.errorList[i]; i++ ) {
                    var error = this.errorList[i];
                    this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
                    this.showLabel( error.element, error.message );
                }
                if( this.errorList.length ) {
                    this.toShow = this.toShow.add( this.containers );
                }
                if (this.settings.success) {
                    for ( var i = 0; this.successList[i]; i++ ) {
                        this.showLabel( this.successList[i] );
                    }
                }
                if (this.settings.unhighlight) {
                    for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
                        this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
                    }
                }
                this.toHide = this.toHide.not( this.toShow );
                this.hideErrors();
                this.addWrapper( this.toShow ).show();
            },

            validElements: function() {
                return this.currentElements.not(this.invalidElements());
            },

            invalidElements: function() {
                return $(this.errorList).map(function() {
                    return this.element;
                });
            },

            showLabel: function(element, message) {
                var label = this.errorsFor( element );
                if ( label.length ) {
                    // refresh error/success class
                    label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );

                    // check if we have a generated label, replace the message then
                    label.attr("generated") && label.html(message);
                } else {
                    // create label
                    label = $("<" + this.settings.errorElement + "/>")
                        .attr({"for":  this.idOrName(element), generated: true})
                        .addClass(this.settings.errorClass)
                        .html(message || "");
                    if ( this.settings.wrapper ) {
                        // make sure the element is visible, even in IE
                        // actually showing the wrapped element is handled elsewhere
                        label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
                    }
                    if ( !this.labelContainer.append(label).length )
                        this.settings.errorPlacement
                            ? this.settings.errorPlacement(label, $(element) )
                            : label.insertAfter(element);
                }
                if ( !message && this.settings.success ) {
                    label.text("");
                    typeof this.settings.success == "string"
                        ? label.addClass( this.settings.success )
                        : this.settings.success( label );
                }
                this.toShow = this.toShow.add(label);
            },

            errorsFor: function(element) {
                var name = this.idOrName(element);
                return this.errors().filter(function() {
                    return $(this).attr('for') == name;
                });
            },

            idOrName: function(element) {
                return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
            },

            validationTargetFor: function(element) {
                // if radio/checkbox, validate first element in group instead
                if (this.checkable(element)) {
                    element = this.findByName( element.name ).not(this.settings.ignore)[0];
                }
                return element;
            },

            checkable: function( element ) {
                return /radio|checkbox/i.test(element.type);
            },

            findByName: function( name ) {
                // select by name and filter by form for performance over form.find("[name=...]")
                var form = this.currentForm;
                return $(document.getElementsByName(name)).map(function(index, element) {
                    return element.form == form && element.name == name && element  || null;
                });
            },

            getLength: function(value, element) {
                switch( element.nodeName.toLowerCase() ) {
                    case 'select':
                        return $("option:selected", element).length;
                    case 'input':
                        if( this.checkable( element) )
                            return this.findByName(element.name).filter(':checked').length;
                }
                return value.length;
            },

            depend: function(param, element) {
                return this.dependTypes[typeof param]
                    ? this.dependTypes[typeof param](param, element)
                    : true;
            },

            dependTypes: {
                "boolean": function(param, element) {
                    return param;
                },
                "string": function(param, element) {
                    return !!$(param, element.form).length;
                },
                "function": function(param, element) {
                    return param(element);
                }
            },

            optional: function(element) {
                return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
            },

            startRequest: function(element) {
                if (!this.pending[element.name]) {
                    this.pendingRequest++;
                    this.pending[element.name] = true;
                }
            },

            stopRequest: function(element, valid) {
                this.pendingRequest--;
                // sometimes synchronization fails, make sure pendingRequest is never < 0
                if (this.pendingRequest < 0)
                    this.pendingRequest = 0;
                delete this.pending[element.name];
                if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
                    $(this.currentForm).submit();
                    this.formSubmitted = false;
                } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
                    $(this.currentForm).triggerHandler("invalid-form", [this]);
                    this.formSubmitted = false;
                }
            },

            previousValue: function(element) {
                return $.data(element, "previousValue") || $.data(element, "previousValue", {
                    old: null,
                    valid: true,
                    message: this.defaultMessage( element, "remote" )
                });
            }

        },

        classRuleSettings: {
            required: {required: true},
            email: {email: true},
            url: {url: true},
            date: {date: true},
            dateISO: {dateISO: true},
            dateDE: {dateDE: true},
            number: {number: true},
            numberDE: {numberDE: true},
            digits: {digits: true},
            creditcard: {creditcard: true}
        },

        addClassRules: function(className, rules) {
            className.constructor == String ?
                this.classRuleSettings[className] = rules :
                $.extend(this.classRuleSettings, className);
        },

        classRules: function(element) {
            var rules = {};
            var classes = $(element).attr('class');
            classes && $.each(classes.split(' '), function() {
                if (this in $.validator.classRuleSettings) {
                    $.extend(rules, $.validator.classRuleSettings[this]);
                }
            });
            return rules;
        },

        attributeRules: function(element) {
            var rules = {};
            var $element = $(element);

            for (var method in $.validator.methods) {
                var value;
                // If .prop exists (jQuery >= 1.6), use it to get true/false for required
                if (method === 'required' && typeof $.fn.prop === 'function') {
                    value = $element.prop(method);
                } else {
                    value = $element.attr(method);
                }
                if (value) {
                    rules[method] = value;
                } else if ($element[0].getAttribute("type") === method) {
                    rules[method] = true;
                }
            }

            // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
            if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
                delete rules.maxlength;
            }

            return rules;
        },

        metadataRules: function(element) {
            if (!$.metadata) return {};

            var meta = $.data(element.form, 'validator').settings.meta;
            return meta ?
                $(element).metadata()[meta] :
                $(element).metadata();
        },

        staticRules: function(element) {
            var rules = {};
            var validator = $.data(element.form, 'validator');
            if (validator.settings.rules) {
                rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
            }
            return rules;
        },

        normalizeRules: function(rules, element) {
            // handle dependency check
            $.each(rules, function(prop, val) {
                // ignore rule when param is explicitly false, eg. required:false
                if (val === false) {
                    delete rules[prop];
                    return;
                }
                if (val.param || val.depends) {
                    var keepRule = true;
                    switch (typeof val.depends) {
                        case "string":
                            keepRule = !!$(val.depends, element.form).length;
                            break;
                        case "function":
                            keepRule = val.depends.call(element, element);
                            break;
                    }
                    if (keepRule) {
                        rules[prop] = val.param !== undefined ? val.param : true;
                    } else {
                        delete rules[prop];
                    }
                }
            });

            // evaluate parameters
            $.each(rules, function(rule, parameter) {
                rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
            });

            // clean number parameters
            $.each(['minlength', 'maxlength', 'min', 'max'], function() {
                if (rules[this]) {
                    rules[this] = Number(rules[this]);
                }
            });
            $.each(['rangelength', 'range'], function() {
                if (rules[this]) {
                    rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
                }
            });

            if ($.validator.autoCreateRanges) {
                // auto-create ranges
                if (rules.min && rules.max) {
                    rules.range = [rules.min, rules.max];
                    delete rules.min;
                    delete rules.max;
                }
                if (rules.minlength && rules.maxlength) {
                    rules.rangelength = [rules.minlength, rules.maxlength];
                    delete rules.minlength;
                    delete rules.maxlength;
                }
            }

            // To support custom messages in metadata ignore rule methods titled "messages"
            if (rules.messages) {
                delete rules.messages;
            }

            return rules;
        },

        // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
        normalizeRule: function(data) {
            if( typeof data == "string" ) {
                var transformed = {};
                $.each(data.split(/\s/), function() {
                    transformed[this] = true;
                });
                data = transformed;
            }
            return data;
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
        addMethod: function(name, method, message) {
            $.validator.methods[name] = method;
            $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
            if (method.length < 3) {
                $.validator.addClassRules(name, $.validator.normalizeRule(name));
            }
        },

        methods: {

            // http://docs.jquery.com/Plugins/Validation/Methods/required
            required: function(value, element, param) {
                // check if dependency is met
                if ( !this.depend(param, element) )
                    return "dependency-mismatch";
                switch( element.nodeName.toLowerCase() ) {
                    case 'select':
                        // could be an array for select-multiple or a string, both are fine this way
                        var val = $(element).val();
                        return val && val.length > 0;
                    case 'input':
                        if ( this.checkable(element) )
                            return this.getLength(value, element) > 0;
                    default:
                        return $.trim(value).length > 0;
                }
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/remote
            remote: function(value, element, param) {
                if ( this.optional(element) )
                    return "dependency-mismatch";

                var previous = this.previousValue(element);
                if (!this.settings.messages[element.name] )
                    this.settings.messages[element.name] = {};
                previous.originalMessage = this.settings.messages[element.name].remote;
                this.settings.messages[element.name].remote = previous.message;

                param = typeof param == "string" && {url:param} || param;

                if ( this.pending[element.name] ) {
                    return "pending";
                }
                if ( previous.old === value ) {
                    return previous.valid;
                }

                previous.old = value;
                var validator = this;
                this.startRequest(element);
                var data = {};
                data[element.name] = value;
                $.ajax($.extend(true, {
                    url: param,
                    mode: "abort",
                    port: "validate" + element.name,
                    dataType: "json",
                    data: data,
                    success: function(response) {
                        validator.settings.messages[element.name].remote = previous.originalMessage;
                        var valid = response === true;
                        if ( valid ) {
                            var submitted = validator.formSubmitted;
                            validator.prepareElement(element);
                            validator.formSubmitted = submitted;
                            validator.successList.push(element);
                            validator.showErrors();
                        } else {
                            var errors = {};
                            var message = response || validator.defaultMessage( element, "remote" );
                            errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
                            validator.showErrors(errors);
                        }
                        previous.valid = valid;
                        validator.stopRequest(element, valid);
                    }
                }, param));
                return "pending";
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/minlength
            minlength: function(value, element, param) {
                return this.optional(element) || this.getLength($.trim(value), element) >= param;
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
            maxlength: function(value, element, param) {
                return this.optional(element) || this.getLength($.trim(value), element) <= param;
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
            rangelength: function(value, element, param) {
                var length = this.getLength($.trim(value), element);
                return this.optional(element) || ( length >= param[0] && length <= param[1] );
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/min
            min: function( value, element, param ) {
                return this.optional(element) || value >= param;
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/max
            max: function( value, element, param ) {
                return this.optional(element) || value <= param;
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/range
            range: function( value, element, param ) {
                return this.optional(element) || ( value >= param[0] && value <= param[1] );
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/email
            email: function(value, element) {
                // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
                return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/url
            url: function(value, element) {
                // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
                return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/date
            date: function(value, element) {
                return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
            dateISO: function(value, element) {
                return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/number
            number: function(value, element) {
                return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/digits
            digits: function(value, element) {
                return this.optional(element) || /^\d+$/.test(value);
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
            // based on http://en.wikipedia.org/wiki/Luhn
            creditcard: function(value, element) {
                if ( this.optional(element) )
                    return "dependency-mismatch";
                // accept only spaces, digits and dashes
                if (/[^0-9 -]+/.test(value))
                    return false;
                var nCheck = 0,
                    nDigit = 0,
                    bEven = false;

                value = value.replace(/\D/g, "");

                for (var n = value.length - 1; n >= 0; n--) {
                    var cDigit = value.charAt(n);
                    var nDigit = parseInt(cDigit, 10);
                    if (bEven) {
                        if ((nDigit *= 2) > 9)
                            nDigit -= 9;
                    }
                    nCheck += nDigit;
                    bEven = !bEven;
                }

                return (nCheck % 10) == 0;
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/accept
            accept: function(value, element, param) {
                param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
                return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
            },

            // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
            equalTo: function(value, element, param) {
                // bind to the blur event of the target in order to revalidate whenever the target field is updated
                // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
                var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
                    $(element).valid();
                });
                return value == target.val();
            }

        }

    });

// deprecated, use $.validator.format instead
    $.format = $.validator.format;

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
;(function($) {
    var pendingRequests = {};
    // Use a prefilter if available (1.5+)
    if ( $.ajaxPrefilter ) {
        $.ajaxPrefilter(function(settings, _, xhr) {
            var port = settings.port;
            if (settings.mode == "abort") {
                if ( pendingRequests[port] ) {
                    pendingRequests[port].abort();
                }
                pendingRequests[port] = xhr;
            }
        });
    } else {
        // Proxy ajax
        var ajax = $.ajax;
        $.ajax = function(settings) {
            var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
                port = ( "port" in settings ? settings : $.ajaxSettings ).port;
            if (mode == "abort") {
                if ( pendingRequests[port] ) {
                    pendingRequests[port].abort();
                }
                return (pendingRequests[port] = ajax.apply(this, arguments));
            }
            return ajax.apply(this, arguments);
        };
    }
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
;(function($) {
    // only implement if not provided by jQuery core (since 1.4)
    // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
    if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
        $.each({
            focus: 'focusin',
            blur: 'focusout'
        }, function( original, fix ){
            $.event.special[fix] = {
                setup:function() {
                    this.addEventListener( original, handler, true );
                },
                teardown:function() {
                    this.removeEventListener( original, handler, true );
                },
                handler: function(e) {
                    arguments[0] = $.event.fix(e);
                    arguments[0].type = fix;
                    return $.event.handle.apply(this, arguments);
                }
            };
            function handler(e) {
                e = $.event.fix(e);
                e.type = fix;
                return $.event.handle.call(this, e);
            }
        });
    };
    $.extend($.fn, {
        validateDelegate: function(delegate, type, handler) {
            return this.bind(type, function(event) {
                var target = $(event.target);
                if (target.is(delegate)) {
                    return handler.apply(target, arguments);
                }
            });
        }
    });
})(jQuery);
/* Missing file: new/common/js/global_storage.js  */
