var myUtils = {
  purge: function(element) {
    element.childElements().each(function(s) {
      s.remove();
    });
  },
  
  getOpacity: function(element) {
    return element.getStyle('opacity');
  }
}

Element.addMethods(myUtils);

Array.prototype.remove = function(from, to) {
  var rest = this.slice((to || from) + 1 || this.length);
  this.length = from < 0 ? this.length + from : from;
  return this.push.apply(this, rest);
};

var CookieJar = Class.create();

CookieJar.prototype = {

	/**
	 * Append before all cookie names to differntiate them.
	 */
	appendString: "__CJ_",

	/**
	 * Initializes the cookie jar with the options.
	 */
	initialize: function(options) {
		this.options = {
			expires: 3600,		// seconds (1 hr)
			path: '',			// cookie path
			domain: '',			// cookie domain
			secure: ''			// secure ?
		};
		Object.extend(this.options, options || {});

		if (this.options.expires != '') {
			var date = new Date();
			date = new Date(date.getTime() + (this.options.expires * 1000));
			this.options.expires = '; expires=' + date.toGMTString();
		}
		if (this.options.path != '') {
			this.options.path = '; path=' + escape(this.options.path);
		}
		if (this.options.domain != '') {
			this.options.domain = '; domain=' + escape(this.options.domain);
		}
		if (this.options.secure == 'secure') {
			this.options.secure = '; secure';
		} else {
			this.options.secure = '';
		}
	},

	/**
	 * Adds a name values pair.
	 */
	put: function(name, value) {
		name = this.appendString + name;
		cookie = this.options;
		var type = typeof value;
		switch(type) {
		  case 'undefined':
		  case 'function' :
		  case 'unknown'  : return false;
		  case 'boolean'  : 
		  case 'string'   : 
		  case 'number'   : value = String(value.toString());
		}
		var cookie_str = name + "=" + escape(Object.toJSON(value));
		try {
			document.cookie = cookie_str + cookie.expires + cookie.path + cookie.domain + cookie.secure;
		} catch (e) {
			return false;
		}
		return true;
	},

	/**
	 * Removes a particular cookie (name value pair) form the Cookie Jar.
	 */
	remove: function(name) {
		name = this.appendString + name;
		cookie = this.options;
		try {
			var date = new Date();
			date.setTime(date.getTime() - (3600 * 1000));
			var expires = '; expires=' + date.toGMTString();
			document.cookie = name + "=" + expires + cookie.path + cookie.domain + cookie.secure;
		} catch (e) {
			return false;
		}
		return true;
	},

	/**
	 * Return a particular cookie by name;
	 */
	get: function(name) {
		name = this.appendString + name;
		var cookies = document.cookie.match(name + '=(.*?)(;|$)');
		if (cookies) {
			return (unescape(cookies[1])).evalJSON();
		} else {
			return null;
		}
	},

	/**
	 * Empties the Cookie Jar. Deletes all the cookies.
	 */
	empty: function() {
		keys = this.getKeys();
		size = keys.size();
		for(i=0; i<size; i++) {
			this.remove(keys[i]);
		}
	},

	/**
	 * Returns all cookies as a single object
	 */
	getPack: function() {
		pack = {};
		keys = this.getKeys();

		size = keys.size();
		for(i=0; i<size; i++) {
			pack[keys[i]] = this.get(keys[i]);
		}
		return pack;
	},

	/**
	 * Returns all keys.
	 */
	getKeys: function() {
		keys = $A();
		keyRe= /[^=; ]+(?=\=)/g;
		str  = document.cookie;
		CJRe = new RegExp("^" + this.appendString);
		while((match = keyRe.exec(str)) != undefined) {
			if (CJRe.test(match[0].strip())) {
				keys.push(match[0].strip().gsub("^" + this.appendString,""));
			}
		}
		return keys;
	}
};

var dlgBox = Class.create({
  initialize: function(params) {
    this.container = new Element('div', {'class':'dialogBox'});
    this.hdrBar = new Element('div', {'class':'headerBar'});
    this.hdrText = new Element('span', {'class':'headerText'});
    this.btnX = new Element('div', {'class':'buttonX'});
    this.spanX = new Element('span', {'class':'spanX'}).update('CLOSE');
    this.imgX = new Element('img', {'class':'imageX','src':'/templates/sngexposure/images/btn_close.png'});
    this.content = new Element('div', {'class':'dialogContent'});
    
    this.buildBaseDomObj();
    this.addBaseObservers();
    this.init(params);
  },
  
  buildBaseDomObj: function() {
    this.container.hide();
    this.setStyles();
    
    this.btnX.appendChild(this.imgX);
    this.btnX.appendChild(this.spanX);
    this.hdrBar.appendChild(this.btnX);
    this.hdrBar.appendChild(this.hdrText);
    this.hdrBar.appendChild(new Element('div', {'class':'clear'}));
  
    this.container.appendChild(this.hdrBar);
    this.container.appendChild(this.content);
  },
  
  addBaseObservers: function() {
    this.btnX.observer = this.hide.bindAsEventListener(this);
    this.btnX.observe('click', this.btnX.observer);
  },
  
  getDomObj: function() {
    return this.container;
  },
  
  center: function() {
    var vpWidth = document.viewport.getWidth();
    var fromLeft = Math.ceil(vpWidth / 2 - this.container.getWidth() / 2) + "px";
    this.container.setStyle({left:fromLeft, top:'40px', position:'fixed'});
  },
  
  hide: function(e) {
    if (e) { Event.stop(e); }
    var objThis = this;
    canvasOverlay.fade();
    if (this.container.visible()) {
      new Effect.Fade(this.container, {afterFinish: function() {
        if (typeof objThis.afterHide != "undefined") { objThis.afterHide(); }
      }});
    }
    if (typeof this.onHide != "undefined") { this.onHide(); }
  },
  
  show: function(params) {
    params = (params) ? params:{};
    params.width = (params.width) ? params.width:400;
    params.width += (typeof(params.width) == 'number') ? "px":"";
    
    this.container.setStyle({width:params.width});
    
    this.center();
    canvasOverlay.appear();
    if (!this.container.visible()) {
      new Effect.Appear(this.container);
    }
  },
  
  setHeader: function(strHdrText) {
    this.hdrText.update(strHdrText);
  },
  
  setHeight: function(newHeight) {
    /*if (!isNaN(newHeight)) {
      var isVisible = this.container.visible();
      if (!isVisible) {
        var tempTop = (newHeight + 100) * -1;
        this.container.setStyle({"top":tempTop + "px"});
        this.container.show();
      }
      var hdrLayout = new Element.Layout(this.hdrBar, true);
      var contentLayout = new Element.Layout(this.content);
      var hdrHeight = hdrLayout.get('padding-box-height');
      var contentPaddingTop = contentLayout.get('padding-top');
      var contentPaddingBottom = contentLayout.get('padding-bottom');
      var contentPadding = contentPaddingTop + contentPaddingBottom;
      var contentHeight = newHeight - hdrHeight - contentPadding;
      if (contentHeight > 50) {
        this.container.setStyle({"height":newHeight + "px"});
        this.content.setStyle({"height":contentHeight + "px"});
      }
      if (!isVisible) {
        this.container.hide();
        this.container.setStyle({"top":"40px"});
      }
    }*/
  },
  
  setStyles: function() {
    this.container.setStyle({"height":"400px"});
    //this.container.setStyle({'backgroundColor':'white', 'padding':'8px', 'position':'fixed', 'top':'40px', 'zIndex':'100', 'overflow':'hidden', 'border':'2px outset #C0C0C0'});
    //this.hdrBar.setStyle({'borderBottom':'1px solid black', 'fontWeight':'bold'});
    //this.hdrText.setStyle({'float':'left'});
    //this.btnX.setStyle({'border':'1px solid white', 'cursor':'pointer', 'float':'right', 'width':'60px'});
    //this.imgX.setStyle({'float':'right', 'height':'1em', 'width':'1em', 'marginLeft':'3px'});
    //this.spanX.setStyle({'float':'left', 'textAlign':'left'});
    //this.content.setStyle({'textAlign':'left'});
  }
});

var dlgEmail = Class.create(dlgBox, {
  init: function(params) {
    params = (params) ? params:{};
    
    this.presetMessage = (params.preset) ? params.preset:'';
    this.subject = (params.subject) ? params.subject:'<no subject>';
    
    this.messageType = params.type;
    this.form = new Element('form', {"style":"padding: 4px"});
    this.contEmailTop = new Element('div', {"id":"contEmailTop"});
    this.contFields = new Element('div', {"id":"contEmailFields"}); 
    
    this.labelTo = new Element('span', {"class":"formLabel"}).update('To:');
    this.contTo = new Element('div', {"class":"emailFormRow", "id":"contEmailTo"});
    this.inputTo = new Element('input', {"type":"text", "name":"emailTo", "id":"emailTo", "size":"40", "maxlength":"255", "class":"emailInputField"});
    
    this.labelFrom = new Element('span', {"class":"formLabel"}).update('From:');
    this.contFrom = new Element('div', {"class":"emailFormRow", "id":"emailFrom"});
    this.spanFrom = new Element('span', {"class":"emailFromText"}).update('Loading...');
    
    this.labelSubject = new Element('span', {"class":"formLabel"}).update('Subj:');
    this.contSubject = new Element('div', {"class":"emailFormRow", "id":"contEmailSubject"});
    this.inputSubject = new Element('input', {"type":"text", "name":"emailSubject", "id":"emailSubject", "size":"40", "maxlength":"255", "class":"emailInputField"});
    
    this.labelMessage = new Element('span', {"class":"formLabel"}).update('Message:');
    this.contMessage = new Element('div', {"class":"emailFormRow", "id":"contEmailMessage"});
    this.contMessagePreset = new Element('div');
    this.inputMessage = new dynTextArea();
    
    this.btnSend = new Element('input', {"type":"button", "name":"emailBtnSend", "id":"emailBtnSend", "value":"Send"});
    
    this.inputSubject.value = (params.subj) ? params.subj:params.subj;
    this.contMessagePreset.update(this.presetMessage);
    this.buildDomObj();
    this.addObservers();
    this.getUserData();
  },
  
  addObservers: function() {
    this.contMessage.observer = function() { this.inputMessage.field.focus(); }.bind(this);
    this.contMessage.observe('click', this.contMessage.observer);
    this.form.observe('submit', function(e) { Event.stop(e); });
    this.btnSend.observer = this.sendMessage.bindAsEventListener(this);
    this.btnSend.observe('click', this.btnSend.observer);
    this.btnX.mailObserver = this.clearForm.bindAsEventListener(this);
    this.btnX.observe('click', this.btnX.mailObserver);
  },
  
  buildDomObj: function() {
    this.contFrom.appendChild(this.labelFrom);
    this.contFrom.appendChild(this.spanFrom);
    this.contTo.appendChild(this.labelTo);
    this.contTo.appendChild(this.inputTo);
    this.contSubject.appendChild(this.labelSubject);
    this.contSubject.appendChild(this.inputSubject);
    this.contFields.appendChild(this.contFrom);
    this.contFields.appendChild(this.contTo);
    this.contFields.appendChild(this.contSubject);
    this.contMessage.appendChild(this.inputMessage.getDomObj());
    this.contMessage.appendChild(this.contMessagePreset);
    
    this.contEmailTop.appendChild(this.btnSend);
    this.contEmailTop.appendChild(this.contFields);
    this.contEmailTop.appendChild(new Element('div', {"class":"clear"}));
    //this.form.appendChild(this.btnSend);
    //this.form.appendChild(this.contFields);
    this.form.appendChild(this.contEmailTop);
    this.form.appendChild(this.contMessage);
    this.content.appendChild(this.form);
  },
  
  clearForm: function() {
    this.spanFrom.update('Loading...');
    this.form.reset();
    this.getUserData();
  },
  
  dlgReset: function() {
    this.form.reset();
  },
  
  getUserData: function() {
    new Ajax.Request('/', {
      method: 'post',
      parameters: { "option": "com_user", "task": "get_user_data" },
      onSuccess: this.getUserDataSuccess.bind(this),
      onFailure: this.getUserDataFailure.bind(this)
    });
  },
  
  getUserDataFailure: function(oXHR) {
    this.content.purge();
    this.content.appendChild(new Element('h4').update('Error ' + oXHR.status));
  },
  
  getUserDataSuccess: function(transport) {
    if (transport.responseText.isJSON) {
      var objResponse = transport.responseText.evalJSON(true);
      if (objResponse.id == 0) {
        this.spanFrom.update('You must be logged in to send messages.');
        this.overlay.show();
      } else {
        var fromAddr = objResponse.name + " &lt;" + objResponse.email + "&gt;";
        this.spanFrom.update(fromAddr);
      }
    } else {
      this.content.purge();
      this.content.appendChild(new Element('h4').update('Error:'));
      this.content.appendChild(new Element('p').update(transport.responseText));
    }
  },
  
  sendMessage: function() {
    var arErrList = this.getErrorList();
    if (arErrList.length == 0) {
      var params = {
        "task":"sendMail",
        "option":"com_sngajaxconduit",
        "to":$F(this.inputTo),
        "subj":$F(this.inputSubject),
        "pre":escape(this.presetMessage),
        "msg":escape($F(this.inputMessage.field))
      }
      new Ajax.Request('/', {
        method: 'post',
        parameters: params,
        onSuccess: function(transport) {
          if (!transport.responseText.isJSON()) {
            var errMsg = "The server responded with an error:\n";
            errMsg += transport.responseText;
            alert(errMsg);
          } else {
            var objResponse = transport.responseText.evalJSON();
            if (objResponse.arErr.length) {
              var errMsg = "An error was encountered while sending your e-mail message:\n";
              objResponse.arErr.each(function(s) { errMsg += " - " + s + "\n"; });
              alert(errMsg);
            } else {
              alert("Message sent.");
              this.dlgReset();
              this.hide();
            }
          }
        }.bind(this),
        onFailure: function() { alert('Send Message Failed'); }
      });
    } else {
      var alertMessage = "Can't send message:\n";
      arErrList.each(function(s) { alertMessage += " - " + s + "\n"; });
      alert(alertMessage);
    }
  },
  
  setMessage: function(msg) {
    this.presetMessage = msg;
    this.contMessagePreset.update(msg);
  },
  
  setSubject: function(msg) {
    this.subject = msg;
    this.inputSubject.value = msg;
  },
  
  setStyles: function() {
    this.container.setStyle({"height":"450px", "width":"450px"});
    this.content.setStyle({"padding":"0px", "height":"425px"});
  },
  
  getErrorList: function() {
    var arErrList = new Array();
    var emailRe = /^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))((\+[\d\w-]+)?@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|((\+[\d\w-]+)?@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i;
    if (!emailRe.test($F(this.inputTo))) {
      arErrList.push("To address invalid.");
    }
    if (!$F(this.inputSubject)) {
      arErrList.push("No subject specified");
    }
    return arErrList;
  }
});

var dynTextArea = Class.create({

  initialize: function(params) {
    
    params = (params) ? params:{};
    var cols = (typeof params.cols == "number") ? params.cols:37;
    var rows = (typeof params.rows == "number") ? params.rows:3;
    rows = (rows < 2) ? 2:rows;
    
    this.maxLen = (params.maxLen) ? params.maxlen:1024;
    this.container = new Element('div');
    if (params["class"]) { this.container.writeAttribute({"class":params["class"]})}
    
    this.field = new Element('textarea', {"name":this.name, "cols":cols, "rows":rows, "class":"dynTextarea"});
    
    this.addObservers();
  },
  
  getDomObj: function() {
    if (!this.container.firstDescendant()) {
      this.buildDomObj();
    }
    return this.container;
  },
  
  addObservers: function() {
    this.field.observer = this.resizer.bindAsEventListener(this);
    
    this.field.observe('click', this.field.observer);
    this.field.observe('keyup', this.field.observer);
  },
  
  buildDomObj: function() {
    this.container.appendChild(this.field);
  },
  
  resizer: function() {
    var lines = this.field.value.split('\n');
    var line = null;
    var newRows = lines.length;
    var oldRows = this.field.readAttribute('rows');
    for (var i = 0; i < lines.length; i++) {
      line = lines[i];
      if (line.length >= this.field.readAttribute('cols')) newRows += Math.floor(line.length / this.field.readAttribute('cols'));
    }
    if (newRows > this.field.readAttribute('rows')) this.field.writeAttribute({"rows":newRows});
    if (newRows < this.field.readAttribute('rows')) this.field.writeAttribute({"rows":Math.max(2, newRows)});
    if (this.field.getValue().length > this.maxLen) {
      this.field.setValue(this.field.getValue().substring(0, this.maxLen - 1));
      this.resizer();
    }
  }
});

var elIE = Class.create({
  initialize: function(el) {
    this.container = el;
    this.imgBlock = this.container.select('.imgBlock')[0];
    this.imgAnchor = this.imgBlock.select('a')[0];
    this.img = this.imgAnchor.select('img')[0];
    this.adjustImg();
  },
  
  adjustImg: function() {
    if(this.img.getHeight() < 80) {
      var h = this.img.getHeight() + "px";
      var w = this.img.getWidth() + "px";
      var offTop = Math.round((80 - this.img.getHeight()) / 2);
      this.img.absolutize();
      this.img.setStyle({top:'0px',left:'0px',width:w,height:h});
      new Effect.Move(this.img, {y: offTop, mode: 'relative' });
    }
  }
});

var elOverlay = Class.create({
  initialize: function(params) {
    this.containingEl = (params.contEl) ? $(params.contEl):$('canvas');
    this.container = new Element('div', {'class':'elOverlay'});
    this.pgEl = $(params.el) || this.containingEl;
    this.container.hide();
    this.animated = false;
    
    this.containingEl.appendChild(this.container);
  },
  
  appear: function() {
    var objThis = this;
    if (!this.animated) {
      if (!this.container.visible()) {
        this.animated = true;
        this.setPosition();
        new Effect.Appear(this.container, {duration:.5, from:0, to:.8, afterFinish:function(){objThis.animated = false;}});
      }
    } else {
      setTimeout(function(){objThis.appear()}, 10);
    }
  },
  
  fade: function() {
    var objThis = this;
    if (!this.animated) {
      if (this.container.visible()) {
        this.animated = true;
        new Effect.Fade(this.container, {duration: .5, afterFinish:function(){objThis.animated = false;}});
      }
    } else {
      setTimeout(function(){objThis.fade()}, 10);
    }
  },
  
  hide: function() {
    this.fade();
  },
  
  posFromCanvas: function() {
    var left = 0;
    var top = 0;
    var thisEl = this.pgEl;
    while (thisEl != this.containingEl)  {
      left += thisEl.offsetLeft;
      top += thisEl.offsetTop;
      thisEl = thisEl.getOffsetParent();
    }
    return {top:top, left:left};
  },
  
  setPosition: function() {
    var dims = this.pgEl.getDimensions();
    var height = dims.height + "px";
    var width = dims.width + "px";
    var pos = this.posFromCanvas();
    var left = pos.left + "px";
    var top = pos.top + "px";
    this.container.setStyle({'top':top, 'left':left, 'height':height, 'width':width});
  },
  
  show: function() {
    this.appear();
  }
});

var form_base = Class.create({
  blankCheck: function() {
    var objThis = this;
    if ($F(this.field)) {
      this.errorState = false;
    } else {
      this.errorState = true;
      if (!this.errorRunning) {
        this.pulse(this.blankCheck);
      }
    }
  },
  
  pulse: function(caller) {
    var objThis = this;
    this.errorRunning = true;
    new Effect.Appear(this.errMark, {afterFinish: function() {
      new Effect.Fade(objThis.errMark, {afterFinish: function() {
        objThis.errorRunning = false;
        var callerX = caller.bind(objThis);
        callerX();
      }});
    }});
  }
});

var form_emailValidator = Class.create(form_base, {
  initialize: function(params) {
    this.field = $(params.el);
    this.errMark = $(params.errEl);
    this.errorRunning = false;
    this.errorState = false;
    this.addObservers();
    this.emailValid();
  },
  
  addObservers: function() {
    this.field.observer = this.emailValid.bindAsEventListener(this);
    this.field.observe('keyup', this.field.observer);
  },
  
  emailValid: function() {
    if (!this.errorRunning) {
      var emailRe = /^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))((\+[\d\w-]+)?@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|((\+[\d\w-]+)?@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i;
      if (!emailRe.test($F(this.field))) {
        if (!this.errorRunning) {
          this.errorState = true
          this.pulse(this.emailValid);
        }
      } else {
        this.errorState = false;
        if (this.errMark.visible()) {
          this.errMark.hide();
        }
      }
    }
  }
});

var loginPanel = Class.create({
  initialize: function() {
    this.username = $('modlgn_username');
    this.password_dud = $('modlgn_passwd_dud');
    this.password = $('modlgn_passwd');
    this.btnSubmit = $('formLoginSubmit');
    
    this.addObservers();
  },
  
  addObservers: function() {
    this.username.focusObserver = this.uFocus.bindAsEventListener(this);
    this.username.blurObserver = this.uBlur.bindAsEventListener(this);
    this.password.focusObserver = this.pFocus.bindAsEventListener(this);
    this.password.blurObserver = this.pBlur.bindAsEventListener(this);
    
    this.username.observe('focus', this.username.focusObserver);
    this.username.observe('blur', this.username.blurObserver);
    this.password_dud.observe('focus', this.password.focusObserver);
    this.password.observe('blur', this.password.blurObserver);
  },
  
  pBlur: function() {
    if (this.password.value == "") {
      this.password.hide();
      this.password_dud.show();
    }
  },
  
  pFocus: function() {
    this.password_dud.hide();
    this.password.show();
    this.password.focus();
  },
  
  uBlur: function() {
    if (this.username.value == "") {
      this.username.value = "username";
      this.username.setStyle({"color":"#666666"});
    }
  },
  
  uFocus: function() {
    if (this.username.value == "username") {
      this.username.value = "";
      this.username.setStyle({"color":"black"});
    }
  }
  
});

var pageNotif = Class.create(dlgBox, {
  init: function() {
    this.container.setStyle({height:'400px'});
    this.content.update($('notifList').innerHTML);
    this.setHeader('Page Notifications');
  },
  
  hide: function() {
    canvasOverlay.fade();
    if (this.container.visible()) {
      this.content.setStyle({overflow:'hidden'});
      var scrollTop = document.viewport.getScrollOffsets().top + 40 + 'px';
      this.container.absolutize();
      this.container.setStyle({top:scrollTop});
      var errBoxPos = getXYpos($('errorBox'));
      new Effect.Move(this.container, {x: errBoxPos.x, y: errBoxPos.y, mode:'absolute'});
      new Effect.Fade(this.container);
      var ebDims = $('errorBox').getDimensions();
      var width = ebDims.width + "px";
      var height = ebDims.height + "px"
      var styleStr = 'width:' + width + ';height:' + height + ';';
      new Effect.Morph(this.container, {style:styleStr, afterFinish: function() {
        new Effect.Pulsate($('errorBox'), {pulses:2, afterFinish: function(){$('errorBox').setStyle({backgroundColor:'#AF151E'})}});
      }});
    }
  },
  
  show: function() {
    canvasOverlay.show();
    if (!this.container.visible()) {
      var scrollTop = document.viewport.getScrollOffsets().top + 40;
      this.container.setStyle({position:'absolute'});
      var errBoxPos = getXYpos($('errorBox'));
      var top = errBoxPos.y + "px";
      var left = errBoxPos.x + "px";
      var ebDims = $('errorBox').getDimensions();
      var width = ebDims.width + "px";
      var height = ebDims.height + "px"
      this.container.setStyle({top:top, left:left, width:width, height:height, overflow:'hidden'});
      var vpWidth = document.viewport.getWidth();
      var fromLeft = Math.ceil(vpWidth / 2 - 200);
      var objThis = this;
      new Effect.Appear(this.container);
      new Effect.Move(this.container, {x:fromLeft, y:scrollTop, mode:'absolute', afterFinish: function() {
        objThis.container.setStyle({position:'fixed', top:'40px', left:fromLeft+'px'});
      }});
      var styleStr = 'width:400px;height:300px;';
      new Effect.Morph(this.container, {style:styleStr, afterFinish: function() {
        objThis.content.setStyle({overflow:'auto'});
      }});
    }
  }
});

var Tips = Class.create({
  initialize: function(el, params) {
    this.fixed = params.fixed;
    this.el = el;
    //document.observe('dom:loaded', this.fire);
    if (!this.fixed) {
      //alert('The request could not be processed.  Please check your information and try again.');
    }
  }
});

function bubbledFromChild(element, event)  {
  var target = event.element();
  if (target === element) target = event.relatedTarget;
  return (target && target.descendantOf(element));
}

function forceLang(lang) {
  var queryString = (location.search) ? location.search + "&":"?";
  queryString += "lang=" + lang;
  var newUrl = location.protocol + "//" + location.host + location.pathname + queryString + location.hash;
  location.replace(newUrl);
}

function getXYpos(elem) {
   if (!elem) {
      return {"x":0,"y":0};
   }
   var xy={"x":elem.offsetLeft,"y":elem.offsetTop}
   var par=getXYpos(elem.offsetParent);
   for (var key in par) {
      xy[key]+=par[key];
   }
   return xy;
}

function insideEdition() {
  if ($('insideEdition')) {
    $$('.editionItem').each(function(s) {
      arElIE.push(new elIE(s));
    });
  }
}

function loadFacebook() {
  if (((typeof fbAppId != "undefined") && (fbAppId != "")) && ((typeof langTag != "undefined") && (langTag != ""))) {
    if (document.location.href.indexOf('test.snapnewspapers') > -1) { fbAppId = "125933864108108"; fbApiKey = "ecedc9cb99456e1d2e31f3610cbac9c7" }
    if (typeof elFbRoot == "undefined") {
      elFbRoot = new Element('div', {"id":"fb-root"})
      document.getElementsByTagName('body')[0].appendChild(elFbRoot);
      fbLib = new Element('script');
      /*fbLib.observe('load', function() {
        FB.init({"appId":fbApp, "status":true, "cookie":true, "xfbml":false});
      });*/
      elFbRoot.appendChild(fbLib);
      fbLib.writeAttribute({"src":document.location.protocol + "//connect.facebook.net/" + langTag.replace("-", "_") + "/all.js"});
    }
  } else {
    alert("Unable to initialize the Facebook components.\nFacebook components on this page have been disabled.");
  }
}

function fbAsyncInit() {
  FB.init({"appId":fbAppId, "apiKey":fbApiKey, "status":true, "cookie":true, "xfbml":false});
  fbInitialized = true;
}

function matchColHeight(lCol, rCol) {
  lCol = $(lCol);
  rCol = $(rCol);
  if (lCol && rCol) {
    var lHeight = lCol.getHeight();
    var rHeight = rCol.getHeight();
    if (lHeight > rHeight) {
      lHeight += "px";
      rCol.setStyle({height:lHeight});
    }
  }
}

function nl2br (str, is_xhtml) {
  var breakTag = '<br />';
  if (typeof is_xhtml != 'undefined' && !is_xhtml) {
    breakTag = '<br>';
  }
  return (str + '').replace(/([^>]?)\n/g, '$1'+ breakTag +'\n');
}

function smoothScroll(destination, laps) {
  laps = (laps) ? laps:1;
  var currentY = document.viewport.getScrollOffsets().top;
  var direction = (destination > currentY) ? "down" : "up";
  var distance = (direction == "down") ? destination - currentY : currentY - destination;
  if ((distance < 5) || (laps > 58)) {
    scrollTo(0, destination);
  } else {
    var step = Math.ceil(distance / 10);
    var toY = (direction == "down") ? currentY + step : currentY - step;
    window.scrollTo(0, toY);
    laps++;
    setTimeout(function() { smoothScroll(destination, laps); }, 1);
  }
}

function snapDomInit() {
  if ((typeof langTag != "undefined") && (typeof regionCode != "undefined")) {
    switch(regionCode) {
      case 1:
        if (langTag != "en-GB") { forceLang('en') }
        break;
      case 2:
        if (langTag != "it-IT") { forceLang('it') }
        break;
    }
  }
  
  canvasOverlay = new elOverlay({el:$('canvas')});

  if (Prototype.Browser.IE7 && $('loginSpacer')) {
    $('loginSpacer').hide();
  }
  
  if (pageAlerts) {
    errorNotifier = new pageNotif();
    errorNotifier.show();
    document.body.appendChild(errorNotifier.getDomObj());
    errBoxObserver = errorNotifier.show.bindAsEventListener(errorNotifier);
    $('errorBox').observe('click', errBoxObserver);
  }
  
  if ($('loginFields')) {
    snapLogin = new loginPanel();
  }
}

function snapinit() {
  if (thisIsHome) {
    matchColHeight($('contentTop').select('.contentLeft')[0], $('contentTop').select('.contentRight')[0]);
  }
  matchColHeight('content', 'rightBar');
  if (typeof objCartInfoPanel != "undefined") {
    objCartInfoPanel.setQty();
  }
}

window.addEvent = function() {
  arguments[1]();
}

thisIsHome = false;
hidePanel = true;
SNAPMailer = null;
var fbInitialized = false;

document.observe("dom:loaded", snapDomInit);
Event.observe(window, 'load', snapinit);

Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring (navigator.userAgent.indexOf("MSIE")+5)) == 6;
Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring (navigator.userAgent.indexOf("MSIE")+5)) == 7;
Prototype.Browser.IE8 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring (navigator.userAgent.indexOf("MSIE")+5)) == 8;