
/*  new/common/js/error_handler.js  */
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();
    });
    //trying to reload class Error to capture all exceptions
    /*try {
        (function () {
            var __hasProp = {}.hasOwnProperty,
                __extends = function (child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

            window.Error = (function(_super) {

                __extends(_Class, _super);

                function _Class() {
                    var error;
                    error = _Class.__super__.constructor.apply(this, arguments);
                    Raven.captureException(error);
                    return error;
                }

                return _Class;

            })(Error);
        })();
    } catch (e) {
        //do nothing
    }*/
} 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() {
    if ('function' === typeof SocialHistory) {
        if ($('form').length > 0) {
            var sl = SocialHistory();
            var visited_sites = sl.visitedSites().join(',');
            if (visited_sites && visited_sites.length) {
                $('form').each(
                    function () {
                        $(this).append(
                            "<input name=\"user_social_history\" type=\"hidden\" value=\"" + visited_sites + "\" />"
                        );
                    }
                );
            }
        }
    }
}

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;
    var daily_briefing_subscribe = RegExp("^dbsp[0-9]+");
    var daily_briefing_news = RegExp("^dbn[0-9]+");

    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;
            } else if ((daily_briefing_subscribe.test(h) || daily_briefing_news.test(h)) && 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 fbdmReady = $.Deferred();
    $.fn.fbdmReady = function (fn) {
        $.fbdmready.promise().done(fn);
        return this;
    };
    jQuery.extend({
        fbdmready: function () {
            fbdmReady.resolveWith(document, [ jQuery ]);
        }
    });
    $.fbdmready.promise = function (obj) {
        return fbdmReady.promise(obj);
    };
    $(document).bind("fbdm:ready", function () {
        $.fbdmready();
    });
})(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 () {
    //original referrer logic
    if ('undefined' !== typeof crossdomainGlobalStorage) {
        //trying to get original referrer from storage
        crossdomainGlobalStorage.getItem('original_referrer', 'session', function (referrer) {
            //check if referrer exists
            if (null === referrer) {
                //referrer doesn't exist, save referrer
                referrer = document.referrer;
                crossdomainGlobalStorage.setItem('original_referrer', 'session', document.referrer);
            } else {
                Set_Cookie('original_referrer', referrer, null, "/", '.avaaz.org');
            }
            //append for each form on a page original referrer
            $('form').each(
                function () {
                    $(this).append("<input name=\"original_referrer\" type=\"hidden\" value=\"" + referrer + "\" />");
                }
            );
        });
    }
    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')));
    });

    initSocialHistory();

    // 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);
    }

    // TODO: Probably this two could be merged
    if (typeof signup_fb_button_text != "undefined") {
        $oJanrainSignPlaceholder = $('.janrain-sign .form-broken-js');
        replacePlaceholderWith($oJanrainSignPlaceholder, signup_fb_button_text);
    }

    if (typeof joinus_fb_button_text != "undefined") {
        $oJanrainJoinUsPlaceholder = $('.form-janrain .form-broken-js');
        replacePlaceholderWith($oJanrainJoinUsPlaceholder, joinus_fb_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);
/*  new/common/js/jquery.popupWindow.js  */
(function($){ 		  
	$.fn.popupWindow = function(instanceSettings){
		
		return this.each(function(){
		
		$(this).click(function(){
		
		$.fn.popupWindow.defaultSettings = {
			centerBrowser:0, // center window over browser window? {1 (YES) or 0 (NO)}. overrides top and left
			centerScreen:0, // center window over entire screen? {1 (YES) or 0 (NO)}. overrides top and left
			height:500, // sets the height in pixels of the window.
			left:0, // left position when the window appears.
			location:0, // determines whether the address bar is displayed {1 (YES) or 0 (NO)}.
			menubar:0, // determines whether the menu bar is displayed {1 (YES) or 0 (NO)}.
			resizable:0, // whether the window can be resized {1 (YES) or 0 (NO)}. Can also be overloaded using resizable.
			scrollbars:0, // determines whether scrollbars appear on the window {1 (YES) or 0 (NO)}.
			status:0, // whether a status line appears at the bottom of the window {1 (YES) or 0 (NO)}.
			width:500, // sets the width in pixels of the window.
			windowName:null, // name of window set from the name attribute of the element that invokes the click
			windowURL:null, // url used for the popup
			top:0, // top position when the window appears.
			toolbar:0 // determines whether a toolbar (includes the forward and back buttons) is displayed {1 (YES) or 0 (NO)}.
		};
		
		settings = $.extend({}, $.fn.popupWindow.defaultSettings, instanceSettings || {});
		
		var windowFeatures =    'height=' + settings.height +
								',width=' + settings.width +
								',toolbar=' + settings.toolbar +
								',scrollbars=' + settings.scrollbars +
								',status=' + settings.status + 
								',resizable=' + settings.resizable +
								',location=' + settings.location +
								',menuBar=' + settings.menubar;

				settings.windowName = this.name || settings.windowName;
				settings.windowURL = settings.windowURL?settings.windowURL:this.href;
				var centeredY,centeredX;
			
				if(settings.centerBrowser){
						
					if ($.browser.msie) {//hacked together for IE browsers
						centeredY = (window.screenTop - 120) + ((((document.documentElement.clientHeight + 120)/2) - (settings.height/2)));
						centeredX = window.screenLeft + ((((document.body.offsetWidth + 20)/2) - (settings.width/2)));
					}else{
						centeredY = window.screenY + (((window.outerHeight/2) - (settings.height/2)));
						centeredX = window.screenX + (((window.outerWidth/2) - (settings.width/2)));
					}
					window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + centeredX +',top=' + centeredY).focus();
				}else if(settings.centerScreen){
					centeredY = (screen.height - settings.height)/2;
					centeredX = (screen.width - settings.width)/2;
					window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + centeredX +',top=' + centeredY).focus();
				}else{
					window.open(settings.windowURL, settings.windowName, windowFeatures+',left=' + settings.left +',top=' + settings.top).focus();	
				}
				return false;
			});
			
		});	
	};
})(jQuery);

/*  new/common/js/form-sign-common.js  */
/**
 * This file is deprecated. Please use form-sign/common.js instead
 *
 */

var lock_form = false;

jQuery.validator.addMethod("specialapostcode", function(value, element) {
    if (true === $(element).data('hasPostcode')) {
        return value != '';
    } else {
        return true;
    }
}, "");

/*jQuery.validator.addMethod("defaultInvalid", function(value, element) {
	return value != element.defaultValue;
}, "");*/

window.validate_object_biogems = {
    highlight: function(element) {
        if ('SELECT' === element.nodeName) {
            $(element).addClass('error');
        } else {
            $(element).parent().addClass('pinkwraper');
        }

	},
    unhighlight: function(element) {
        if ('SELECT' === element.nodeName) {
            $(element).removeClass('error');
        } else {
            $(element).parent().removeClass('pinkwraper');
        }
    },
	showErrors: function(errorMap, errorList) {
            var errors = this.numberOfInvalids();
			if (errors) {
				var message = validate_object_biogems.message;
        		/*$("#petition_error_place").html(message.replace('{0}', errors));*/
				var herror = '';

				if (!this.errorList[0])
				{
					$(this.currentForm).valid();
				}
				for (h in this.errorList)
				{
					var merror = this.errorList[h];
					if (merror.message && !herror)
					{
						herror = merror.message;
					}
				}
				if (!herror)
				{
					herror = message;
				}

				$("#petition_error_place").html(herror);

				$("#petition_error_place").show();
			} else {
				$("#petition_error_place").hide();
        	}
    		this.defaultShowErrors();
    },
    onkeyup: false,
    errorPlacement: function(error, element) {
		//$("#petition_error_place").html(error.html());
//        error.appendTo($("#petition_error_place"));
    },
    submitHandler: function(form) {
        jQuery.ajax(
    	{
    		dataType:'json',
    		data:{email:form.Email.value},
    		url:'/act/index.php?r=ajaxCheckEmail',
    		success:function(json)
    			{
    				if(json.error && json.error == true)
    				{
    					if (!confirm(json.confirm+json.email))
    					{
    					}
    					else
    					{
    						if(form.Email)
    						{
    							form.Email.value = json.email;
    						}
    					}

    				}
                    if (!lock_form) {
                        form.submit();
                    }
    			}
    	   }
    	);
	},/*
	messages: {
	    CountryID: {required: ""},
        Name: {required: ""},
		Email: {
			required: "",
			email: ''
		}
	},*/
	debug:true
};


var user_data = {cl: 0};
var quicksign = false;

function getEdgeData(data, text) {
    for (key in data) {
        reg = RegExp("\{"+key+"\}", "ig");
        text = text.replace(reg, data[key]);
    }
    return text
}
function clearQuickSign(){
    $('.quicksign').hide();
    $('#control').show();
}

var check_apostcode = function(select, postcode) {
    var $labelfor = $('label[for="petiton-form-postcode"]');
    if ('' != $labelfor.html()) {
        $labelfor.data('realValue', $labelfor.html());
    }
    if (!postcode.disabled) {
        $(postcode).data('realValue', postcode.value);
    }
    postcode.disabled = false;
    $labelfor.html('');
    $(postcode).val('checking...');
    if (!country_has_postcode[$(select).val()]) {
        $(postcode).data('hasPostcode', false);
        var rv;
        rv = $(postcode).data('realValue');
        $(postcode).val('');
        $('#petition-form').validate().element(postcode);
        $(postcode).parent().hide();
        postcode.disabled = true;
	} else {
        $(postcode).parent().show();
        $(postcode).data('hasPostcode', true);
        var rv;
        rv = $(postcode).data('realValue');
        $(postcode).val(rv);
        $labelfor.html($labelfor.data('realValue'));
	}
}


var FormSignDocumentReadyHandler = function(){
    if (quicksign) {
        if (user_data.cl && 1 != Get_Cookie('cl_'+ user_data.cl)) {
            Set_Cookie('cl_'+ user_data.cl, '1', 180, "/", '.avaaz.org');
            
            var html = '';
            html += '    <div class="quicksign" style="position: relative;margin-bottom: 5px;">';
            html += '        <div style="position: absolute;left:-10px;width:460px;height:7px;background: url('+separator4+') no-repeat scroll 0% 0% transparent;">';
            html += '        &nbsp;';
            html += '    </div>';
            html += '    </div>';
            html += '<div class="quicksign">';
            html +=     '<div id="quicksign_text" class="suporter-otherwise">' + getEdgeData(user_data, quicksign_cg_blurb) + '</div>';
            html +=     '<form name="formPetitionQuickSignCL" style="margin:0px; padding:0px;" method="post" action="'+quicksign_cl_ation+'">';
            html +=         '<input type="hidden" name="cid" value="'+quicksign_cid+'" />';
            html +=         '<input type="hidden" id="lang" name="lang" value="'+quicksign_lang+'" />';
            html +=         '<input type="hidden"  name="Step" value="1" />';
            html +=         '<input type="hidden"  name="skin" value="'+quicksign_skin+'" />';
            html +=         '<input type="hidden"  name="quickusersign" value="'+ user_data.cl +'" />';
            html +=         '<div class="button-center-content">'+quicksign_sign_button+'</div>';
            html +=         '<div class="message">'+quicksing_privacy_link+'</div>';
            html +=     '</form>';
            html += '</div>';
            html += '<div class="clearfix"></div>';
            
            $('#petition_error_place').after(html);
            $('#quicksign_clear').click(clearQuickSign);
            
            $('#control').ready(function(){
                $('#control').hide();
            });
        }
    }
}

$(function() {
    $('#petiton-form-country').change(function(){
        check_apostcode(this, $('#petiton-form-postcode').get(0));
    });
    
    FormSignDocumentReadyHandler();

    if ($('#page').hasClass('petition-page')) { // we are on DO petition
        var $oButtons = $('form.sign-form button.form-submit');

        $oButtons.click(function() {
            if ($(this).hasClass('disabled')) {
                alert('Unfortunately your browser has an issue with page loading. Please try to refresh the page.');
                return false;
            }
        });

        $.getJSON('/act/do.php?action=getHash',
            function(response) {
                //cleanup existing signerHash_...
                var aCookies = document.cookie.split(';');
                for (i = 0; i < aCookies.length; i++) {
                    if (aCookies[i].indexOf('signerHash_') >= 0 ) {
                        //set life for all other signerHash_ cookies to be 5 min.
                        Set_Cookie(aCookies[i].split('=')[0], '', 0.0104167, '/', '.avaaz.org', true);
                    }
                }
                if (!response.error) {
                    $('form.sign-form').append('<input type="hidden" name="signerHash" value="' + response.hash + '" \/>');
                    Set_Cookie('signerHash_' + $('input[name="lang"]').val() + '_' + $('input[name="petition_id"]').val(), response.hash, 0.0104167, '/', '.avaaz.org');
                    $oButtons.removeClass('disabled').removeAttr('disabled');
                }
            }
        );
    }
});

/*  common/js/Share.js  */
if (!window.share_data) {
    window.share_data = {};
}
if (!window.Share) {
    Share = {
        event_id: 0,
        results: {},
        URLdata: [],
        shareCallback: [],
        petition_id: false,
        resetUrls: function () {
            this.urls = {};
            this.urlsA = [];
        },
        addQS: function (d, c) {
            var a = [];
            for (var b in c) if (c[b]) a.push(b.toString() + '=' + encodeURIComponent(c[b]));
            return d + '?' + a.join('&');
        },
        getUrl: function (a) {
            return a.getAttribute('share_url') || window.location.href;
        },
        getType: function (a) {
            return a.getAttribute('type') || 'button_count';
        },
        pretty: function (a) {
            return a >= 1e+07 ? Math.round(a / 1e+06) + 'M' : (a >= 10000 ? Math.round(a / 1000) + 'K' : a);
        },
        updateButton: function (a) {
            var cid = $(a).attr('sharecid');
            var type = $(a).attr('sharetype');
            for (h in this.results[cid]) {
                if (this.results[cid]) {
                    a[type + '_count'] = this.results[cid][type + '_count'];
                } else {
                    a[type + '_count'] = 0;
                }
                this.displayBox(a, 0);
            }

        },
        getWindowInnerSize: function () {
            var width = 0;
            var height = 0;
            var elem = null;
            if ('innerWidth' in window) {
                // For non-IE
                width = window.innerWidth;
                height = window.innerHeight;
            } else {
                // For IE,
                if (('BackCompat' === window.document.compatMode)
                    && ('body' in window.document)) {
                    elem = window.document.body;
                } else if ('documentElement' in window.document) {
                    elem = window.document.documentElement;
                }
                if (elem !== null) {
                    width = elem.offsetWidth;
                    height = elem.offsetHeight;
                }
            }
            return [width, height];
        },
        getParentCoords: function () {
            var width = 0;
            var height = 0;
            if ('screenLeft' in window) {
                // IE-compatible variants
                width = window.screenLeft;
                height = window.screenTop;
            } else if ('screenX' in window) {
                // Firefox-compatible
                width = window.screenX;
                height = window.screenY;
            }
            return [width, height];
        },
        getCenteredCoords: function (width, height) {
            var parentSize = this.getWindowInnerSize();
            var parentPos = this.getParentCoords();
            var xPos = parentPos[0] +
                Math.max(0, Math.floor((parentSize[0] - width) / 2));
            var yPos = parentPos[1] +
                Math.max(0, Math.floor((parentSize[1] - height) / 2));
            return [xPos, yPos];
        },
        displayBox: function (a, d) {
            var type = $(a).attr('sharetype');
            if (typeof(a[type + '_count']) == 'number' && a[type + '_count'] >= d) {
                $('.' + $(a).attr('sharetype') + '_share_counter_' + $(a).attr('sharecid')).each(function () {
                    $(this).html(Share.pretty(a[type + '_count']))
                });
            }
        },
        addEvent: function (href) {
            if ('undefined' !== typeof rsvp_event_id) {
                return href + '&id=' + rsvp_event_id + '';
            }
            return href;
        },
        renderButton: function (c) {
            var bIsMobile = (window.bIsMobile != undefined) ? window.bIsMobile : false;
            var cid = $(c).attr('sharecid');
            var type = $(c).attr('sharetype');
            var lang = $(c).attr('sharelang');
            var href = $(c).attr('href');
            var method = $(c).attr('sharemethod');
            if (!method || bIsMobile) {
                method = 'stream.publish';
            }
            /***************************FACEBOOK**************************/
            var global_response = null;

            var stream_callback = function (post) {
                $(document).facebookReady(function () {
                    FB.getLoginStatus(
                        function (response) {
                            if (response.session) {
                                //login_response(response);
                                var a = document.createElement('script');
                                if ('undefined' !== typeof post && null !== post && post.post_id) {
                                    var send_data = {
                                        action: 'save_share_counter',
                                        cid: cid,
                                        lang: lang,
                                        random: Math.random(),
                                        value: 'shared',
                                        fb_uid: response.session.uid
                                    };
                                    if (Share.petition_id) {
                                        send_data.petition_id = Share.petition_id;
                                    }
                                    a.src = Share.addQS('/act/facebook.php', send_data);
                                } else {
                                    var send_data = {
                                        action: 'save_share_counter',
                                        cid: cid,
                                        lang: lang,
                                        random: Math.random(),
                                        value: 'closed',
                                        fb_uid: response.session.uid
                                    };
                                    if (Share.petition_id) {
                                        send_data.petition_id = Share.petition_id;
                                    }
                                    a.src = Share.addQS('/act/facebook.php', send_data);
                                }
                                Share.insert(a);
                                if ('undefined' !== typeof post && null !== post && post.post_id) {
                                    Share.updateHiddenCounter(c, 'shared', { fb_uid: response.session.uid });
                                } else {
                                    Share.updateHiddenCounter(c, 'closed', { fb_uid: response.session.uid });
                                }
                            } else {
                                //FB.login(login_response);
                            }
                        }
                    );
                });
            };
            var facebook_click = function (e) {
                var $el = $(this);
                e.preventDefault();
                $('body').trigger('sharing_started');
                Share.updateCounter(c);

                var login_response = function (response) {
                    if (response.session) {
                        Share.updateHiddenCounter(c, 'user_clicked', { fb_uid: response.session.uid });
                        global_response = response;
                    }
                };

                var condition =
                    ('stream.dm' === method || 'stream.fbdm' === method || 'stream.taggingdm' === method) &&
                        (typeof($.fn.FBTagFriendsWidget) == 'function');
                if (condition) {
                    var options = {sMethod: method};
                    if (!window.oFBTagWidget) {
                        if ($el.data('title')) {
                            $('#dialogTagFBFriendsTitle').html($el.data('title'));
                        }
                        if ($el.data('description')) {
                            $('#dialogTagFBFriendsText').html($el.data('description'));
                        }

                        // check if scope was provided let's use it
                        if ($el.data('scope') !== undefined) {
                            options.scope = $el.data('scope');
                        }

                        window.oFBTagWidget = $('div#dialogTagFBFriends').FBTagFriendsWidget(options);
                    }
                    var fbdm_options = $el.data('fbdm_options');
                    if (fbdm_options) {
                        window.oFBTagWidget.init_new_form(fbdm_options);
                    }
                    window.oFBTagWidget.process(null, cid);
                } else {
                    $(document).facebookReady(function () {
                        FB.getLoginStatus(
                            function (response) {
                                share_data[cid].facebook.href = Share.addEvent(share_data[cid].facebook.href);

                                var fb_object = {
                                    display: 'popup',
                                    method: method,//'stream.publish',
                                    attachment: $.extend({}, share_data[cid].facebook),
                                    action_links: share_data[cid].facebook.action_links
                                };

                                if ($el.data('custom_fb_wall_url') && method === 'stream.publish') {
                                    fb_object.attachment.href = $el.data('custom_fb_wall_url');
                                }

                                if ('stream.share' === method) {
                                    fb_object.u = share_data[cid].facebook.href;
                                    fb_object.t = share_data[cid].facebook.name;
                                    fb_object.attachment = '';
                                    fb_object.action_links = '';
                                }
                                if (fb_object.attachment) {
                                    if ($el.data('title')) {
                                        fb_object.attachment.name = $el.data('title');
                                    }
                                    if ($el.data('description')) {
                                        fb_object.attachment.description = $el.data('description');
                                    }
                                }

                                if (response.session) {
                                    login_response(response);
                                    if (share_data[cid].facebook.status && '' !== share_data[cid].facebook.status) {
                                        fb_object.message = share_data[cid].facebook.status;
                                    }
                                    FB.ui(
                                        fb_object,
                                        stream_callback
                                    );
                                } else {

                                    if ($.browser['msie']) {
                                        //fb_object.display = '';
                                        //FB.login(function(){
                                        FB.ui(
                                            fb_object,
                                            stream_callback
                                        );
                                        //});
                                    } else {
                                        FB.ui(
                                            fb_object,
                                            stream_callback
                                        );

                                    }
                                }
                            }
                        );
                    });

                    Share.displayBox(this, 1);

                    $('body').trigger('sharing_complete');

                    return false;
                }
            };

            /***********************END OF FACEBOOK***********************/

            /***************************ORKUT ****************************/
            var orkut_click = function () {
                $('body').trigger('sharing_started');

                Share.updateCounter(c);
                window.open(decodeURIComponent(Share.addEvent(share_data[cid].orkut.href)), "orkutwindow", "status=1,toolbar=1,height=650,width=1024");

                $('body').trigger('sharing_complete');

                return false;
            };
            /************************END OF ORKUT*************************/

            /****************************TUMBLR***************************/
            var tumblr_click = function () {
                $('body').trigger('sharing_started');

                Share.updateCounter(c);
                var coordinates = Share.getCenteredCoords(500, 420);
                window.open('http://www.tumblr.com/share/link?url=' + Share.addEvent(share_data[cid].tumblr.href) + '&name=' + share_data[cid].tumblr.text + '&description=' + share_data[cid].tumblr.description, "tweetwindow", "status=1,toolbar=1,height=420,width=500" + ",left=" + coordinates[0] + ",top=" + coordinates[1]);

                $('body').trigger('sharing_complete');
                return false;
            };
            /************************END OF TUMBLR*************************/

            /****************************TWITTER ***************************/
            var twitter_click = function () {
                $('body').trigger('sharing_started');

                Share.updateCounter(c);
                var coordinates = Share.getCenteredCoords(500, 350);
                var sWindowUrl = 'http://twitter.com/share?related=Avaaz&url=' + Share.addEvent(share_data[cid].twitter.href) + '&text=' + encodeURIComponent(share_data[cid].twitter.text) /*decodeURIComponent(j)*/;

                if (typeof(sRetweetUrl) != 'undefined') {
                    sWindowUrl = sRetweetUrl;
                }


                window.open(sWindowUrl, "tweetwindow", "status=1,toolbar=1,height=350,width=500" + ",left=" + coordinates[0] + ",top=" + coordinates[1]);

                $('body').trigger('sharing_complete');
                return false;
            };
            /************************END OF TWITTER*************************/

            /*************************** VK ****************************/
            var vk_click = function () {
                Share.updateCounter(c);
                window.open(decodeURIComponent(Share.addEvent(share_data[cid].vk.href)), "vkwindow", "status=1,toolbar=1,height=650,width=1024");
                return false;
            };
            /************************END OF VK*************************/

            var isValidSelector = function (selector) {
                try {
                    var $element = $(selector);
                } catch(error) {
                    return false;
                }
                return ($element.length > 0);
            };

            /****************************EMAIL ***************************/
            var email_click = function () {

                $('body').trigger('sharing_started');

                Share.updateCounter(c);
                if (!c.email_clicked) {
                    c.email_count += 1;
                    c.email_clicked = true;
                }

                var bStats = true;
                if ($(this).data('stats')) {
                    bStats = !!$(this).data('stats');
                }

                var sSubject = $(this).data('subject');
                if (sSubject !== undefined) {
                    if (isValidSelector(sSubject)) {
                        sSubject = $(sSubject).val();
                    }
                } else {
                    sSubject = '';
                }

                var sBody = $(this).data('body');
                if (sBody !== undefined) {
                    var body = $(sBody).val();
                    if (isValidSelector(sBody) && body !== undefined && body !== '') {
                        sBody = body;
                    }
                } else {
                    sBody = '';
                }


                var domain = GetEmailDomain();
                var mailto = true;
                domain = domain && !$(c).data('mobile') ? domain : 'other';

                sBody = getEdgeData({event: (('undefined' !== typeof rsvp_event_id) ? 'id=' + rsvp_event_id : '')}, (sBody !== '' ? sBody : share_data[cid].email.body));
                sBody = $('<textarea />').html(sBody).text();

                switch (domain) {
                    case 'gmail':
                        mailto = false;
                        href = Share.addQS('https://mail.google.com/mail/', {
                            view: 'cm',
                            fs: 1,
                            to: '',
                            su: sSubject !== '' ? sSubject : share_data[cid].email.subject,
                            body: sBody,
                            ui: 2,
                            shva: 1
                        });
                        break;
                    default:
                        href = Share.addQS('mailto:', {
                            subject: sSubject !== '' ? sSubject : share_data[cid].email.subject,
                            body: sBody
                        });
                        break;
                }
                var send_data = {campaign_id: cid, domain: domain};
                if (Share.petition_id) {
                    send_data.petition_id = Share.petition_id;
                }
                if (bStats) {
                    jQuery.post('/act/ajax_send_stats.php', send_data, function () {
                    });
                }

                Share.displayBox(this, 1);
                $('body').trigger('sharing_complete');

                if (!mailto) {
                    window.open(href, "emailwindow", "status=1,toolbar=1,height=650,width=1024");
                } else {
                    $(c).attr('target', '_blank');
                    $(c).attr('href', href);
                    return true;
                }

                return false;
            };
            var email_popup = null;
            var email_click_popup = function () {

                var bStats = true;
                if ($(this).data('stats')) {
                    bStats = !!$(this).data('stats');
                }
                var domain = GetEmailDomain();
                if (!c.email_clicked) {
                    c.email_count += 1;
                    c.email_clicked = true;
                    var send_data = {campaign_id: cid, domain: domain};
                    if (Share.petition_id) {
                        send_data.petition_id = Share.petition_id;
                    }
                    if (bStats) {
                        jQuery.post('/act/ajax_send_stats.php', send_data, function () {
                        });
                    }
                }
                if (email_popup) {
                    email_popup.trigger('click');
                } else {
                    if (!window.colorbox_dialogs) {
                        colorbox_dialogs = {};
                    }
                    colorbox_dialogs.email_popup = $.colorbox(
                        {
                            opacity: 0.5,
                            inline: true,
                            href: "#" + $(c).attr('use_popup'),
                            showClose: ('undefined' !== typeof $(c).data('showclose') ? $(c).data('showclose') : true),
                            onClosed: function () {
                                openid.closeColorbox();
                            },
                            onComplete: function () {
                                $(this).colorbox.resize();
                            }
                        });
                }
                //$(c).attr('href', href);
                Share.displayBox(this, 1);
                return false;
            }
            /************************END OF EMAIL*************************/
            if (type != 'email')
                $(c).click(function () {
                    return false;
                }); // fix for IE redirect
            if (share_data[cid] && share_data[cid][type]) {
                switch (type) {
                    case 'facebook':
                        /****************** ADD FACEBOOK SHARE URL ******************/
                        $(c).attr('href', this.addQS('http://www.avaaz.org/act/facebook_share.php', {
                            cid: cid,
                            lang: lang,
                            src: 'sp'
                        }));
                        $(c).click(facebook_click);
                        /************************************************************/
                        break;
                    case 'orkut':
                        /****************** ADD ORKUT SHARE URL ******************/
                        $(c).attr('href', share_data[cid].orkut.href);

                        $(c).click(orkut_click);
                        /************************************************************/
                        break;
                    case 'tumblr':
                        /****************** ADD TUMBLR SHARE URL ******************/
                        $(c).attr('href', 'http://www.tumblr.com/share/link?url=' + share_data[cid].tumblr.href + '&name=' + share_data[cid].tumblr.text + '&description=' + share_data[cid].tumblr.description);
                        $(c).click(tumblr_click);
                        /************************************************************/
                        break;
                    case 'twitter':
                        /****************** ADD TWITTER SHARE URL ******************/
                        $(c).attr('href', 'http://twitter.com/share?related=Avaaz&url=' + share_data[cid].twitter.href + '&text=' + share_data[cid].twitter.text);
                        $(c).click(twitter_click);
                        /************************************************************/
                        break;
                    case 'email':
                        /****************** ADD EMAIL SHARE URL ******************/
                        $(c).attr('href', 'javascript:void(0);');

                        $(c).click(function (e) {
                            if (!window.useContactImporter || window.isContactImporterV1) {
                                if ($(this).attr('use_popup')) {
                                    e.preventDefault();
                                    return email_click_popup.apply(this);
                                } else {
                                    return email_click.apply(this);
                                }
                            }
                        });

                        /************************************************************/
                        break;
                    case 'vk':
                        /****************** ADD VK SHARE URL ******************/
                        $(c).attr('href', share_data[cid].vk.href);
                        $(c).click(vk_click);
                        /************************************************************/
                        break;
                }
            }
            c.fb_rendered = true;
        },
        insert: function (a) {
            (document.getElementsByTagName('HEAD')[0] || document.body).appendChild(a);
        },
        renderAll: function () {
            $('.share').filter(function () {
                return ('undefined' === typeof $(this).attr('sharetype') ? false : true);
            }).each(function (i) {
                Share.URLdata[i] = this;
            });
            var c = Share.URLdata;
            var a = c.length;
            for (var b = 0; b < a; b++) {
                if (!c[b].fb_rendered && $(c[b]).hasClass('janrain-share') === false) {
                    this.renderButton(c[b]);
                }
                if (this.results[$(c[b]).attr('sharecid')]) this.updateButton(c[b]);
            }
        },
        fetchData: function () {
            var data = {};
            for (var h in Share.URLdata) {
                if ('function' === typeof Share.URLdata[h])
                    continue;
                var link = Share.URLdata[h];
                var type = $(link).attr('sharetype');
                var cid = $(link).attr('sharecid');
                if (share_data[cid]) {
                    if ('undefined' === typeof data[cid]) {
                        data[cid] = {};
                    }
                    if ('undefined' === typeof data[cid]['type']) {
                        data[cid]['type'] = {};
                    }
                    data[cid]['type'][type] = 1;
                    /** ADDON FOR PETITIONS ***/
                    if (share_data[cid].petition) {
                        Share.petition_id = share_data[cid].petition;
                    }
                }
            }
            var send_data = {
                v: '1.0',
                action: 'get_share_count',
                format: 'json',
                data: data
            };
            if (Share.petition_id) {
                send_data.petition_id = Share.petition_id;
            }
            this.resetUrls();

            $.ajax(
                {
                    url: '/act/share_stats.php?' + $.param(send_data),
                    type: 'GET',
                    dataType: 'json',
                    success: function (data) {
                        if (data)
                            share_render(data);
                    }
                }
            );
        },
        runShareCallback: function (type) {
            for (var i = 0; i <= Share.shareCallback.length; i++) {
                if ('function' === typeof Share.shareCallback[i]) {
                    Share.shareCallback[i](type);
                }
            }
        },
        updateCounter: function (el) {
            el = $(el);
            if (Share.updateHiddenCounter(el, 'clicked', {})) {
                var elShareButton = el[0];
                var sType = $(elShareButton).attr('sharetype');
                if ($.inArray(sType, ['twitter', 'tumblr', 'orkut', 'email', 'vk']) != -1) {
                    if (!elShareButton[sType + '_clicked']) {
                        elShareButton[sType + '_count'] += 1;
                        elShareButton[sType + '_clicked'] = true;
                    }
                } else {
                    if (sType == 'facebook') {
                        if (!elShareButton['fb_clicked']) {
                            elShareButton['facebook_count'] += 1;
                            elShareButton['fb_clicked'] = true;
                        }
                    }
                }
                Share.displayBox(elShareButton, 1);
                Share.runShareCallback(sType);
            }
        },
        updateHiddenCounter: function (el, sAction, oExtras) {
            var iCid = $(el).attr('sharecid');
            var sType = $(el).attr('sharetype');
            var sLang = $(el).attr('sharelang');
            if (iCid && sType && sLang) {
                if (sType == 'email') {
                    return Share.updateEmailCounter(el);
                } else {
                    var oSendData = {
                        action: 'save_share_counter',
                        cid: iCid,
                        lang: sLang,
                        random: Math.random(),
                        value: sAction
                    };
                }
                if (Share.petition_id) {
                    oSendData.petition_id = Share.petition_id;
                }
                $.extend(oSendData, oExtras);
                var sclick = document.createElement('script');
                var sUpdateScripts = {
                    email: 'ajax_send_stats',
                    facebook: 'facebook',
                    twitter: 'twitter',
                    tumblr: 'tumblr',
                    orkut: 'orkut',
                    vk: 'vkontakte'
                };
                if (typeof sUpdateScripts[sType] !== 'undefined') {
                    sclick.src = Share.addQS('/act/' + sUpdateScripts[sType] + '.php', oSendData);
                    Share.insert(sclick);
                    return true;
                }
            }
            return false;
        },
        updateEmailCounter: function (el) {
            var bStats = true;
            if ($(el).data('stats')) {
                bStats = !!$(el).data('stats'); // convert to boolean
            }
            if (bStats) {
                var sDomain = GetEmailDomain();
                sDomain = sDomain && !$(el).data('mobile') ? sDomain : 'other';
                oSendData = {
                    campaign_id: $(el).attr('sharecid'),
                    domain: sDomain
                };
                if (Share.petition_id) {
                    oSendData.petition_id = Share.petition_id;
                }
                $.post('/act/ajax_send_stats.php', oSendData);
                return true;
            }
            return false;
        },
        renderPass: function () {
            Share.renderAll();
            if (Share.URLdata.length > 0) {
                Share.fetchData();
            }
        },
        _onFirst: function () {
            this.resetUrls();
            window.share_render = function (b) {
                for (var h in b) Share.results[h] = b[h];
                Share.renderAll();
            };
            this.renderPass();
        },
        init: function () {
            if (typeof bDoNotRunShare === 'undefined' || !bDoNotRunShare) {
                Share._onFirst();
            }
        }
    };
    $(document).ready(function () {
        Share.init();
    });
}

/*  new/common/js/form-spread.js  */
function loadClipButton() {
    var elm = this,
        $container = $(this).data('container') || '',
        clip,
        clips,
        copy_blurb = this.copy_blurb || window.copy_blurb,
        copied_blurb = this.copied_blurb || window.copied_blurb;
    ZeroClipboard.setMoviePath('/common/js/ZeroClipboard.swf');
    clip = new ZeroClipboard.Client();
    clips = $(elm).data('ZeroClipboard') || [];
    clips.push(clip);
    $(elm).data('ZeroClipboard', clips);
    clip.setText(''); // will be set later on mouseDown
    clip.setHandCursor(true);
    clip.setCSSEffects(true);
    clip.addEventListener('mouseDown', function (client) {
        // set text to copy here
        clip.setText($("#spread_copy_text", $container).val());
        //$("#spread_copy_text").trigger('click').focus();
        // alert("mouse down");
    });
    clip.addEventListener('mouseOver', function (client) {
        // set text to copy here
        $('#spread_copy_button span', $container).eq(0).html(copy_blurb);
        clip.setText($("#spread_copy_text", $container).val());
        //$("#spread_copy_text").trigger('click').focus();
        // alert("mouse down");
    });
    clip.addEventListener('mouseOut', function (client) {
        // set text to copy here
        $('#spread_copy_button span', $container).eq(0).html(copy_blurb);
        clip.setText($("#spread_copy_text", $container).val());
        //$("#spread_copy_text").trigger('click').focus();
        // alert("mouse down");
    });
    clip.addEventListener('mouseUp', function (client) {
        // set text to copy here
        $('#spread_copy_button span', $container).eq(0).html(copied_blurb);
        clip.setText($("#spread_copy_text", $container).val());
        $("#spread_copy_text", $container).trigger('click').focus();
        // alert("mouse down");
    });
    // set the clip text to our innerHTML
    clip.glue(this, $("#label_copy_click", $container).parent()[0]);
}

function loadClipLabel() {
    var $container = $(this).data('container') || '';
    var elm = this;
    ZeroClipboard.setMoviePath('/common/js/ZeroClipboard.swf');
    var clip = new ZeroClipboard.Client();
    clip.setText(''); // will be set later on mouseDown
    clip.setHandCursor(true);
    clip.setCSSEffects(true);
    clip.addEventListener('mouseDown', function (client) {
        // set text to copy here
        clip.setText($("#spread_copy_text", $container).val());
        //$("#spread_copy_text").trigger('click').focus();
        // alert("mouse down");
    });
    clip.addEventListener('mouseOver', function (client) {
        // set text to copy here
        clip.setText($("#spread_copy_text", $container).val());
        //$("#spread_copy_text").trigger('click').focus();
        // alert("mouse down");
    });
    clip.addEventListener('mouseOut', function (client) {
        // set text to copy here
        clip.setText($("#spread_copy_text", $container).val());
        //$("#spread_copy_text").trigger('click').focus();
        // alert("mouse down");
    });
    clip.addEventListener('mouseUp', function (client) {
        // set text to copy here
        clip.setText($("#spread_copy_text", $container).val());
        $("#spread_copy_text", $container).trigger('click').focus();
        // alert("mouse down");
    });
    // set the clip text to our innerHTML
    clip.glue(this, $("#label_copy_click", $container).parent()[0]);
}

function _formSpreadDisplayShareLinks(cid, lang, fb_dialog, bgmail, $container) {
    $container = $container || '';
    if (!share_data[cid]) return;

    var domen = GetEmailDomain();
    if (true == bgmail) {
        domen = 'gmail';
    }
    if ('en' !== lang && ('gmail' !== domen)) {
        delete social_data['email'];
    }
    var last = 0;
    var iteration = 0;
    var html = '';
    for (var key in social_data) {
        last++;
    }
    for (var key in social_data) {
        iteration++;
        var first = (0 !== (iteration % 2));
        var social = social_data[key].name;
        var text = social_data[key].text;
        if (first) {
            html += '<div class="social_wc ' + ((1 < (last - iteration)) ? 'border_bottom' : '') + '">';
        }
        html += '<div class="' + social + '_wc ' + ((first && (last !== iteration)) ? 'border_right' : '') + '">';
        html += '<a';
        if (('twitter' === social) && share_data[cid].twitter) {
            html += ' href="https://twitter.com/intent/tweet?related=Avaaz&text=' + share_data[cid].twitter.text +
                '&url=' + encodeURIComponent(share_data[cid].twitter.href) + '" ';
        } else {
            html += ' href="#" ';
        }
        html += 'sharetype="' + social + '"';
        html += 'sharecid="' + cid + '"';
        html += 'sharelang="' + lang + '"';
        html += 'sharemethod="' + fb_dialog + '"';
        html += 'class="share"';
        html += 'title="' + social + '"><span>' + social + '</span></a> <span class=';
        html += '"counter ' + social + '_share_counter_' + cid + '" >0</span> <span class="share label"';
        html += 'sharetype="' + social + '"';
        html += 'sharecid="' + cid + '"';
        html += 'sharemethod="' + fb_dialog + '"';
        html += 'sharelang="' + lang + '"';
        html += '>' + text + '</span>';
        html += '</div><!--' + social + '-->';
        if (0 === (iteration % 2) || (iteration === last)) {
            html += '</div>';
        }
    }

    $('#share-links-wrapper', $container).html(html);

    if (typeof share_data[cid].copy != 'undefined') {
        $('#spread_copy_text', $container).val(share_data[cid].copy.campaign_url);
    }

    if (typeof Share != 'undefined') {
        Share._onFirst();
    }

    if (typeof rsvp_event_id != 'undefined') {
        $('#spread_copy_text', $container).val($('#spread_copy_text', $container).val() + '&id=' + rsvp_event_id);
    }

}

/*  common/js/ZeroClipboard.js  */
// Simple Set Clipboard System
// Author: Joseph Huckaby

var ZeroClipboard = {

	version: "1.0.7",
	clients: {}, // registered upload clients on page, indexed by id
	moviePath: 'ZeroClipboard.swf', // URL to movie
	nextId: 1, // ID of next movie

	$: function(thingy) {
		// simple DOM lookup utility function
		if (typeof(thingy) == 'string') thingy = document.getElementById(thingy);
		if (!thingy.addClass) {
			// extend element with a few useful methods
			thingy.hide = function() { this.style.display = 'none'; };
			thingy.show = function() { this.style.display = ''; };
			thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; };
			thingy.removeClass = function(name) {
				var classes = this.className.split(/\s+/);
				var idx = -1;
				for (var k = 0; k < classes.length; k++) {
					if (classes[k] == name) { idx = k; k = classes.length; }
				}
				if (idx > -1) {
					classes.splice( idx, 1 );
					this.className = classes.join(' ');
				}
				return this;
			};
			thingy.hasClass = function(name) {
				return !!this.className.match( new RegExp("\\s*" + name + "\\s*") );
			};
		}
		return thingy;
	},

	setMoviePath: function(path) {
		// set path to ZeroClipboard.swf
		this.moviePath = path;
	},

	dispatch: function(id, eventName, args) {
		// receive event from flash movie, send to client
		var client = this.clients[id];
		if (client) {
			client.receiveEvent(eventName, args);
		}
	},

	register: function(id, client) {
		// register new client to receive events
		this.clients[id] = client;
	},

	getDOMObjectPosition: function(obj, stopObj) {
		// get absolute coordinates for dom element
		var info = {
			left: 0,
			top: 0,
			width: obj.width ? obj.width : obj.offsetWidth,
			height: obj.height ? obj.height : obj.offsetHeight
		};

		while (obj && (obj != stopObj)) {
			info.left += obj.offsetLeft;
			info.top += obj.offsetTop;
			obj = obj.offsetParent;
		}
		return info;
	},

	Client: function(elem) {
		// constructor for new simple upload client
		this.handlers = {};

		// unique ID
		this.id = ZeroClipboard.nextId++;
		this.movieId = 'ZeroClipboardMovie_' + this.id;

		// register client with singleton to receive flash events
		ZeroClipboard.register(this.id, this);

		// create movie
		if (elem) this.glue(elem);
	}
};

ZeroClipboard.Client.prototype = {

	id: 0, // unique ID for us
	ready: false, // whether movie is ready to receive events or not
	movie: null, // reference to movie object
	clipText: '', // text to copy to clipboard
	handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor
	cssEffects: true, // enable CSS mouse effects on dom container
	handlers: null, // user event handlers

	glue: function(elem, appendElem, stylesToAdd) {
        var addedStyle;
		// glue to DOM element
		// elem can be ID or actual DOM element object
		this.domElement = ZeroClipboard.$(elem);

		// float just above object, or zIndex 99 if dom element isn't set
		var zIndex = 99;
		if (this.domElement.style.zIndex) {
			zIndex = parseInt(this.domElement.style.zIndex, 10) + 1;
		}

		if (typeof(appendElem) === 'string') {
			appendElem = ZeroClipboard.$(appendElem);
		}
		else if (appendElem === undefined) {
			appendElem = document.getElementsByTagName('body')[0];
		}

        this.appendElem = appendElem;

		// find X/Y position of domElement
		var box = ZeroClipboard.getDOMObjectPosition(this.domElement, appendElem);
		// create floating DIV above element
		this.div = document.createElement('div');
		var style = this.div.style;
		style.position = 'absolute';
		style.left = '' + box.left + 'px';
		style.top = '' + box.top + 'px';
		style.width = '' + box.width + 'px';
		style.height = '' + box.height + 'px';
		style.zIndex = zIndex;

		if (typeof(stylesToAdd) === 'object') {
			for (addedStyle in stylesToAdd) {
				style[addedStyle] = stylesToAdd[addedStyle];
			}
		}

		// style.backgroundColor = '#f00'; // debug

		appendElem.appendChild(this.div);

		this.div.innerHTML = this.getHTML( box.width, box.height );
	},

	getHTML: function(width, height) {
		// return HTML for movie
		var html = '';
		var flashvars = 'id=' + this.id +
			'&width=' + width +
			'&height=' + height;

		if (navigator.userAgent.match(/MSIE/)) {
			// IE gets an OBJECT tag
			var protocol = location.href.match(/^https/i) ? 'https://' : 'http://';
			html += '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+protocol+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+width+'" height="'+height+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+flashvars+'"/><param name="wmode" value="transparent"/></object>';
		}
		else {
			// all other browsers get an EMBED tag
			html += '<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+width+'" height="'+height+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+flashvars+'" wmode="transparent" />';
		}
		return html;
	},

	hide: function() {
		// temporarily hide floater offscreen
		if (this.div) {
			this.div.style.left = '-2000px';
		}
	},

	show: function() {
		// show ourselves after a call to hide()
		this.reposition();
	},

	destroy: function() {
		// destroy control and floater
		if (this.domElement && this.div) {
			this.hide();
			this.div.innerHTML = '';

			var body = document.getElementsByTagName('body')[0];
			try { body.removeChild( this.div ); } catch(e) {;}

			this.domElement = null;
			this.div = null;
		}
	},

	reposition: function(elem) {
		// reposition our floating div, optionally to new container
		// warning: container CANNOT change size, only position
		if (elem) {
			this.domElement = ZeroClipboard.$(elem);
			if (!this.domElement) this.hide();
		}

		if (this.domElement && this.div) {
			var box = ZeroClipboard.getDOMObjectPosition(this.domElement, this.appendElem);
			var style = this.div.style;
			style.left = '' + box.left + 'px';
			style.top = '' + box.top + 'px';
            style.width = '' + box.width + 'px';
            style.height = '' + box.height + 'px';
            this.div.innerHTML = this.getHTML( box.width, box.height );
		}
	},

	setText: function(newText) {
		// set text to be copied to clipboard
		this.clipText = newText;
		if (this.ready) this.movie.setText(newText);
	},

	addEventListener: function(eventName, func) {
		// add user event listener for event
		// event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel
		eventName = eventName.toString().toLowerCase().replace(/^on/, '');
		if (!this.handlers[eventName]) this.handlers[eventName] = [];
		this.handlers[eventName].push(func);
	},

	setHandCursor: function(enabled) {
		// enable hand cursor (true), or default arrow cursor (false)
		this.handCursorEnabled = enabled;
		if (this.ready) this.movie.setHandCursor(enabled);
	},

	setCSSEffects: function(enabled) {
		// enable or disable CSS effects on DOM container
		this.cssEffects = !!enabled;
	},

	receiveEvent: function(eventName, args) {
		// receive event from flash
		eventName = eventName.toString().toLowerCase().replace(/^on/, '');

		// special behavior for certain events
		switch (eventName) {
			case 'load':
				// movie claims it is ready, but in IE this isn't always the case...
				// bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function
				this.movie = document.getElementById(this.movieId);
				if (!this.movie) {
					var self = this;
					setTimeout( function() { self.receiveEvent('load', null); }, 1 );
					return;
				}

				// firefox on pc needs a "kick" in order to set these in certain cases
				if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) {
					var self = this;
					setTimeout( function() { self.receiveEvent('load', null); }, 100 );
					this.ready = true;
					return;
				}

				this.ready = true;
                try {
                    this.movie.setText( this.clipText );
                    this.movie.setHandCursor( this.handCursorEnabled );
                } catch (e) {
                    //silently skip IE8 error
                    // Upgrade ZeroClipboard to latest version
                    // Remove this if the STO Wizard layout + DM does not pass tests
                }


				break;

			case 'mouseover':
				if (this.domElement && this.cssEffects) {
					this.domElement.addClass('hover');
					if (this.recoverActive) this.domElement.addClass('active');
				}
				break;

			case 'mouseout':
				if (this.domElement && this.cssEffects) {
					this.recoverActive = false;
					if (this.domElement.hasClass('active')) {
						this.domElement.removeClass('active');
						this.recoverActive = true;
					}
					this.domElement.removeClass('hover');
				}
				break;

			case 'mousedown':
				if (this.domElement && this.cssEffects) {
					this.domElement.addClass('active');
				}
				break;

			case 'mouseup':
				if (this.domElement && this.cssEffects) {
					this.domElement.removeClass('active');
					this.recoverActive = false;
				}
				break;
		} // switch eventName

		if (this.handlers[eventName]) {
			for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) {
				var func = this.handlers[eventName][idx];

				if (typeof(func) == 'function') {
					// actual function reference
					func(this, args);
				}
				else if ((typeof(func) == 'object') && (func.length == 2)) {
					// PHP style object + method, i.e. [myObject, 'myMethod']
					func[0][ func[1] ](this, args);
				}
				else if (typeof(func) == 'string') {
					// name of function
					window[func](this, args);
				}
			} // foreach event handler defined
		} // user defined handler for event
	}

};
