if(typeof($)=='function') {
  $(document).ready(function(){

    loggedIn = false;

    function htmlEncode(html) {
      return $('<div/>').text(html).html();
    }

    function showLoadingIndicator() {
      // check whether there's already an indicator shown
      if($('#loading').length)
        return;
      
      // take all links in the content out of the tab order
      // (note: we don't bother storing the current value of the
      // tabindex attribute on the assumption that there is none)
      $('#content a').blur().attr('tabindex', -1);
      // remove focus and disable all form elements in the content
      $('#content button,#content input,#content select,#content textarea')
        .blur().attr('disabled', 'disabled');

      // create the indicator
      $(document.body).append(
        '<div id="loading"><div><p>'+htmlEncode(lang.loading)+'</p></div></div>'
      );
      // fade the indicator in
      $('#loading').hide().fadeIn('fast');
    }
    
    
    function hideLoadingIndicator(reEnableForms) {
      if(arguments.length==0)
        reEnableForms = false;
      if(reEnableForms) {
        $('#content button,#content input,#content select,#content textarea')
          .removeAttr('disabled');
        $('#content a').removeAttr('tabindex');
      }
      $('#loading').fadeOut('normal', function(){
        $(this).remove();
      });
    }


    function showDialog(isError, dialogType, heading, message, additional,
                        callback, location, messageIsHTML, isPAYG) {
      if(arguments.length<8)
        messageIsHTML = false;
      // work out our location (we don't use the
      // location parameter, above, any more)
      var you = $('#you').val();
      var youParsed = new PhoneNumber(you);
      if(you.length && youParsed.valid
         && youParsed.areaCode==lang.areaCodeIOM) {
        var location = 'isleofman';
      } else if(you.length && youParsed.valid
                && (youParsed.areaCode==lang.areaCodeJSY
                    || youParsed.areaCode==lang.areaCodeJSYAirtel
                    || youParsed.areaCode==lang.areaCodeJSYJT)) {
        var location = 'mobile';
      } else if(you.length && youParsed.valid
                && (youParsed.areaCode==lang.areaCodeGSY
                    || youParsed.areaCode==lang.areaCodeGSYAirtel
                    || youParsed.areaCode==lang.areaCodeGSYWave)) {
        var location = 'guernsey';
      } else {
        // - fall back on the cookie
        /*var location = undefined;
        var cookieStart = document.cookie.indexOf('locn=');
        if(cookieStart!=-1) {
          cookieStart += 5;  // 'locn='.length()==5
          var cookieEnd = document.cookie.indexOf(';', cookieStart);
          if(cookieEnd==-1) cookieEnd = document.cookie.length;
          location = document.cookie.substring(cookieStart, cookieEnd);
          if(location=='iom' || location=='isleofman') {
            location = 'isleofman';
          } else if(location=='gsy' || location=='guernsey') {
            location = 'guernsey';
          } else {
            // - default to Jersey
            location = 'mobile';
          }
        } else {
          // - default to Jersey
          location = 'mobile';
        }*/
        // - we don't fall back on the cookie any more,
        // we ask the user instead
        var location = undefined;
      }

      // take all links in the content out of the tab order
      // (note: we don't bother storing the current value of the
      // tabindex attribute on the assumption that there is none)
      $('#content a').blur().attr('tabindex', -1);
      // remove focus and disable all form elements in the content
      $('#content button,#content input,#content select,#content textarea')
        .blur().attr('disabled', 'disabled');
      // create the dialog
      $(document.body).append(
        '<div id="dialog-overlay" style="opacity:0;"></div>'
        +'<div id="dialog"'+(isError?' class="error"':'')+'>'
        +'<div id="dialog-sheet"><div id="dialog-content">'
        +'<h3>'+htmlEncode(heading)+'</h3>'
        +(messageIsHTML?'<div id="dialog-message">'+message+'</div>'
                       :'<p>'+htmlEncode(message).replace(/\n/g, '<br />\n')
                        +'</p>')
        +(additional?'<p id="dialog-additional"><small>'
                     +htmlEncode(additional).replace(/\n/g, '<br />\n')
                     +'</small></p>'
                    :'')
        +(dialogType=='login'
          ?'<form>'
           +'<fieldset><legend><span>'+lang.loginFormHeader+'</span></legend>'
           +'<p><small>'+htmlEncode(lang.loginFormSignup)+' '
           +'<a href="'+(location=='isleofman'
                         ?lang.accountSignupUrlIOM
                         :(location=='guernsey'
                           ?lang.accountSignupUrlGSY
                           :(location=='mobile'
                             ?lang.accountSignupUrlJSY
                             :lang.accountSignupUrl)))+'">'
           +htmlEncode(lang.loginFormSignupLink)+'</a></small></p>'
           +'<dl><dt><label for="login">'
           +htmlEncode(lang.emailAddress)+'</label></dt>'
           +'<dd><input type="text" name="login" id="login" /></dd>'
           +'<dt><label for="passwd">'
           +htmlEncode(lang.password)+'</label></dt>'
           +'<dd><input type="password" name="passwd" id="passwd" />'
           +(location=='guernsey'
             ?''
             :'<small><a href="'
              +(location=='isleofman'
                ?lang.forgotPasswordUrlIOM
                :(location=='mobile'
                  ?lang.forgotPasswordUrlJSY
                  :lang.forgotPasswordUrl))
              +'">'+htmlEncode(lang.loginFormForgottenPassword)
              +'</a></small>')
           +'</dd></dl>'
           +'<p class="buttons"><input type="submit" name="login" '
           +'id="dialog-login" value="'+htmlEncode(lang.login)+'" /> '
           +'<button id="dialog-cancel">'+htmlEncode(lang.cancel)+'</button>'
           +'</p></fieldset></form>'
          :'<p class="buttons">'
           +'<button id="dialog-ok">'+htmlEncode(lang.ok)+'</button></p>')
        +'</div></div><div id="dialog-footer"><div></div></div></div>'
      );
      // hide this dialog (we'll slide it in in a moment)
      $('#dialog').hide();
      // set the onclick function for the OK or cancel button
      $('#dialog button').click(function(){
        // dismiss the dialog
        $('#dialog-ok').blur().attr('disabled', 'disabled');
        $('#dialog-overlay').fadeOut('normal');
        $('#dialog').SlideOutUp('slow', function(){
          $('#content button,#content input,#content select,#content textarea')
            .removeAttr('disabled');
          $('#content a').removeAttr('tabindex');
          $('#dialog,#dialog-overlay').remove();
          if(typeof(callback)=='function') callback(this.id);
        });
        return false;  // for the cancel button, which is in a form
      });
      // set the onsubmit function for the login form
      $('#dialog form').submit(function(){
        // dismiss the dialog
        $('#dialog-ok').blur().attr('disabled', 'disabled');
        $('#dialog-overlay').fadeOut('normal');
        $('#dialog').SlideOutUp('slow', function(){
          // get the submitted data
          var login = $('#login').val(),
              passwd = $('#passwd').val();
          // get rid of the dialog 
          $('#content button,#content input,#content select,#content textarea')
            .removeAttr('disabled');
          $('#content a').removeAttr('tabindex');
          $('#dialog,#dialog-overlay').remove();
          // we make the call to the server here in the callback function
          // so that if we end up showing a new dialog as a result,
          // we can guarantee that the old one has gone; if it's still
          // around then the click events on the buttons of the new dialog
          // don't get assigned properly
          $.ajax({
            url: 'http://www.surecw.com/friends/do.asp?what=login',
            cache: false,
            type: 'POST',
            dataType: 'json',
            data: {login:login, passwd:passwd},
            error: function() {
              // hide the loading indicator
              hideLoadingIndicator(true);
              // show an error dialog
              showDialog(
                true,
                'message',
                lang.errorGeneral,
                lang.errorGeneralMsg,
                lang.errorGeneralDetail,
                function(){},
                ''
              );
            },
            success: function(results){
              // hide the loading indicator
              hideLoadingIndicator(true);
              // check the results
              loggedIn = results.loggedIn;
              if(results.loggedIn) {
                // modify the page to show the logged in view
                // - change the login button to an info box
                $('#login-link').text('Logged in as '+results.userid);
                // get rids of any current message box
                $('#messagebox').remove();
                // show the form if it's hidden
                var formfields = $('#formfields');
                if(formfields.css('display')=='none') {
                  formfields.animate({
                      height: 'show',
                      opacity: 'show'
                    }, 'slow');
                }
                if(results.friends.partOfPromotion) {
                  // - hide the unique code box and the T&Cs checkbox
                  $('#code-term,#code-desc,#tandcs').hide();
                  // check the T&Cs checkbox
                  $('#you').val(results.you);
                  $('#you').attr('disabled', 'disabled');
                  $('#agree').val('1');
                  if(results.friends.canChangeFriends) {
                    // fill all our friends
                    $('#friend1').val(results.friends.friends[0]);
                    $('#friend2').val(results.friends.friends[1]);
                    $('#friend3').val(results.friends.friends[2]);
                    // show a message saying about changing only every 30 days
                    var messagebox = $('<p id="messagebox"/>');
                    messagebox.html(htmlEncode(lang.change)+'<br/>'
                                    +htmlEncode(lang.makeChanges));
                    messagebox.hide();
                    $('#formfields').before(messagebox);
                    messagebox.animate({
                      height: 'show',
                      opacity: 'show'
                    }, 'slow');
                  } else {
                    // fill all our friends as read-only
                    $('#friend1').val(results.friends.friends[0]);
                    $('#friend1').attr('readonly', 'readonly');
                    $('#friend2').val(results.friends.friends[1]);
                    $('#friend2').attr('readonly', 'readonly');
                    $('#friend3').val(results.friends.friends[2]);
                    $('#friend3').attr('readonly', 'readonly');
                    // hide the go button
                    $('#go').hide();
                    // show a message saying about changing only every 30 days
                    var messagebox = $('<p id="messagebox"/>');
                    messagebox.text(
                      lang.loginToChange+' '+lang.nextChange.replace(/%date%/g,
                 formatDate(new Date(results.friends.dateOfNextAllowedChange)))
                      +' '+lang.topUp
                    );
                    messagebox.hide();
                    $('#formfields').before(messagebox);
                    messagebox.animate({
                      height: 'show',
                      opacity: 'show'
                    }, 'slow');
                  }
                } else {
                  // not part of the promotion - hide everything
                  $('#formfields').hide('fast', function(){
                    var messagebox = $('<p id="messagebox"/>');
                    messagebox.text(lang.notPartOfPromotion);
                    messagebox.hide();
                    $('#formfields').before(messagebox);
                    messagebox.animate({
                      height: 'show',
                      opacity: 'show'
                    }, 'slow');
                  });
                }
              } else {
                // show a new login dialog
                showDialog(
                  true,
                  'login',
                  lang.errorLoginInvalid,
                  '',
                  '',
                  function(){}
                );
              }
            }
          });
        });
        // show a loading indicator
        showLoadingIndicator();
        // prevent the default submission action
        return false;
      });
      // show the dialog
      $('#dialog-overlay').height($(window).height()).fadeTo('fast', 0.4);
      $('#dialog').SlideInUp('slow', function(){
        $(dialogType=='login'?'#login':'#dialog-ok').focus();
      });
    }



    // Hide the entire page so we can slide it into view later
    $('#content').hide();

    // Add an opera-specific stylesheet if needed.
    // (NOTE: Ugly, ugly hack! The site is perfectly usable
    // in Opera without this though, so it's acceptable.)
    if(window.opera) {
      $('head').append('<link rel="stylesheet" type="text/css" '
                       +'href="css/opera.css" />');
    }

    // Add a class to the body as a hook for the JS-only styles
    $('#page').addClass('has-js');

    // Make the logo link open in a new window.
    $('#surelogo a').click(function(){
      window.open(this.href);
      return false;
    });

    // Hook up our fake checkbox
    function updateCheckboxGraphic() {
      if(this.checked)
        $('#tandcs').addClass('checked');
      else
        $('#tandcs').removeClass('checked');
    }
    $('#agree')
      .change(updateCheckboxGraphic)
      .click(updateCheckboxGraphic)  // needed for IE
      .change();  // update the graphic now

    // Make the help open in a dialog
    $('#help a').click(function(){
      // show a loading indicator
      showLoadingIndicator();
      // get the help
      var content = fetchImmediacyPage('mobile', lang.helpPage);
      // hide the loading indicator
      hideLoadingIndicator();
      // show the dialog
      showDialog(
        false,
        'message',
        lang.helpHeader,
        content,
        undefined,
        undefined,
        undefined,
        true
      );
      return false;
    });

    /*
	|-------------------------------
	| Make the T&Cs open in a dialog DISABLED FOR TIME BEING
    |-------------------------------
	/*
	
	$('#tandcs a').click(function()
	{
      showLoadingIndicator();
      
	  var you = $('#you').val();
      var youParsed = new PhoneNumber(you);
      
	  if(you.length && youParsed.valid && youParsed.areaCode == lang.areaCodeIOM)
	  {
        var locn = 'isleofman';
      
	  } else if(you.length && youParsed.valid && (youParsed.areaCode == lang.areaCodeJSY || youParsed.areaCode==lang.areaCodeJSYAirtel || youParsed.areaCode==lang.areaCodeJSYJT))
	  {
        var locn = 'mobile';
      
	  } else if(you.length && youParsed.valid && (youParsed.areaCode==lang.areaCodeGSY || youParsed.areaCode==lang.areaCodeGSYAirtel || youParsed.areaCode==lang.areaCodeGSYWave))
	  {
        var locn = 'guernsey';
      
	  } else {
        
		var locn = undefined;
        var cookieStart = document.cookie.indexOf('locn=');
        
		if(cookieStart!=-1)
		{
          cookieStart += 5;  // 'locn='.length()==5
          var cookieEnd = document.cookie.indexOf(';', cookieStart);
          
		  if(cookieEnd==-1) cookieEnd = document.cookie.length;
          
		  locn = document.cookie.substring(cookieStart, cookieEnd);
          
		  if(locn=='iom' || locn=='isleofman')
		  {
            locn = 'isleofman';
          
		  } else if(locn=='gsy' || locn=='guernsey')
		  {
            locn = 'guernsey';
          
		  } else {
            
			locn = 'mobile';
          }
        } else {
          
		  locn = 'mobile';
        }
      }
      
	  var content = fetchImmediacyPage(
        locn,
        locn=='isleofman'
              ?lang.termsAndConditionsPageIOM
              :(locn=='guernsey'
                ?lang.termsAndConditionsPageGSY
                :lang.termsAndConditionsPageJSY)
      );
      
	  hideLoadingIndicator();
      
	  showDialog(
        false,
        'message',
        lang.termsAndConditionsHeader,
        content,
        undefined,
        undefined,
        undefined,
        true
      );
      
	  return false;
   });
	*/

    // Make the login button show a dialog
    $('#login-link a').click(function(){
      showDialog(
        false,
        'login',
        '',
        '',
        '',
        function(){}
      );
      return false;
    });

    // Load our existing friends once you
    // and code have been filled in
    $('#you,#code').change(function(){
        var fieldWhichHasChanged = this;
        var youParsed = new PhoneNumber($('#you').val());
        var code = $('#code').val();
        
        if(/^[0-9]{5}$/.test(code) && youParsed.valid
           && (youParsed.areaCode==lang.areaCodeGSY
		           || youParsed.areaCode==lang.areaCodeGSYAirtel
						   || youParsed.areaCode==lang.areaCodeGSYWave
						   || youParsed.areaCode==lang.areaCodeIOM
							 || youParsed.areaCode==lang.areaCodeJSY
							 || youParsed.areaCode==lang.areaCodeJSYAirtel
							 || youParsed.areaCode==lang.areaCodeJSYJT)) {
          // - show a loading indicator
          showLoadingIndicator();
          $.ajax({
            url: 'http://www.surecw.com/friends/do.asp',
            cache: false,
            dataType: 'json',
            data: {what: 'getFriends',
             you: '0'+youParsed,
             code: code},
            error: function() {
              // hide the loading indicator
              hideLoadingIndicator(true);
              // fail silently
            },
            success: function(results){
              // hide the loading indicator
              hideLoadingIndicator(true);
              // check the results
              var numExistingFriends = 0;
              if(results.firstVisit) {
                // prefill any existing freinds,
                // but leave them editable
                for(var i=0, j=results.friends.length; i<j; i++) {
                  if(results.friends[i].length) {
                    $('#friend'+(i+1))
                      .removeAttr('readonly')
                      .val(results.friends[i]);
                    numExistingFriends++;
                  }
                }
                // clear any info in the remaining friend fields
                for(i=j; i<3; i++) {
                  $('#friend'+(i+1))
                    .removeAttr('readonly')
                    .val('');
                }
              } else {
                // show any existing friends as read only
                var numberStr;
                for(var i=0, j=results.friends.length; i<j; i++) {
                  if(results.friends[i].length) {
                    $('#friend'+(i+1))
                      .attr('readonly', 'readonly')
                      .val(results.friends[i]);
                    numExistingFriends++;
                  }
                }
                // clear any info in the remaining friend fields
                for(i=j; i<3; i++) {
                  $('#friend'+(i+1))
                    .removeAttr('readonly')
                    .val('');
                }
              }
              switch(numExistingFriends) {
                case 3:
                  // get rid of any current message box
                  $('#messagebox').animate({
                    height: 'hide',
                    opacity: 'hide'
                  }, 'slow').remove();
                  if(results.firstVisit) {
                    // show the T&Cs checkbox and the go button
                    $('#tandcs,#tandcs+p').animate({
                      height: 'show',
                      opacity: 'show'
                    }, 'fast');
                    // focus the first friend field
                    $('#friend1').focus().select();
                  } else {
                    // hide the T&Cs checkbox and the go button
                    $('#tandcs,#tandcs+p').animate({
                      height: 'hide',
                      opacity: 'hide'
                    }, 'slow');
                    // show a new message box
                    $('#formfields').before(
                      $('<p id="messagebox"/>').hide().html(
                        htmlEncode(lang.errorMaxFriends
                                   .replace(/%maxFriends%/g,
                                            lang.maxFriends))+'<br/>'
                        +htmlEncode(lang.loginToChange)
                      )
                    );
                    $('#messagebox').animate({
                      height: 'show',
                      opacity: 'show'
                    }, 'slow');
                  }
                  break;
                case 0:
                  // get rid of any current message box
                  $('#messagebox').animate({
                    height: 'hide',
                    opacity: 'hide'
                  }, 'slow').remove();
                  // show the T&Cs checkbox and the go button
                  $('#tandcs,#tandcs+p').animate({
                    height: 'show',
                    opacity: 'show'
                  }, 'slow');
                  // focus the next field
                  if(fieldWhichHasChanged.id && fieldWhichHasChanged.id=='you')
                    $('#code').focus();
                  else
                    $('#friend1').focus();
                  break;
                default:
                  // get rid of any current message box
                  $('#messagebox').animate({
                    height: 'hide',
                    opacity: 'hide'
                  }, 'fast').remove();
                  // show the T&Cs checkbox and the go button
                  $('#tandcs,#tandcs+p').animate({
                    height: 'show',
                    opacity: 'show'
                  }, 'fast');
                  // focus the first blank friend field
                  $('#friend'+(numExistingFriends+1)).focus().select();
              }
            }
          });
        }
    });

    // Check and process form submissions
    $('#go').click(function(){
      // check the data
      if(loggedIn) {
        var allowGuernseyNumbers = true;
        var results = checkFreeCallsData(
          $('#you').val(),
          undefined,
          [$('#friend1').val(), $('#friend2').val(), $('#friend3').val()],
          true,
          true,
          allowGuernseyNumbers
        );
        if(results.errors.length) {
          // something's not right - show an error message
          // (we just show the first error here)
          showDialog(
            true,
            'message',
            lang.error,
            results.errors[0].msg,
            results.errors[0].additional,
            function(){
              // highlight the field with an error
              $('#'+results.errors[0].field).focus().select();
            }
          );

        } else {
          // data is OK
          // - show a loading indicator
          showLoadingIndicator();
          // - process the data on the server
          $.ajax({
            url: 'http://www.surecw.com/friends/do.asp',
            cache: false,
            dataType: 'json',
            data: {what: 'update',
             friend1: results.friends[0].valid?'0'+results.friends[0]:'',
             friend2: results.friends[1].valid?'0'+results.friends[1]:'',
             friend3: results.friends[2].valid?'0'+results.friends[2]:''},
            error: function() {
              // hide the loading indicator
              hideLoadingIndicator();
              // show an error dialog
              showDialog(
                true,
                'message',
                lang.errorGeneral,
                lang.errorGeneralMsg,
                lang.errorGeneralDetail,
                function(){},
                ''
              );
            },
            success: function(dialog){
              // hide the loading indicator
              hideLoadingIndicator();
              // show the required dialog
              showDialog(
                dialog.isError,
                dialog.dialogType,
                dialog.heading,
                dialog.message,
                dialog.additional,
                function(){
                  if(dialog.isError==false) {
                    function showMessageBox() {
                      // get rid of any current message box
                      $('#messagebox').animate({
                        height: 'hide',
                        opacity: 'hide'
                      }, 'fast').remove();
                      // show a new message box
                      $('#formfields').before(
                        $('<p id="messagebox"/>').hide().html(
                          htmlEncode(lang.nextChangeAgain.replace(
                            /%date%/g, formatDate(
                              new Date((new Date()).getTime()
                                       +(lang.canChangeFriendsAfter*86400000))
                              )  // 86400000 = number of milliseconds in a day
                          ))+'<br/>'
                          +htmlEncode(lang.fairUsage
                                      +(dialog.isPAYG?' '+lang.topUp:''))
                        )
                      );
                      $('#messagebox').animate({
                        height: 'show',
                        opacity: 'show'
                      }, 'slow');
                    }
                    // clear and hide the form fields,
                    // then show the message box
                    $('#you').val('');
                    $('#code').val('');
                    $('#friend1').val('');
                    $('#friend2').val('');
                    $('#friend3').val('');
                    $('#formfields').animate({
                      height: 'hide',
                      opacity: 'hide'
                    }, 'slow', showMessageBox);
                  } else if(dialog.field) {
                    // highlight the field with an error
                    $('#'+dialog.field).focus().select();
                  }
                },
                dialog.location,
                false,
                dialog.isPAYG
              );
            }
          });
        }

      } else {
        var inputFriends = [
          $('#friend1'),
          $('#friend2'),
          $('#friend3')
        ];
        for(var i=0, j=inputFriends.length; i<j; i++) {
          if(!inputFriends[i][0] || inputFriends[i][0].readOnly)
            inputFriends[i] = '';
          else
            inputFriends[i] = inputFriends[i].val();
        }
        var allowGuernseyNumbers = true;
		
        var results = checkFreeCallsData(
          $('#you').val(),
          $('#code').val(),
          inputFriends,
          $('#agree:checked').length>0,
          false,
          allowGuernseyNumbers
        );
        if(results.errors.length) {
          // something's not right - show an error message
          // (we just show the first error here)
          showDialog(
            true,
            'message',
            lang.error,
            results.errors[0].msg,
            results.errors[0].additional,
            function(){
              // highlight the field with an error
              $('#'+results.errors[0].field).focus().select();
            }
          );

        } else {
          // data is OK
          // - show a loading indicator
          showLoadingIndicator();
          // - process the data on the server
          $.ajax({
            url: 'http://www.surecw.com/friends/do.asp',
            cache: false,
            dataType: 'json',
            data: {you: '0'+results.you,
             code: results.code,
             friend1: results.friends[0].valid?'0'+results.friends[0]:'',
             friend2: results.friends[1].valid?'0'+results.friends[1]:'',
             friend3: results.friends[2].valid?'0'+results.friends[2]:'',
             agree: results.agree?'1':''},
            error: function() {
              // hide the loading indicator
              hideLoadingIndicator();
              // show an error dialog
              showDialog(
                true,
                'message',
                lang.errorGeneral,
                lang.errorGeneralMsg,
                lang.errorGeneralDetail,
                function(){},
                ''
              );
            },
            success: function(dialog){
              // hide the loading indicator
              hideLoadingIndicator();
              // show the required dialog
              showDialog(
                dialog.isError,
                dialog.dialogType,
                dialog.heading,
                dialog.message,
                dialog.additional,
                function(){
                  if(dialog.isError==false) {
                    function showMessageBox() {
                      // show a message about logging in
                      // if we haven't already done so
                      if(!$('#messagebox').length) {
                        $('#formfields').before(
                          $('<p id="messagebox"/>').hide().text(
                            lang.loginToChange+' '+lang.fairUsage
                            +(dialog.isPAYG?' '+lang.topUp:'')
                          )
                        );
                        $('#messagebox').animate({
                          height: 'show',
                          opacity: 'show'
                        }, 'slow');
                      }
                    }
                    if(results.friends[0].valid
                       && results.friends[1].valid
                       && results.friends[2].valid) {
                      // we now have the maximum number of friends,
                      // so clear and hide the form fields,
                      // then show the message box
                      $('#you').val('');
                      $('#code').val('');
                      $('#friend1').val('');
                      $('#friend2').val('');
                      $('#friend3').val('');
                      $('#formfields').animate({
                        height: 'hide',
                        opacity: 'hide'
                      }, 'slow', showMessageBox);
                    } else {
                      // sort results.friends so that
                      // all valid numbers come first
                      results.friends.sort(function(a, b) {
                        if(a.valid && !b.valid) return -1;
                        if(!a.valid && b.valid) return 1;
                        return 0;
                      });
                      // make already filled-in fields read-only
                      var numberStr, numValid = 0;
                      for(var k=0; k<3; k++) {
                        if(results.friends[k].valid) {
                          numValid++;
                          $('#friend'+(k+1)).attr('disabled', 'disabled');
                        }
                      }
                      // show the message box
                      showMessageBox();
                    }
                  } else if(dialog.field) {
                    // highlight the field with an error
                    $('#'+dialog.field).focus().select();
                  }
                },
                dialog.location,
                false,
                dialog.isPAYG
              );
            }
          });
        }

      }
      return false;
    });

    // Slide the content into view
    $('#content').SlideInUp(3000, function(){
      $('#you').focus();
    }, 'bounceout');

  });
}



/* From http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf#Compatibility
 * (MIT License).
 */
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}



/* Object representing a phone number.
 */
function PhoneNumber(number) {
  this.valid = true;

  number = number.replace(/\s+/g, '');
  var matches = /^(?:\+44|44|0)?([0-9]{4})([0-9]{6})$/.exec(number);
  if(matches===null) {
    // check for a six-digit number which begins with 2
    // - IOM customers tend to write their mobile numbers as six digits
    matches = /^()(2[0-9]{5})$/.exec(number);
    if(matches===null) {
      this.valid = false;
    } else {
      // treat this as an IOM number
      matches[1] = lang.areaCodeIOM.substring(1);
    }
  }
  
  if(this.valid) {
    this.areaCode = '0'+matches[1];
    this.localPart = matches[2];
    this.internalFormat = matches[1]+matches[2];
    this.ukFormat = this.areaCode+' '+this.localPart;
    this.intlFormat = '+44'+this.internalFormat;
    this.networkFormat = '44'+this.internalFormat;
  }
}
PhoneNumber.prototype.toString = function() {
  return this.internalFormat;
}
PhoneNumber.prototype.markup = function(startAt) {
  if(!this.valid)
    return undefined;

  var out = '';
  var counter = startAt;
  for(var i=0, j=this.ukFormat.length; i<j; i++) {
    char = this.ukFormat.charAt(i);
    if(char==' ') {
      out += '<span class="number-space"> </span>';
    } else {
      counter = (counter+1)%12;
      if(counter==0)
        counter = 1;
      out += '<span class="number-'+counter+'-'+char+'">'+char+'</span>';
    }
  }
  return '<span class="number">'+out+'</span>';
}



function formatDate(dateTime) {
  return dateTime.getDate()+' '
         +lang.months[dateTime.getMonth()]+' '
         +dateTime.getFullYear();
}



/* Fetches the content of a page from Immediacy
 */
function fetchImmediacyPage() {
  if(arguments.length<2) {
    // not enough parameters
    return '<p>No page specified: To display a page from the website, '
           +'you must specify which page you\'d like to display.</p>';
  } else {
    // correct number of parameters - construct the URL
    var site = encodeURIComponent(arguments[0]);
    var page = encodeURIComponent(arguments[1]);
    if(arguments.length>2)
      var area = arguments[2];
    else
      var area = 'main';
    // add a dummy parameter based on the current time, to prevent caching
    var now = new Date()
    var noCache = '&'+now.getTime();
    var pageUrl = 'http://www.surecw.com/'+site+'/xml.aspx?page='+page+noCache;

    // fetch the XML document
    var statusOK = false, pageOK = false, content, matches;
    if(typeof($)=='function') {
      $.ajax({
        async: false,
        url: pageUrl,
        dataType: 'html',
        success: function(doc, status) {
          statusOK = true;
          if(matches = /<area name="main"[^>]*>/.exec(doc)) {
            var areaStart = matches.index+matches[0].length;
            var areaEnd = doc.indexOf('</area>', areaStart);
            if(areaEnd==-1) areaEnd = doc.length;
            content = doc.substring(areaStart, areaEnd);
            pageOK = true;
          }
        },
        error: function(req, status, err) {
          //document.location = 'http://www.surecw.com/'+site+'/page-'+page;
        }
      });
    } else {
      var xml = Server.CreateObject('Microsoft.XMLHTTP');
      xml.Open('GET', pageUrl, false);
      xml.Send();
      if(xml.status=='200') {
        // page successfully fetched
        statusOK = true;
        var xmlDoc = xml.responseXML;
        var areas = xmlDoc.getElementsByTagName('area');
        var contentArea = null;
        for(var i=0; i<areas.length; i++) {
          if(areas(i).getAttribute('name')==area) {
            pageOK = true;
            contentArea = areas(i);
            content = contentArea.xml;
            // remove the area tags
            content = content.replace(new RegExp('<area name="'+area
                                                 +'" type="xhtml">',
                                                 'g'), '');
            content = content.replace(new RegExp('</area>', 'g'), '');
            break;
            // replace ILINKs with real URLs
            content = content.replace(/ILINK\|([0-9]+),\|/g, 'http://www.surecw.com//'+site+'/page-$1')
          }
        }
      }
    }
    if(statusOK) {
      if(pageOK) {
        return content;
      } else {
        // invalid area name
        return '<p>No such area: There is no content named \''+area
               +'\' on page '+page+' of the '+site+' website.</p>';
      } 
    } else {
      // could not fetch page
      return '<p>No such page: The requested page (page '+page
             +' on the '+site+' website) no longer exists.</p>';
    }
  }
}




/* Checks submitted data from the 'get free calls' form.
 * Returns an object containing the following properties:
 *    errors: array of objects containing error messages;
 *      each item is of the form:
 *         {field:'fieldName', msg:'error message', additional:'extra info'}
 *      errors has zero length if there were no errors.
 *    you: PhoneNumber represting you, or null if error.
 *    code: code, or undefined if error.
 *    friend: PhoneNumber represting friend, or null if error.
 */
function checkFreeCallsData(you, code, friends, agree, allowNoFriends,
                            allowGuernseyNumbers) {
	// IS NOT CHECKED HERE IS CHECKED IN SERVER SIDE FUNCTIONS FOR PRE CODE CHECK :-0!!! which is why the switch didnt work - chris $("p").text("ALLOW GSY NO in checkFreeCallsData"+allowGuernseyNumbers);
  if(arguments.length<5)
    var allowNoFriends = false;
  if(arguments.length<6)
    var allowGuernseyNumbers = false;
  var errors = [];

  // Check the data for syntactic validity
  youParsed = new PhoneNumber(you);
  for(var friendsParsed=[], i=0, friendsLen=friends.length; i<friendsLen; i++)
    friendsParsed.push(new PhoneNumber(friends[i]));

  // Raise any error messages
  var okToRaiseFriendLocationError = false;
  // you
  if(you.length==0) {
    // nothing provided
    errors[errors.length] = {field:'you', msg:lang.errorYou};
  } else if(!youParsed.valid) {
    // invalid input
    errors[errors.length] = {
      field: 'you',
      msg: lang.errorYou,
      additional: lang.errorYouDetail
    };
  } else if(!allowGuernseyNumbers
            && (youParsed.areaCode==lang.areaCodeGSY
                || youParsed.areaCode==lang.areaCodeGSYAirtel
                || youParsed.areaCode==lang.areaCodeGSYWave)) {
    // valid input, but it's a Guernsey number
    errors[errors.length] = {
      field: 'you',
      msg: lang.errorYouGsy.replace(/%areaCodeGSY%/g, lang.areaCodeGSY),
      additional: '' //'ALLOW GSY NO in checkFreeCallsData' + allowGuernseyNumbers.toString()
    };
  } else if((!allowGuernseyNumbers
             && (youParsed.areaCode!=lang.areaCodeIOM
		             && youParsed.areaCode!=lang.areaCodeJSY
		             && youParsed.areaCode!=lang.areaCodeJSYAirtel
		             && youParsed.areaCode!=lang.areaCodeJSYJT))
		        || (allowGuernseyNumbers
                && (youParsed.areaCode!=lang.areaCodeGSY
                    && youParsed.areaCode!=lang.areaCodeGSYAirtel
		                && youParsed.areaCode!=lang.areaCodeGSYWave
		                && youParsed.areaCode!=lang.areaCodeIOM
				            && youParsed.areaCode!=lang.areaCodeJSY
				            && youParsed.areaCode!=lang.areaCodeJSYAirtel
				            && youParsed.areaCode!=lang.areaCodeJSYJT))) {
    // valid input, but it's not a Jersey or Isle of Man number
    // (or a Guernsey number, if allowGuernseyNumbers==true)
    errors[errors.length] = {
      field: 'you',
      msg: lang.errorYou,
      additional: lang.errorYouAreaCodeDetail
                  .replace(/%areaCodeGSY%/g, lang.areaCodeGSY)
                  .replace(/%areaCodeIOM%/g, lang.areaCodeIOM)
                  .replace(/%areaCodeJSY%/g, lang.areaCodeJSY)
    };
  } else {
    // valid input
    okToRaiseFriendLocationError = true;
  }
  // code
  if(code!==undefined) {
    if(code.length==0) {
      // nothing provided
      errors[errors.length] = {field:'code', msg:lang.errorCode};
    } else if(!/^[0-9]{5}$/.test(code)) {
      // invalid input
      errors[errors.length] = {
        field: 'code',
        msg: lang.errorCode,
        additional: lang.errorCodeDetail
      };
      code = undefined;
    }
  }
  // friends
  var noFriends = true, okToRaiseFriendInvalidError = true,
      okToRaiseFriendSameAsYouError = true;
  for(i=0; i<friendsLen; i++) {
    if(friends[i].length==0) {
      // nothing provided
    } else if(!friendsParsed[i].valid) {
      // invalid input
      if(okToRaiseFriendInvalidError) {
        errors[errors.length] = {
          field: 'friend'+i,
          msg: lang.errorFriend,
          additional: lang.errorFriendDetail
        };
        okToRaiseFriendInvalidError = false;
      }
      noFriends = false;
    } else if(youParsed.internalFormat==friendsParsed[i].internalFormat) {
      // valid input, but `friend` is the same number as `you`
      if(okToRaiseFriendSameAsYouError) {
        errors[errors.length] = {
          field: 'friend'+i,
          msg: lang.errorFriendSameAsYou,
          additional: lang.errorFriendSameAsYouDetail
        };
      }
      noFriends = false;
    } else {
      // valid input, and all's well
      noFriends = false;
    }
  }
  if(noFriends && !allowNoFriends) {
    errors[errors.length] = {field:'friend1', msg:lang.errorFriend};
  }
  
  if(!agree) {
    errors[errors.length] = {field:'agree', msg:lang.errorAgree};
  }

  return {
    errors: errors,
    you: youParsed,
    code: code,
    friends: friendsParsed,
    agree: agree
  };
}

