try {

  // ~~~~~~~ main components event handlers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  /// hide and restore default text (value) of textbox (<input type="text" />)
  /// also resets (#000000) and sets back color of input text
  ///
  /// @note can be used with multiple text inputs, but requires unique values of sender.id property for target inputs
  var HideDefaultText = {
    txt: new Array(),
    color: new Array(),

    /// restores default value of input in case when input is blured with no value (textfield is blank)
    /// @param sender                       pointer to sender input
    Blur: function(sender)
    {
      if (sender.value == '') {
        sender.value = this.txt[sender.id];
        sender.style.color = this.color[sender.id];
      }
    },

    /// clear value of input and remember it for further usage by HideDefaultText.Blur method
    /// @param sender                       pointer to sender input
    Focus: function(sender)
    {
      if (this.txt[sender.id] === undefined) {
        this.txt[sender.id] = sender.value;
      }
      if (sender.value == this.txt[sender.id]) { 
        sender.value = '';
        this.color[sender.id] = sender.style.color;
        sender.style.color = '#000000';
      }
    },

    Reset: function(sender)
    {
      if (sender) {
        this.txt[sender.id] = undefined;
      }
    }

  }; // end of HideDefaultText instance definition/instance declaration

/// horizontal scroller
  var ScrollH = {
// PUBLIC (configuration):
    AccelerationStep:   2,                  ///< number of pixels per scrolling step durin acceleration
    DecelerationStep:   1,                  ///< number of pixels per scrolling step durin deceleration
    AccelerationDelay:  20,                 ///< number of milliseconds between scrolling steps durin acceleration \n @note higher number means slower speed
    DecelerationDelay:  50,                 ///< number of milliseconds between scrolling steps during deceleration \n @note higher number means slower speed

    TargetId:           '',                 ///< ID of target element to scroll

// PRIVATE:
    _Target:            null,               ///< target element \n @note use _GetTarget()

    _Direction:         null,               ///< current direction
    _TimerId:           null,               ///< ID of scroll timer (only for acceleration)
    _Speed:             0,                  ///< current speed
    _Accelerate:        false,              ///< whether currently accelerates or decelerates
    _LastPosition:      null,               ///< last scroll position -> for calculation of scroll delta

    _GetTarget: function()
    {
      // initialise _Target property
      if (this._Target === null) {
        this._Target = document.getElementById(this.TargetId);
      }
      return(this._Target);
    },

    /// change (increase or decrease) speed and perform one scrolling step
    Scroll: function()
    {
      if (this._GetTarget()) {

        // save last position
        this._LastPosition = this._Target.scrollLeft;

        // reduce or increase current speed depending on _Accelerate property value
        this._Speed = ((this._Accelerate) ? (this._Speed + this.AccelerationStep) : ((this._Speed > this.DecelerationStep) ? (this._Speed - this.DecelerationStep) : 1) );

        // perform scrolling depending on direction
        this._Target.scrollLeft += this._Speed * ((this._Direction == 'left') ? -1 : 1);

        // test, whether we reached margin
        if (this._LastPosition == this._Target.scrollLeft) {
          // margin is reached -> stop scrolling by setting speed to zero
          this._Speed = 0;
        }
      }
    },

    /// scrolls by specified number of pixels
    ///
    /// @param int val                      number of pixels to scroll
    ScrollBy: function(val)
    {
      if (this._GetTarget()) {
        this._Target.scrollLeft += val;
      }
    },

    /// gradually reduce current speed to zero and perform scrolling
    /// @note called recursively as timeout callback (without timer ID - so we can't (don't want to) abort execution)
    Decelerate: function()
    {
      // reduce speed and perform scroll step
      this.Scroll();

      if (this._Speed > 1) {
        // register timeout callback
        setTimeout('ScrollH.Decelerate()',this.DecelerationDelay);
      } else {
        // reset speed to zero
        this._Speed = 0;
      }
    },

    /// stop scrolling and start decceleration
    /// can be used as handler of @c onmouseup and @c onmouseout events of scroll-button
    Stop: function()
    {
      if (this._TimerId != null) {

        // stop timer
        clearInterval(this._TimerId);
        this._TimerId = null;

        // switch to deceleration
        this._Accelerate = false;

        // start deceleration (perform first step)
        this.Decelerate();
      }
    },

    /// start scrolling
    /// can be used as handler of @c onmousedown event of scroll-button
    ///
    /// @param string                       'left or 'right' - determines direction of scrolling
    /// @see StartLeft(), StartRight
    Start: function(direction)
    {
      // reset speed, when changing direction (before zero speed is reached during deceleration)
      if (this._Direction != direction) {
        this._Speed = 0;
      }
      this._Direction = direction;

      // switch to acceleration
      this._Accelerate = true;

      // start timer
      this._TimerId = setInterval('ScrollH.Scroll()',this.AccelerationDelay);
    },

    /// start scrolling to the left
    /// can be used as handler of @c onmousedown event of LEFT scroll-button
    StartLeft: function()
    {
      this.Start('left');
    },

    /// start scrolling to the right
    /// can be used as handler of @c onmousedown event of RIGHT scroll-button
    StartRight: function()
    {
      this.Start('right');
    }

  }; // end of ScrollH

  /// multiple checkbox-group operations
  var ChbxOperations = {

    SetChecked: function(TargetId,Status)
    {
      if (Status === undefined) {
        Status = true;
      }

      var target = document.getElementById(TargetId);
      if (target) {
        var inputs = target.getElementsByTagName("input");
        for (var i = 0; i < inputs.length; i++) {
          if (inputs[i].getAttribute('type') == 'checkbox') {
            inputs[i].checked = Status;
          }
        }
      }
    },

    ChbxSelectAll: function(TargetId)
    {
      this.SetChecked(TargetId,true);
    },

    ChbxSelectNone: function(TargetId)
    {
      this.SetChecked(TargetId,false);
    }

  }; // end of ChbxOperations

} catch (e) {
  // do nothing
}

/// we are trying to have valid XHTML Strict, which doesn't support new windows...
function externalLinks()
{
	if (!document.getElementsByTagName) return;
	var anchors = document.getElementsByTagName("a");
	for (var i=0; i<anchors.length; i++)
	{
		var anchor = anchors[i];
		if (anchor.getAttribute("href") &&
			anchor.getAttribute("rel") == "external")
		anchor.target = "_blank";
	}
	
	var forms = document.getElementsByTagName("form");
	for(var i = 0; i < forms.length; i++)
	{
		var form = forms[i];
		if(typeof form.getAttribute("id") == 'string' && form.getAttribute("id").substring(0, 3) == "s2f")
		{
			form.target = "_blank";
		}
	}
}
window.onload = externalLinks;

  // ~~~~~~~ AJAX ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

var http_request = false;

/// make GET request to server
/// @param url                       where we send GET request?
/// @param callback                  what should be call after sent?
function makeGETRequest(url, callback)
{
	http_request = false;
	
	if(window.XMLHttpRequest) // Mozilla, Safari, ...
	{ 
		http_request = new XMLHttpRequest();
		if (http_request.overrideMimeType)
			http_request.overrideMimeType('text/html');
	}
	else if (window.ActiveXObject) // IE
	{
		try {
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
      	// Do nothing.
			}
	}
	if (!http_request)
	{
		return false;
	}
   
	http_request.onreadystatechange = callback;
	http_request.open('GET', url, true);
	http_request.setRequestHeader("Content-type", "text/html");
	http_request.setRequestHeader("Connection", "close");
	http_request.send("");
}

function iLikeItResponse()
{
	if (http_request.readyState == 4)
	{
		if (http_request.status == 200)
		{
			result = http_request.responseText;
			document.getElementById('ilikeit').innerHTML = result;
		}
	}
}

var BoxResponseTarget = 'login_box';
var BoxResponseRenameTo = null;

// AJAX response callback for login operation
function BoxResponse()
{
	if ((http_request.readyState == 4) && (http_request.status == 200)) {
		res = http_request.responseText;
		if (res != '') {
  		target = document.getElementById(BoxResponseTarget);
      if (target) {
        target.innerHTML = res;
        if (BoxResponseRenameTo !== null) {
          target.id = BoxResponseRenameTo;
        }
      }
    }
	}
}

var BoxResponseScheduleTarget = 'schedule_box';
function BoxResponseSchedule() {
	if ((http_request.readyState == 4) && (http_request.status == 200)) {
		res = http_request.responseText;
		if (res != '') {
  		target = document.getElementById(BoxResponseScheduleTarget);
      if (target) {
        target.innerHTML = res;
      }
    }
	}
}

var StarsTarget = 'shows_starslist';
var StarsResponseContent = null;
// response for stars bios
function StarsResponse()
{
	if ((http_request.readyState == 4) && (http_request.status == 200)) {
		res = http_request.responseText;
		if (res != '') {
  		target = document.getElementById(StarsTarget);
      if (target) {
        StarsResponseContent = target.innerHTML;
        target.innerHTML = res;
      }
		}
	}
}

  // ~~~~~~~ ZIP checker hacks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// Some functions from Prototype.
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Function.prototype.bind = function() {
	var __method = this, args = $A(arguments), object = args.shift();
	return function() {
		return __method.apply(object, args.concat($A(arguments)));
	}
}

var helper_node = [];
var helper_nodes = 0;

var orderPBTV = {
	checkBrowser: function(body) {
		this.browser = {
			version: (this.userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
			safari: /webkit/.test(this.userAgent),
			opera: /opera/.test(this.userAgent),
			msie: /msie/.test(this.userAgent) && !/opera/.test(this.userAgent),
			mozilla: /mozilla/.test(this.userAgent) && !/(compatible|webkit)/.test(this.userAgent),
			konqueror: this.userAgent.match(/konqueror/i)
		};
	},
	
	send: function(url) {
		this.readyState = 2;
		this.url = url;
		this.userAgent = navigator.userAgent.toLowerCase();
		this.checkBrowser();
		this.prepare();
		this.getURL(this.url);
	},
	
	callback: function() {
		this.readyState = 4;
		doneOrderPBTV();
	},
	
	prepare: function() {
		if (this.browser.safari || this.browser.konqueror) {
			var helper_node = [];
			var helper_nodes = 0;
		}
	},
	
	getURL: function() {
		/* determine arguments */
		var arg = {
			'url': null
		};
    arg.url = arguments[0];

		/* generate <script> node */
		this.node = document.createElement('SCRIPT');
		this.node.setAttribute('type', 'text/javascript');
    this.node.setAttribute('src', arg.url);

		/* optionally apply event handler to <script> node for
			garbage collecting <script> node after loading and/or
			calling a custom callback function */
		var node_helper = null;

		if (this.browser.msie)
		{
			function mybind(obj) {
				temp = function() {
				if (this.readyState == "complete" || this.readyState == "loaded")
					return obj.callback.call(obj);
				};
				return temp;
			}
			/* MSIE doesn't support the "onload" event on
				 <script> nodes, but it at least supports an
				 "onreadystatechange" event instead. But notice:
				 according to the MSDN documentation we would have
				 to look for the state "complete", but in practice
				 for <script> the state transitions from "loading"
				 to "loaded". So, we check for both here... */
			this.node.onreadystatechange = mybind(this);
		/* Safari/WebKit and Konqueror/KHTML do not emit
				 any_ events at all, but we can exploit the fact
				 that dynamically generated <script> DOM nodes
				 are executed in sequence (although the scripts
				 theirself are still loaded in parallel) */
  	} else if (this.browser.safari || this.browser.konqueror) {
	    helper_nodes++;

			var helper = 'var ctx = helper_node[' + helper_nodes + '];' + 'alert("We are sending your request."); ctx.callback.call(ctx.node); ' + 'setTimeout(function () {' + '    ctx.node_helper.parentNode.removeChild(ctx.node_helper);' + '}, 100);';
			node_helper = document.createElement('SCRIPT');
			node_helper.type = 'text/javascript';
			node_helper.appendChild(document.createTextNode(helper));
			helper_node[helper_nodes] = {
			callback: this.callback.bind(this),
				node: this.node,
				node_helper: node_helper
			};
		} else {
			/* Firefox, Opera and other reasonable browsers can
				 use the regular "onload" event... */
			this.node.onload = this.callback.bind(this);
		}

    /* inject <script> node into <head> of document */
    this.readyState = 3;
		var head = document.getElementsByTagName('HEAD')[0];
		head.appendChild(this.node);

		/* optionally inject helper <script> node into <head>
		 (Notice: we have to use a strange indirection via
		 setTimeout() to insert this second <script> node here or
		 at least Konqueror (and perhaps also Safari) for unknown
		 reasons will not execute the first <script> node at all) */

		
		if (node_helper !== null)
		{
			setTimeout(function() {
			var head = document.getElementsByTagName('HEAD')[0];
			head.appendChild(node_helper);
	    }, 100);
		}
	}	
};

function processOrder(form)
{
	var append = "";
	for(var i = 0; i < form.elements.length; i++)
	{
		if(form.elements[i].tagName == "INPUT")
		{
			append += (append == "" ? form.elements[i].name + "=" + form.elements[i].value : "&" + form.elements[i].name + "=" + form.elements[i].value); 
		}
	}

	orderPBTV.send(orderPBTVURL + "?" + append);
}

function doneOrderPBTV()
{
	document.getElementById('order_pbtv').action = orderPBTVURL;
	
	if(orderPBTVTarget == 'popup')
	{
		// Generate random number.
		var rand = ( Math.floor ( Math.random ( ) * 101 ) );
		
		window.open('','zipwindow' + rand,'width=800,height=600,toolbar=yes,location=yes,status=yes,menubar=yes,resizable=yes,scrollbars=yes');
		
		// Have to be after action because of Safari.
		document.getElementById('order_pbtv').target = 'zipwindow' + rand;
	}
	document.getElementById('order_pbtv').submit();
}