// JavaScript routines for Reggae Fever shop.
// 2006-12-07 Christian d'Heureuse (chdh@inventec.ch): File created.

// JSLint declarations:
/*jslint browser: true, devel: true, undef: true */
/*global window:false, ActiveXObject:false, _gat:false, DD_belatedPNG:false */

var skipFormValidation;
var lazyFormValidation;

//--- Misc. utility routines --------------------------------------------------

// Registers an event handler.
function registerEventHandler (node, eventName, eventHandler) {
   if (node.addEventListener) {                            // DOM compatible
      node.addEventListener (eventName,eventHandler,true); }
    else if (node.attachEvent) {                           // IE6
      node.attachEvent ("on"+eventName,eventHandler); }
    else {                                                 // old browsers
      node["on"+eventName] = eventHandler; }}

function getTime() {
   return new Date().getTime(); }

// Returns the elapsed time in milliseconds.
function getElapsedTime (startTime) {
   if (startTime === undefined) {
      return undefined; }
   return getTime() - startTime; }

function setFocus (elementId) {
   document.getElementById(elementId).focus(); }

// A FIFO queue implemented as a linked list.
function Fifo() {}
Fifo.prototype = {
   put: function (v) {
      var e = {value: v};
      if (this.tail === undefined) {
         this.head = e; }
       else {
         this.tail.next = e; }
      this.tail = e; },
   // Returns undefined if the queue is empty.
   get: function() {
      var e = this.head;
      if (e === undefined) {
         return undefined; }
      var next = e.next;
      this.head = next;
      if (next === undefined) {
         this.tail = undefined; }
      return e.value; },
   clear: function() {
      this.head = undefined;
      this.tail = undefined; }};

//--- Type checking and string routines ---------------------------------------

// Returns true if the argument string contains a valid number.
function isNumber (s) {
   return !isNaN(Number(s)); }

// Returns true if the argument string contains a valid integer value.
function isInteger (s) {
   var n = Number(s);
   if (isNaN(n)) {
      return false; }
   if ((n%1)!==0) {
      return false; }
   return true; }

function isValidEmailAddress (s) {
   var regex = /^[a-zA-Z0-9\.\_\%\+\-]+\@([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,6}$/;
     // Note: The same RegEx is also used in the Servlet to prevent insertion
     // of an invalid address by hacking.
   return regex.test(s); }

// Removes leading and trailing blanks from a string value.
function trimString (s) {
   return s.replace(/^\s+/,"").replace(/\s+$/,""); }

//--- Cookies -----------------------------------------------------------------

var cookiePrefix = "RFShop_";

function deleteCookie (cookieName, path) {
   var s = cookieName + "=";
   if (path) {
      s += "; path=" + path; }
   // s += "; max-age=0";             // max-age=0 is DOM compatible but does not work with Safari 3.1.2
   s += "; expires=Thu, 01-Jan-70 00:00:01 GMT";
   document.cookie = s; }

function setCookie (cookieName, cookieValue, permanent, path) {
   if (cookieValue == "") {
      deleteCookie (cookieName, path);
      return; }
   var s = cookieName + "=" + encodeURIComponent(cookieValue);
   if (path) {
      s += "; path=" + path; }
   if (permanent) {
      s += "; expires=Thu, 31-Dec-2037 23:00:00 GMT; max-age=315360000"; } // (IE6 needs "expires")
   document.cookie = s; }

function getCookie (cookieName, defaultValue) {
   var m = document.cookie.match("(^|;)\\s*"+cookieName+"=([^;]*)");
   if (!m) {
      return defaultValue; }
   var s = m[2];
   if (!s) {
      return defaultValue; }
   return decodeURIComponent(s); }

//--- Stylesheets -------------------------------------------------------------

function addStyleRule (selector, declaration) {
   var rule = selector+" {"+declaration+"}";
   if (!document.styleSheets) {
      return; }
   var ss = document.styleSheets[0];
   if (!ss) {
      return; }
// if (navigator.userAgent.indexOf("AppleWebKit")>=0) {    // Safari
//    ss.ownerNode.appendChild (document.createTextNode(rule));
//    return; }
   if (ss.insertRule) {                                    // DOM
      ss.insertRule (rule, ss.cssRules.length);
      return; }
   if (ss.addRule) {                                       // IE6
      ss.addRule (selector, declaration);
      return; }
   /* ignore */ }

//--- Form field validation ---------------------------------------------------

// Validates an integer form field.
function validateIntegerField (f) {
   var s = trimString(f.value);
   if (s == "") {
      return true; }
   if (!isInteger(s)) {
      alert ("Invalid integer value \"" + s + "\".");
      f.focus();
      return false; }
   return true; }

function validateRequiredField (f, msg) {
   var s = trimString(f.value);
   if (s != "") {
      return true; }
   alert (msg);
   f.focus();
   return false; }

function validateEmailField (f, msg, optional) {
   var s = trimString(f.value);
   if (!s && optional) {
      return true; }
   if (isValidEmailAddress(s)) {
      return true; }
   alert (msg);
   f.focus();
   return false; }

//--- Show / hide elements and text --------------------------------------------

function showElementObj (element, visible, visibleDisplayAttrib) {
   if (visible === undefined) {
      visible = true; }
   if (visibleDisplayAttrib === undefined) {
      visibleDisplayAttrib = "block"; }
   var newDisplay = visible ? visibleDisplayAttrib : "none";
   try {
      element.style.display = newDisplay; }
    catch (x) {
      element.style.display = "block"; }}                   // for IE6

function showElement (elementId, visible, visibleDisplayAttrib) {
   var e = document.getElementById(elementId);
   if (!e) {
      alert ("showElement: Element \""+elementId+"\" not found.");
      return; }
   showElementObj (e, visible, visibleDisplayAttrib); }

//--- Menu ---------------------------------------------------------------------

var noOfMenuBlocks = 10;
var menuState = 0;

function saveMenuState() {
   setCookie (cookiePrefix+"menuState", menuState); }
function loadMenuState() {
   menuState = Number(getCookie(cookiePrefix+"menuState", 0)); }

function isMenuBlockOpen (menuNo) {
   return (menuState & (1<<(menuNo-1))) !== 0; }

function showMenuBlock (menuNo, visible) {
   showElement ("menuBlock"+menuNo, visible);
   if (visible) {
      menuState |= (1<<(menuNo-1)); }
    else {
      menuState &= ~(1<<(menuNo-1)); }
   saveMenuState(); }

function toggleMenuBlock (menuNo) {
   showMenuBlock (menuNo, !isMenuBlockOpen(menuNo)); }

function initMenuBlocks() {
   loadMenuState();
   for (var menuNo=1; menuNo<=noOfMenuBlocks; menuNo++) {
      if (isMenuBlockOpen(menuNo)) {
         addStyleRule ("#menuBlock"+menuNo, "display:block"); }}}

//--- Popups -------------------------------------------------------------------

var activePopup;
var closedPopup;
var popupOpenTime;
var popupCloseTime;
var popupCloseEventHandlerRegistered;
var mouseInPopup;

function closePopup() {
   if (activePopup === undefined) {
      return; }
   showElement (activePopup, false);
   closedPopup = activePopup;
   activePopup = undefined;
   mouseInPopup = false;
   popupCloseTime = getTime(); }

function toggleClosePopup (popupId) {
   if (popupId == activePopup) {
      closePopup(); return true; }
   if (activePopup === undefined && closedPopup == popupId) {  // the mousedown event has closed the popup
      if (getElapsedTime(popupCloseTime) < 200) {
         return true; }}
   return false; }

function popupCloseEventHandler() {
   if (activePopup === undefined || mouseInPopup) {
      return; }
   if (getElapsedTime(popupOpenTime) < 200) {
      return; }
   closePopup(); }

function popupMouseOverEventHandler() {
   mouseInPopup = true; }

function popupMouseOutEventHandler (e) {
   // (This event handler is also called when the mouse moves out of a
   // sub-element of the popup, but we ignore that because the mouseOver
   // event is called immediately afterwards in this case).
   mouseInPopup = false; }

function openPopup (popupId) {
   if (activePopup == popupId) {
      return; }
   closePopup();
   showElement (popupId);
   activePopup = popupId;
   mouseInPopup = false;
   var e = document.getElementById(popupId);
   e.onmouseover = popupMouseOverEventHandler;
   e.onmouseout = popupMouseOutEventHandler;
   if (!popupCloseEventHandlerRegistered) {
      registerEventHandler (document.body, "mousedown", popupCloseEventHandler);
      popupCloseEventHandlerRegistered = true; }
   popupOpenTime = getTime(); }

//--- URL building and navigation ---------------------------------------------

function combineUrlAndQueryString (baseUrl, queryString) {
   if (baseUrl.indexOf("?") == -1) {
      return baseUrl+"?"+queryString; }
    else {
      return baseUrl+"&"+queryString; }}

function refreshPage() {
   window.location.reload(); }

//--- HTTP communication routines ----------------------------------------------

var asyncHttpRequestQueue = new Fifo();
var asyncHttpRequestActive = false;

var startNextAsyncHttpRequest;                             // forward declaration

function handleAsyncHttpRequestEvent (req, job) {
   if (req.readyState != 4) {
      return; }
   asyncHttpRequestActive = false;
   var s;
   if (req.status == 200) {
      s = req.responseText; }
    else {
      s = "Error while retrieving "+job.url+": "+req.statusText; }
   job.resultProcessingFunction (s);
   startNextAsyncHttpRequest(); }

// Returns: true = ok, false = error.
startNextAsyncHttpRequest = function() {
   if (asyncHttpRequestActive) {
      return true; }
   var job = asyncHttpRequestQueue.get();
   if (job === undefined) {
      return true; }
   var req;
   if (window.XMLHttpRequest) {
      req = new XMLHttpRequest(); }
    else if (window.ActiveXObject) {
      req = new ActiveXObject("Microsoft.XMLHTTP"); }
    else {
      alert ("Unable to retrieve dynamic content because your browser does not support XMLHttpRequest.");
      return false; }
   req.onreadystatechange = function() {
      handleAsyncHttpRequestEvent (req, job); };
   req.open ("GET", job.url, true);
   req.send (null);
   asyncHttpRequestActive = true;
   return true; };

// Starts an asynchronous HTTP request.
// Returns: true = ok, false = error.
function startHttpRequest (url, resultProcessingFunction) {
   var job = {
      url: url,
      resultProcessingFunction: resultProcessingFunction};
   asyncHttpRequestQueue.put (job);
   return startNextAsyncHttpRequest(); }

// Performs a synchronous HTTP request.
// Returns the response string or undefined if an error occurred.
function synchHttpRequest (url) {
   var req;
   if (window.XMLHttpRequest) {
      req = new XMLHttpRequest(); }
    else if (window.ActiveXObject) {
      req = new ActiveXObject("Microsoft.XMLHTTP"); }
    else {
      return undefined; }
   req.open ("GET", url, false);
   req.send (null);
   if (req.readyState != 4) {
      alert ("Error while retrieving "+url+": readyState="+req.readyState);
      return undefined; }
   if (req.status != 200) {
      alert ("Error while retrieving "+url+": "+req.statusText);
      return undefined; }
   var s = req.responseText;
   if (!s) {
      alert ("Error while retrieving "+url+": empty response received.");
      return undefined; }
   return s; }

//--- Load static content asynchronously ---------------------------------------

var asyncContentRequested = {};

// Returns true if the content for targetId has already been requested and possibly already loaded.
function isAsynchContentRequested (targetId) {
   return asyncContentRequested[targetId] !== undefined; }

// Gets static content via an asynchronous HTTP request and stores it in the document.
function loadAsynchContent (url, targetId) {
   asyncContentRequested[targetId] = true;
   function resultProcessingFunction (s) {
      document.getElementById(targetId).innerHTML = s; }
   startHttpRequest (url, resultProcessingFunction); }

//--- Cart form ---------------------------------------------------------------

function validateCartForm2() {
   var f = document.getElementById("cartForm");
   var iel = f.getElementsByTagName("input");
   for (var p=0; p<iel.length; p++) {
      var e = iel[p];
      var en = e.name;
      if (en && en.match("^quantity_")) {
         if (!validateIntegerField(e)) {
            return false; }}}
   return true; }

function validateCartForm() {
   try {
      return validateCartForm2(); }
    catch (e) {
      alert ("Error in validateCartForm: "+e);
      return false; }}

function updateCart (evt) {
   // Problem: Beim drücken von Enter mit einer falschen Eingabe kommt die Fehlermeldung doppelt. Bis jetzt keine Lösung gefunden.
   if (!validateCartForm()) {
      return false; }
   document.getElementById("cartForm").submit();
   return true; }

//--- Cart --------------------------------------------------------------------

function setLinkImage (link, imageFileName) {
   var imgs = link.getElementsByTagName("img");
   if (imgs.length === 0) {
      return; }
   var img = imgs[0];
   img.src = "images/"+imageFileName; }

function completeAddToCart (articleKey, link, resp, syncUrl) {
    if (resp != "ok") {
       if (resp == "err_cookieProblem") {
          alert ("Error: The session cookie has been lost.\nPlease change your browser settings to enable cookies."); }
        else {
          alert ("Error: Invalid response from server: "+resp); }
       window.location = syncUrl;                          // fallback, to enable filling the cart when ajax doesn't work
       return; }
   setLinkImage (link, "cartFull.gif");
   var cartIndicatorImg = document.getElementById("cartIndicatorImg");
   if (cartIndicatorImg) {
      cartIndicatorImg.src = "images/cartFull.gif"; }}

function addToCart (articleKey, link) {
   var syncUrl = "cartSet?article="+articleKey;
   var asyncUrl = syncUrl+"&ajax=1";
   link.onclick = "";                                      // disable link
   setLinkImage (link, "cartTransition.gif");
   function resultProcessingFunction (resp) {
      completeAddToCart (articleKey, link, resp, syncUrl); }
   if (!startHttpRequest(asyncUrl, resultProcessingFunction)) {
      window.location = syncUrl;                           // fallback, to enable filling the cart when Ajax doesn't work
      return; }}

//--- Address input form ------------------------------------------------------

// This validation is also done when the "back" button is pressed.
function validateAddressInputForm2a (f) {
   if (skipFormValidation) {
      return true; }
   if (f.email !== undefined && !validateEmailField(f.email, "Your email address does not look valid.")) {
      return false; }
   if (f.email2 !== undefined && !validateEmailField(f.email2, "Your second email address does not look valid.", true)) {
      return false; }
   return true; }

// This validation is only done when the "continue" or "save" buttons are used.
function validateAddressInputForm2b (f) {
   if (skipFormValidation || lazyFormValidation) {
      return true; }
   if (f.email !== undefined && !validateRequiredField(f.email, "Please enter your email address.")) {
      return false; }
   if (!validateRequiredField(f.firstName, "Please enter your first name.")) {
      return false; }
   if (!validateRequiredField(f.lastName, "Please enter your last name.")) {
      return false; }
   //...
   if (!validateRequiredField(f.country, "Please select your country from the list.")) {
      return false; }
   //...
   return true; }

function validateAddressInputForm (f) {
   try {
      if (!validateAddressInputForm2a(f)) {
         return false; }
      if (!validateAddressInputForm2b(f)) {
         return false; }
      return true; }
    catch (e) {
      alert ("Error in validateAddressInputForm: "+e);
      return false; }}

function validateCheckoutAddrForm (f) {
   return validateAddressInputForm(f); }

function validateProfileForm (f) {
   return validateAddressInputForm(f); }

//--- Change password form -----------------------------------------------------

function validateChangePasswordForm2 (f) {
   if (skipFormValidation) {
      return true; }
   var pw = trimString(f.newPassword.value);
   var pw2 = trimString(f.newPassword2.value);
   if (pw != pw2) {
      alert ("Passwords are not identical.");
      return false; }
   if (!pw) {
      alert ("Empty password not allowed.");
      return false; }
   return true; }

function validateChangePasswordForm (f) {
   try {
      return validateChangePasswordForm2(f); }
    catch (e) {
      alert ("Error in validateChangePasswordForm: "+e);
      return false; }}

//--- Currency selection -------------------------------------------------------

function switchCurrency (sel, resumeUrl) {
   var currencyCode = sel.value;
   window.location = "switchCurrency?currency="+currencyCode+"&resume="+resumeUrl; }

//--- MP3 samples -------------------------------------------------------------

function openSamples (articleKey, link) {
   var popupId = "samples_"+articleKey;
   if (toggleClosePopup(popupId)) {
      return; }
   openPopup (popupId);
   if (isAsynchContentRequested(popupId)) {
      return; }
   var url = "trackList?articleKey="+articleKey;
   loadAsynchContent (url, popupId); }

//--- Google Analytics --------------------------------------------------------

function googleAnalytics() {
   if (window._gat === undefined) {
      return; }
   try {
      var pageTracker = _gat._getTracker("UA-8718395-1");
      pageTracker._trackPageview(); }
    catch (err) {}}

//--- Init --------------------------------------------------------------------

function preLoadInit() {
   initMenuBlocks(); }
preLoadInit();

function contentLoadedEvent() {
   switch (document.body.className) {
      case "login":
         setFocus ("loginFormUserId");
         break;
      case "recoverPw":
         setFocus ("recoverPwFormEmail");
         break;
      case "profile":
         setFocus ("email2Field");
         break;
      case "changePassword":
         setFocus ("newPasswordField");
         break;
      case "checkoutAddrL":
         setFocus ("remarksField");
         break;
      case "checkoutAddrN":
         setFocus ("emailField");
         break; }
   googleAnalytics(); }

function fixupTransparentPngs() {
   if (window.DD_belatedPNG === undefined) {
      return; }
   var a = document.getElementsByTagName("img");
   for (var i=0; i<a.length; i++) {
      var img = a[i];
      if (img.src.indexOf(".png") != -1) {
         DD_belatedPNG.fixPng (img); }}}

function onLoadEvent() {
   switch (document.body.className) {
      case "index":
         fixupTransparentPngs();
         break; }}
