// Handle image preview display, form hints.

(function() {
  var initPage = function () {
    var eltThumbs = document.getElementById('thumbs');
    var arEltThumb = eltThumbs.getElementsByTagName('img');
    var eltField = document.getElementById('sDesign');

    var aaEltPreviewByDesignStr = {};
    var aaEltThumbByDesignStr = {};

    for (var ix = 0, ct = arEltThumb.length; ix < ct; ix++) {
      var id = arEltThumb[ix].id;
      aaEltPreviewByDesignStr[id] = document.getElementById(id + 'Mini');
      aaEltThumbByDesignStr[id] = arEltThumb[ix];
    }

    var handleImgClick = function (e) {
      var event = e || window.event;
      var elt = event.target || event.srcElement;

      if (elt == eltThumbs) {
	return;
      }

      if (eltField.value != '') {
	aaEltPreviewByDesignStr[eltField.value].style.display = 'none';
	aaEltThumbByDesignStr[eltField.value].className = '';
      }

      eltField.value = elt.id;
      aaEltPreviewByDesignStr[eltField.value].style.display = 'block';
      aaEltThumbByDesignStr[eltField.value].className = 'selected';
    }

    eltThumbs.onclick = handleImgClick;

    if (eltField.value != '') {
      // design was preselected (possible form error) - reselect it.
      aaEltPreviewByDesignStr[eltField.value].style.display = 'block';
      aaEltThumbByDesignStr[eltField.value].className = 'selected';
    }

    // The captcha image has a limited number of allowed reloads
    var eltImgCaptcha = document.getElementById('captcha');
    var eltLinkCaptcha = document.getElementById('captcha-link');
    var ctTry = 5;

    var handleCaptchaClick = function (e) {
      var surl = eltImgCaptcha.src;
      var ixEqualNext = surl.lastIndexOf('=') + 1;
      var ct = surl.slice(ixEqualNext) - 0;

      if (ct < ctTry) {
	eltImgCaptcha.src = eltImgCaptcha.src.slice(0, ixEqualNext) + (ct + 1);
      }
      if (ct + 1 == ctTry) {
	eltLinkCaptcha.style.display = 'none';
      }
      return false;
    }
    eltImgCaptcha.onclick = handleCaptchaClick;
    eltLinkCaptcha.onclick = handleCaptchaClick;


    // return here to have a working form with only server-side validation
    // and no in-place hints.

    function bNonEmptyString(s) {
      return s != '';
    }

    function bValidMailbox(s) {
      // This function (but not any surrounding code) is copyright
      // (c) 2007 David Smith (dave a t sheepshank d o t org).
      // This work is licensed under a Creative Commons Attribution
      // 2.0 UK: England & Wales License.
      // http://creativecommons.org/licenses/by/2.0/uk/
      
      // The regular expression below is based on RFC2822. It matches
      // the 'mailbox' token defined in that RFC, with the following
      // changes: no obsolete parts; no comments; no domain literals;
      // no spaces within or around the domain; no unquoted spaces in
      // the local-part; at least one dot in the domain; no CRLF
      // allowed.

      // It is believed to be accurate but YMMV. Use at your own risk.

      // Examples that PASS this test (one example per line):
      // jdoe@example.org
      // <boss@nil.test>
      // John Doe <jdoe@machine.example>
      // Who? <one@y.test>
      // "Joe Q. Public" <john.q.public@example.com>
      // Joe "Q." Public <john.q.public@example.com>
      // "Giant; \"Big\" Box" <sysservices@example.net>
      // Giant \'Big\' Box <sysservices@example.net>
      // "john q. doe"@machine.example
      // John "Q." Doe <"john q. doe"@machine.example>

      // Examples that FAIL this test (reason after the dash):
      // me  - no domain
      // me@you  - domains must have a dot
      // me@you.  - that's not at the end
      // me@.you  - or the beginning
      // me me@example.com  - address spec not within <>
      // my.name <me@example.com>  - no unquoted dots allowed there
      // me@example . com  - no spaces allowed there
      // me@ example.com  - or there
      // me @example.com  - or there
      // me < me@example.com >  - or there
      // me@[1.2.3.4]  - domain literals not supported
      return /^(([\x20\x09]*[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+[\x20\x09]*|[\x20\x09]*\x22([^\x00\x0a\x0d\x22\x5c\x80-\xff]|\x5c[\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e-\x7f])*[\x20\x09]*\x22[\x20\x09]*)*[\x20\x09]*\x3c([\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+(\x2e[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+)*|[\x20\x09]*\x22([^\x00\x0a\x0d\x22\x5c\x80-\xff]|\x5c[\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e-\x7f])*[\x20\x09]*\x22[\x20\x09]*)\x40[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+(\x2e[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+)+\x3e[\x20\x09]*|([\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+(\x2e[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+)*|[\x20\x09]*\x22([^\x00\x0a\x0d\x22\x5c\x80-\xff]|\x5c[\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e-\x7f])*[\x20\x09]*\x22[\x20\x09]*)\x40[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+(\x2e[\x21\x23-\x27\x2a\x2b\x2d\x2f\x30-\x39\x3d\x3f\x41-\x5a\x5e-\x7e]+)+)$/.test(s);
    }


    // Some fields have in-place hints that disappear onfocus and
    // reappear if the content is empty onblur. All fields validate
    // client-side (as well as server-side).
    var aaFieldInfoById = {
      'sDesign': {
	validate: bNonEmptyString
      },
      'sEmailRecipient': {
	sHint: ' friend@example.com',
	validate: bValidMailbox
      },
      'sMessage': {
	sHint: ' Your message (no HTML)',
	validate: bNonEmptyString
      },
      'sNameSender': {
	sHint: ' Your name (not your email)',
	validate: bNonEmptyString
      },
      'sValediction': {
	validate: bNonEmptyString
      },
      'sCodeCaptcha': {
	sHint: ' Type the text above',
	validate: bNonEmptyString
      }
    }
    var aaEltFieldById = {};
    var aaEltErrorById = {};

    var clearHintMaybe = function (elt) {
      if (elt.className == 'hint') {
        elt.className = '';
        elt.value = '';
      }
    }

    var setHintMaybe = function (elt) {
      if (elt.value == '' || elt.value == aaFieldInfoById[elt.id].sHint) {
        elt.className = 'hint';
        elt.value = aaFieldInfoById[elt.id].sHint;
      }
    }

    var handleInputFocus = function (e) {
      var event = e || window.event;
      var elt = event.target || event.srcElement;
      clearHintMaybe(elt);
    }

    var handleInputBlur = function (e) {
      var event = e || window.event;
      var elt = event.target || event.srcElement;
      setHintMaybe(elt);
    }

    // Assign handlers for fields to show/hide the hind as needed.
    for (var id in aaFieldInfoById) {
      var elt = document.getElementById(id);
      aaEltFieldById[id] = elt;

      if (aaFieldInfoById[id].sHint) {
	elt.onfocus = handleInputFocus;
	elt.onblur = handleInputBlur;

	setHintMaybe(elt);
      }

      aaEltErrorById[id] = document.getElementById(id + '-error');
    }

    // Client-side validation.
    var eltForm = document.getElementById('sendCard');
    var eltFormError = document.getElementById('sendCard-error');

    eltForm.onsubmit = function (e) {
      var bValid = true;

      for (var id in aaFieldInfoById) {
	var finfo = aaFieldInfoById[id];

	// yes, this does work for a select field.
	var value = aaEltFieldById[id].value;
	
	if ((finfo.sHint && value == finfo.sHint)
	    || (finfo.validate && !finfo.validate(value))) {
	  bValid = false;
	  aaEltErrorById[id].className = 'error';
	} else {
	  aaEltErrorById[id].className = 'errorHidden';
	}
      }

      eltFormError.className = bValid ? 'errorHidden' : 'error';

      return bValid; // submit the form if true, don't if false.
    };

  }

  var fn = window.onload;
  window.onload = function() {
      fn && fn();
      initPage(); 
  };
})();
