/* Behold.  The CNU Namespace */
var CNU = {};

/* * * CNU config * * */
CNU.config = {};
CNU.config.cluster = '';
CNU.config.brand = '';
CNU.config.country = '';
CNU.config.language = '';

/* Assistant Debug Switch */
CNU.config.DEBUG_ASSISTANT = false;

/* General Console Debug Switch */
CNU.config.DEBUG = false;

/* ON/OFF switch for Form Submit Validation */
CNU.config.VALIDATE_FORMS = true;

/* ON/OFF switch for entire Validator Assistant */
CNU.config.VALIDATE = true;

/* regex's */
CNU.config.regex = {};
CNU.config.regex['email_address'] = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;

/* Utility Functions */
CNU.util = {};
CNU.ev = {};
CNU.dom = {};

// check for visibility through DOM ancestors
CNU.dom.is_visible = function (element) {

  if (typeof element.ancestors == undefined) { 
    var el = $(element);
  } else { 
    var el = element;
  }

  // IE complains about ancestors without $ function
  try {
    var ancestors = el.ancestors();
  } catch(err) {
    var ancestors = $(el).ancestors();
  }

  for (var i = 0; i < ancestors.length; i++ ) {
    if ((! ancestors[i].visible()) || (ancestors[i].style.visibility == 'hidden')) return false;
  }
  return true;
};

CNU.dom.hideByClass = function (searchClass,node,tag) {
  var elements = CNU.dom.getElementsByClass(searchClass, node, tag);
  var elsLen = elements.length;
  for (var i = 0; i < elsLen; i++) {
    elements[i].style.display = 'none';
  }
};

/* logging functions */
function log   (msg) { if (console == undefined) { var console = $(document.createElement('div')); } CNU.util.msg('LOG  : '+msg, 'log', console); }
function debug (msg) { if (console == undefined) { var console = $(document.createElement('div')); } CNU.util.msg('DEBUG: '+msg, 'debug', console); }
function error (msg) { if (console == undefined) { var console = $(document.createElement('div')); } CNU.util.msg('ERROR: '+msg, 'error', console); }
function warn  (msg) { if (console == undefined) { var console = $(document.createElement('div')); } CNU.util.msg('WARN : '+msg, 'warn', console); }

/* messaging system for logging. */
CNU.util.msg = function (message, type, console) { 
  if (CNU.config.DEBUG == true) {
    try {
      switch(type) {
        case 'log':   console.log(message);
                      break;
        case 'error': console.error(message);
                      break;
        case 'warn':  console.warn(message);
                      break;
        case 'debug': console.debug(message);
                      break;
      }
    } catch (err) {

      if (!console) console = $(document.createElement('div'));
      console.id = 'console';
      console.style.position = 'absolute';
      console.style.top = '0';
      console.style.left = '0';
      console.style.backgroundColor = '#CCCCCC';
      
      document.body.appendChild(console);
        
      var log = $(document.createElement('div'));
      log.appendChild(document.createTextNode(message));
      console.appendChild(log);

    }
  }
};


/* Chains event functions to window.onload */
CNU.ev.addLoadEvent = function (func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      /* REFACTOR 4036: this if () is always true, due to typeof check above */
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
};
CNU.util.is_active = function () { document.getElementsByTagName('body')[0].addClassName('js'); };


/* addEvent attachment */
CNU.ev.addEvent = function ( obj, type, fn ) {
  if (obj.addEventListener) {
    obj.addEventListener( type, fn, false );
    CNU.ev.EventCache.add(obj, type, fn);
  }
  else if (obj.attachEvent) {
    obj["e"+type+fn] = fn;
    obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
    obj.attachEvent( "on"+type, obj[type+fn] );
    CNU.ev.EventCache.add(obj, type, fn);
  }
  else {
    obj["on"+type] = obj["e"+type+fn];
  }
}

CNU.ev.EventCache = function () {
  var listEvents = [];
  return {
    listEvents : listEvents,
    add : function(node, sEventName, fHandler){
      listEvents.push(arguments);
    },
    flush : function(){
      var i, item;
      for(i = listEvents.length - 1; i >= 0; i = i - 1){
        item = listEvents[i];
        if(item[0].removeEventListener){
          item[0].removeEventListener(item[1], item[2], item[3]);
        };
        if(item[1].substring(0, 2) != "on"){
          item[1] = "on" + item[1];
        };
        if(item[0].detachEvent){
          item[0].detachEvent(item[1], item[2]);
        };
        item[0][item[1]] = null;
      };
    }
  };
}();
CNU.ev.addEvent(window,'unload',CNU.ev.EventCache.flush);

/* thank you, quirksmode */
CNU.ev.getTarget = function (e) { 
  var targ;
  if (!e) var e = window.event;
  if (e.target) targ = e.target;
  else if (e.srcElement) targ = e.srcElement;
  if (targ.nodeType == 3) targ = targ.parentNode;
  return targ;
};

/* inspect */
function inspect (o) { return CNU.util.inspect(o); }
CNU.util.inspect = function (o) {
  var r = '{';
  for (var k in o) { r += k + ': ' + o[k] + ','; }
  r.replace(/,$/,'');
  r += '}';
  return r;
};

// returns first form element found of a specific class
// this is useful because it stays within the given form
// not the whole document.
CNU.dom.getChildElementByClass = function (class_name, form) {
  var el = form;
  var elements = $(form).immediateDescendants();
  for (var i = elements.length-1; i > 0; i--) {
    if ($(elements[i]).hasClassName(class_name)) {
      el = elements[i];
      i = 0;
    } else {
    }
  }
  return el;
};

// returns first form element found of a specific class
// this is useful because it stays within the given form
// not the whole document.
CNU.dom.getDescendantElementByClass = function (class_name, form) {
  var el = null;
  var desc = $(form).descendants();
  for (var i = desc.length-1; i > 0; i--) {
    if ($(desc[i]).hasClassName(class_name)) {
      el = desc[i];
      i = 0;
    }
  }
  return el;
};


/* grab Elements from the DOM by className */
CNU.dom.getElementsByClass = function (searchClass,node,tag) {
  var i = 0;
  var j = 0;
  var classElements = new Array();
  if ( node == null )
    node = document;
  if ( tag == null )
    tag = '*';
  var els = node.getElementsByTagName(tag);
  var elsLen = els.length;
  var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
  for (i = 0, j = 0; i < elsLen; i++) {
    if ( pattern.test(els[i].className) ) {
      classElements[j] = els[i];
      j++;
    }
  }
  return classElements;
};

CNU.dom.insertAfter = function (parent, node, referenceNode) { parent.insertBefore(node, referenceNode.nextSibling); }

/* utilities for returning all form tags from the document */
CNU.dom.get_forms = function () { return document.getElementsByTagName('form'); };
CNU.dom.get_inputs = function (form) { return form.getElementsByTagName('input'); };
CNU.dom.get_selects = function (form) { return form.getElementsByTagName('select'); };
CNU.dom.get_textareas = function (form) { return form.getElementsByTagName('textarea'); };

/* Extend certain portions of the built-in dom */
CNU.dom.extend_string = function () {

  if (!String.prototype.contains) {
    String.prototype.contains = function (t) { return this.indexOf(t) >= 0 ? true : false; }
  }
  if (!String.prototype.trim) {
    String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }
  }

};


/* Build Assistant */
CNU.Assistant = function () {

  // private method for saying things to the user.
  var say = function (message) {
    if (CNU.config.DEBUG_ASSISTANT == true) {
      try {
        if (!console) {
          $('content_main').appendChild(document.createTextNode("Assistant says: "+message));
          $('content_main').appendChild(document.createElement("<br />"));
        } else console.log("Assistant says: "+message);
      } catch (err) {
        // nothing
      }
    }
  };

  // Validator takes an object.
  // Validator validates that object
  function Validator (element, initialize) {

    this.initialize = initialize || true;
    this.o = element;

    this.value = null;
    this.name = this.o.name;
    this.id = this.o.id;
    this.classes = this.o.className;
    this.result = true;
    this.message = this.MESSAGES['default'];
    this.msgElement = this.get_error_element();

    if (this.initialize) this.init();

  }

  Validator.prototype.init = function () {
    if (this.needs_validator(this.o)) { 
      switch (this.o.nodeName) {

        // find all class names, validate against classnames
        case 'TEXTAREA':  // say('VALIDATING textarea...');
                          this.value = this.o.value;
                          this.result = this.is_valid();
                          break;
  
        // find all class names, validate against classnames
        case 'INPUT':     // say('VALIDATING input...');
                          if (this.o.getAttribute('type') != 'hidden') {
                            this.value = this.o.value;
                            this.result = this.is_valid();
                          }
                          break;
  
        // find all class names, validate against classnames
        case 'SELECT':    // say('VALIDATING select...');
                          this.value = this.o.options[this.o.selectedIndex].value;
                          this.result = this.is_valid();
                          break;
        
        // find all forms, validate each form
        case '#document': // say('VALIDATING document...');
                          this.forms();
                          break;
  
        // find all form elements, validate each element
        case 'FORM':      // say('----------- INIT: VALIDATING form...');
                          this.inputs(this.o);
                          break;
  
      
        // can't do jack shit.
        default:          // say("Can't validate " + this.o.nodeName);
                          break;
      }
    }
  }


  Validator.prototype.MESSAGES = { 
    'is_required' : "This field is required.", 
    'matches_syntax' : "Improper Format.", 
    'default' : "There is an error in this field",
    'form' : "There is an error in this form" 
  };

  Validator.prototype.empty_message_container = function () {
    var container = document.createElement('div');
    container.className = 'error_message';
    container.setAttribute('id', 'error_message_'+this.id);
    return container;
  }

  Validator.prototype.HASCALENDAR_STRING = new String('hasCalendar');
  Validator.prototype.DATE_STRING = new String('date');
  Validator.prototype.CALENDAR_STRING = new String('calendar');
  Validator.prototype.REQUIRED_STRING = new String('required');
  Validator.prototype.ERROR_STRING = new String('error');
  Validator.prototype.MARITAL_STATUS_STRING = new String('marital_status_cd');

  Validator.prototype.is_checkbox = function () { 
    var r = false;
    try { r = (this.o.getAttribute('type') == 'checkbox'); }
    catch (err) { /* do nothing -- object doesn't support this method, which is no big deal.  */ }
    return r;
  };

  Validator.prototype.is_checked = function () {
    var r = false;
    try { r = (this.o.checked); }
    catch (err) { /* do nothing -- object doesn't support this method, which is no big deal.  */ }
    return r;
  };
    

  Validator.prototype.is_required = function () { return this.classes.contains(this.REQUIRED_STRING); };

  Validator.prototype.is_present = function () { 
    if (this.is_checkbox()) return this.is_checked();
    if (this.o.nodeName == 'SELECT') { 

      // start with the current select tag's value
      var result = ((this.value !== null) && (this.value !== ''));

      // loop through the rest of the selects, if there are any.
      var selects = $(this.o.parentNode).getElementsByTagName('select');
      for (var i = 0; i < selects.length; i++) {
        var select_value = selects[i].options[selects[i].selectedIndex].value;
        result = result && ((select_value !== null) && (select_value !== ''));
      }
      return result;
      
    }
    return ((this.value !== null) && (this.value.trim() !== '')); 
  };

  Validator.prototype.has_syntax_rules = function () {
    var r = this.get_syntax_name();
    return (r != false);
  };

  Validator.prototype.is_valid = function () { 
    var r = true;
    if (this.is_required()) {
      if (! this.has_syntax_rules()) { 
        r = this.is_present();
        if (! r) this.message = this.MESSAGES['is_required'];
      } else {
        r = this.is_present();
        if (! r) {
          this.message = this.MESSAGES['is_required'];
        } else {
          r = this.matches_syntax();
          if (! r) this.message = this.MESSAGES['matches_syntax'];
        }
      }
    } else {
      if (this.has_syntax_rules() && this.is_present()) {
        r = this.matches_syntax();
        if (! r) this.message = this.MESSAGES['matches_syntax'];
      }
    }
    return r;
  };

  Validator.prototype.prepare_value = function () {
    var str = new String(this.o.value)
    str = str.replace(/(^\s+|\s+$)/g, '');
    str = str.replace(/\s\s+/g, ' ');
    return str;
  };

  Validator.prototype.matches_syntax = function () {
    var v = this.prepare_value();
    this.MESSAGES['matches_syntax']= 'Improper Format';
    var syntax = this.get_syntax(); // Here we got collection of validation cases
    for (var validation_case in syntax['validation_cases']){ // for each validation case
      var s = syntax['validation_cases'][validation_case]; // get validation case
      if(s){ // If validation case is defined
        if (s['mask'] instanceof RegExp) { // If validation case is regular expression
          // All previous checks should be valid AND this check should be valid
          if(!s['mask'].test(v)){ // If not then
            if(s['error_message']){ // If custom error message is defined
              this.MESSAGES['matches_syntax']=s['error_message']; // Set up Error message for this validator
            }
            return false; // And return false (Input is not valid)
          }
        }
      }
    }
    return true; // By default input is valid
  };

  Validator.prototype.get_syntax = function () { 
    var s_name = this.get_syntax_name();
    var r = CNU.config.regex[s_name]; 
    return r;
  };

  Validator.prototype.get_syntax_name = function () {
    var syntax_name = this.classes;
    var reserved_words = [  new RegExp(this.CALENDAR_STRING), 
                            new RegExp(this.DATE_STRING), 
                            new RegExp(this.HASCALENDAR_STRING), 
                            new RegExp(this.REQUIRED_STRING), 
                            new RegExp(this.ERROR_STRING) ];
    $A(reserved_words).each(function (reserved_word) { syntax_name = syntax_name.replace(reserved_word, ''); });
    syntax_name = syntax_name.trim();
    return syntax_name || false;
  };

  Validator.prototype.needs_validator = function (element) { 
    if (element.nodeName == '#document') { element = document.getElementsByTagName('body')[0]; }
    if (element.id.match('customer___person___ssn')) return true;
    if (element.id.match('last4')) return false;
    if (element.id.match('ssn')) return false;
    if (! CNU.dom.is_visible(element)) return false;
    return (! $(element).hasClassName('valid')); 
  };

  Validator.prototype.forms = function () {
    var f = null;
    var all_forms = CNU.dom.get_forms();
    for (var i = 0; i < all_forms.length; i++) {
      f = all_forms.item(i);
      if (this.needs_validator(f)) {
        if (this.has_submit_once(f)) {
          var btn = this.get_submit_once(f);
          var oldonclick = btn.onclick;
          if (typeof btn.onclick != 'function') {
            btn.onclick = function () { var validation = new Validator(this); return validation.result; }
          } else { 
            btn.onclick = function() {
              var validation = new Validator(this.form);
              if (validation.result == true) {
                if (oldonclick) { oldonclick(); }
              }
            }
          }
        }
        f.onsubmit = function () { 
          if (typeof CNU.config.submit == 'function') { CNU.config.submit(); }
          var validation = new Validator(this);

          if (validation.result) validation.unset_form_error(this);
          else validation.set_form_error(this);

          /* Check to see if form submition validation is turned on */
          if (CNU.config.VALIDATE_FORMS == true) return validation.result;
          else return true;
        };

        this.enable_form_events(f);
      }
    }
  };

  Validator.prototype.unset_form_error = function (f) {
    // get all 'form_message' className
    var form_error = CNU.dom.getDescendantElementByClass('form_error', f);
    if (form_error) x = $(form_error).remove();
  };

  Validator.prototype.set_form_error = function (f) { 
    this.unset_form_error(f);
    // generate message
    var msgNode = document.createElement('div');
    msgNode.innerHTML = this.MESSAGES['form']; 
    $(msgNode).addClassName('form_error');

    // get actions fieldset
    var fieldset = CNU.dom.getChildElementByClass('actions', f);

    // append message
    try {
      fieldset.appendChild(msgNode);
    } catch (err) { 
      f.appendChild(msgNode); 
    }
    f.addClassName('f_error');
  };

  Validator.prototype.has_submit_once = function (form) {
    var r = false;
    r = CNU.dom.getElementsByClass('submit_once', form)[1];
    return r;
  };

  Validator.prototype.get_submit_once = function (form) { return CNU.dom.getElementsByClass('submit_once', form)[1]; };

  Validator.prototype.inputs = function (form) {
    var inputs = CNU.dom.get_inputs(form);
    this.check_elements(inputs);

    var selects = CNU.dom.get_selects(form);
    this.check_elements(selects);

    var textareas = CNU.dom.get_textareas(form);
    this.check_elements(textareas);
  };

  Validator.prototype.check_elements = function (elements) {
    var type = null;
    for (var i = 0; i < elements.length; i++) {
      try { type = elements.item(i).getAttribute('type'); }
      catch (err) { type = 'generic'; }
      if ((type != 'hidden') && (type != 'button') && (type != 'image') && (type != 'reset') && (type != 'submit')) { 

          var element = new Validator(elements.item(i));
          if (element.result == true) element.unset_error();
          else element.set_error();
          this.result = this.result && element.result;

      }
    }
  };

  Validator.prototype.enable_form_events = function (form) {
    var inputs = CNU.dom.get_inputs(form);
    this.enable_element_events(inputs);

    var selects = CNU.dom.get_selects(form);
    this.enable_element_events(selects);

    var textareas = CNU.dom.get_textareas(form);
    this.enable_element_events(textareas);
  };

  Validator.prototype.enable_element_events = function (elements) {

    var type = null;
    for (var i = 0; i < elements.length; i++) {
      try { type = elements.item(i).getAttribute('type'); }
      catch (err) { type = 'generic'; }
      if ((type != 'submit') && (type != 'hidden') && (type != 'reset')) {
        CNU.ev.addEvent(elements.item(i), 'blur', function (e) { 
          var validate = new Validator(this);
          validate.unset_focus();
          if (validate.result) validate.unset_error();
          else validate.set_error();

          CNU.Assistant.blurred_input = CNU.ev.getTarget(e);

        });
        CNU.ev.addEvent(elements.item(i), 'focus', function () { 
          CNU.Assistant.blurred_input = false;
          var validate = new Validator(this);
          if (validate.has_error()) validate.unset_error();
          validate.set_focus();
        });
        CNU.ev.addEvent(elements.item(i), 'keydown', function (evt) {
          var keyCode = false;

          if ("which" in evt) {
            keyCode=evt.which;
          } else if ("keyCode" in evt) {
            keyCode=evt.keyCode;
          } else if ("keyCode" in window.event) {
            keyCode=window.event.keyCode;
          } else if ("which" in window.event) {
            keyCode=evt.which;
          } else {
            debug("the browser don't support");  
          }

          if (keyCode == 9) CNU.Assistant.tabbed = true;
          else CNU.Assistant.tabbed = false;
        });
      }

      /* special case: submit_once tags need click invoked after blurs. */
      if ((type == 'submit') || (type == 'reset') || (type == 'button')) {
        //if ($(elements.item(i)).hasClassName('submit_once')) { 
          CNU.ev.addEvent(elements.item(i), 'focus', function (e) {
            if (! CNU.Assistant.tabbed) {
              var target = CNU.ev.getTarget(e);
              if (CNU.Assistant.blurred_input) target.click();
              CNU.Assistant.blurred_input = false;
            }
          });
        //}
      }
    }

  };

  Validator.prototype.has_class = function (class_name) { 
    return this.o.parentNode.hasClassName(class_name);
  };

  Validator.prototype.set_class = function (class_name) {
    $(this.o.parentNode).addClassName(class_name);
    if (class_name == 'error') { 
      $(this.o).addClassName(class_name); 
      if (this.o.nodeName == 'SELECT') { 
        var selects = $(this.o.parentNode).getElementsByTagName('select');
        for (var i = 0; i < selects.length; i++) { $(selects[i]).addClassName(class_name); }
      }
    }
  };

  Validator.prototype.unset_class = function (class_name) {
    $(this.o.parentNode).removeClassName(class_name);
    if (class_name == 'error') { 
      $(this.o).removeClassName(class_name); 
      if ((this.o.nodeName == 'SELECT') || (this.o.hasClassName('hasDatepicker'))) { 
        var selects = $(this.o.parentNode).getElementsByTagName('select');
        for (var i = 0; i < selects.length; i++) { $(selects[i]).removeClassName(class_name); }
      }
    }
  };

  Validator.prototype.has_error_message = function () { return (this.message !== null); };

  Validator.prototype.set_error_message = function () {
    this.msgElement.innerHTML = this.message;
    this.o.parentNode.appendChild(this.msgElement);
  }

  Validator.prototype.has_error_element = function () {
    if (this.o.nodeName == '#document') return false;
    debug(CNU.dom.getElementsByClass('error_message', $(this.o.parentNode)).size());
    debug(CNU.dom.getElementsByClass('error_message', $(this.o.parentNode)).size() == 1);
    return (CNU.dom.getElementsByClass('error_message', $(this.o.parentNode)).size() == 1);
  }

  Validator.prototype.get_error_element = function () {
    var r = false;
    if (this.has_error_element()) {
      r = CNU.dom.getElementsByClass('error_message', $(this.o.parentNode))[0];
      if (! r) r = $('error_message_'+this.id+'___hidden');
    }
    return r;
  }

  Validator.prototype.unset_error_message = function () { 
    var errNode = this.get_error_element();
    try {
      $(this.o.parentNode).removeChild(errNode); 
    } catch (err) {
      try {
        $('error_message_'+this.id).remove()
      } catch (err) {
        // console.log('still no luck.'+ err.message + ':' + err.lineNumber);
      }
    }
  }

  Validator.prototype.set_error = function () {
    if (! this.message) this.message = this.MESSAGES['default'];
    if (! this.msgElement) this.msgElement = this.empty_message_container();
    if (! this.has_class('error')) {
      this.set_class('error');
      this.set_error_message();
    }
  };

  Validator.prototype.unset_error = function () {
    if (this.message != null) this.message = null;
    if (this.has_class('error')) {
      this.unset_class('error');
      this.unset_error_message();
    }
  };

  Validator.prototype.has_error = function () { return this.has_class('error'); };
  Validator.prototype.has_focus = function () { return this.has_class('focus'); };

  Validator.prototype.set_focus = function () {
    if (! this.has_class('focus')) {
      this.set_class('focus');
    }
    this.show_tip();
  };
  Validator.prototype.unset_focus = function () {
    this.unset_class('focus');
    this.hide_tip();
  };

  Validator.prototype.get_tip = function () { 
    return CNU.dom.getElementsByClass('tooltip', $(this.o.parentNode))[0];
  };
  Validator.prototype.show_tip = function () { 
    var tip = this.get_tip(); 
    if (tip) {
      if (this.needs_tip_moved()) this.move_tip(tip);
      tip.style.display = 'block'; 
    }
  };
  Validator.prototype.hide_tip = function () { 
    var tip = this.get_tip(); 
    if (tip) tip.style.display = 'none'; 
  };

  Validator.prototype.needs_tip_moved = function () {
    if (this.o.nodeName == 'SELECT') return true;
    // if (this.o.hasClassName('date')) return true;
    return false;
  };

  Validator.prototype.move_tip = function (tip) { 
    var label = false;
    try { label = $(this.o.parentNode).getElementsByTagName('label')[0]; }
    catch (err) { debug('ERR: parent node issue again, most likely.'); }
    if (label) this.o.parentNode.insertBefore(tip, label);
  };

  

  // public hash
  return {

    // a public method for initializing the Assistant
    init: function () {
      CNU.ev.addLoadEvent(function () {
        if (CNU.config.VALIDATE == true) {
          CNU.dom.extend_string();
          CNU.dom.hideByClass('tooltip', document);
          CNU.Assistant.setup_errors();
          var validations = new Validator(document);
        }
      });
    },

    validate: function (element) {
      var validation = new Validator(element);
      if (validation.result) validation.unset_error();
      else validation.set_error();
      return validation.result;
    },

    enable: function (element) {
      var validation = new Validator(element);  
      validation.enable_form_events(element);
    },

    set_focus: function (element) {
      var validation = new Validator(element);  
      validation.set_focus();
    },

    unset_focus: function (element) {
      var validation = new Validator(element);
      validation.unset_focus();
    },

    setup_errors: function () {
      var errors = CNU.dom.getElementsByClass('error');
      for (var i = 0; i < errors.length; i++) {
        if ((errors[i].nodeName == 'INPUT') ||
            (errors[i].nodeName == 'SELECT') ||
            (errors[i].nodeName == 'TEXTAREA')) {
          if (! $(errors[i].parentNode).hasClassName('error')) {
            $(errors[i].parentNode).addClassName('error');
          }
        }
      }
    },

    blurred_input: false,
    tabbed: null,

    enable_tips: function () {
      CNU.dom.hideByClass('tooltip');
      var tips = CNU.dom.getElementsByClass('tooltip');
      for (var i = 0; i < tips.length; i++) {
        var icon = document.createElement('img');
        icon.setAttribute('src', '../../images/GB/info_icon.gif');
        icon.setAttribute('alt', '');
        CNU.ev.addEvent(icon, 'click', function (e) { 
          var target = CNU.ev.getTarget(e);
          var tts = CNU.dom.getElementsByClass('tooltip', target.parentNode);
          $(tts[0]).toggle();
        });
        $(tips[i]).parentNode.insertBefore(icon, tips[i]);
      }
    }

  } // Assistant return publich hash

}(); // Assistant
CNU.Assistant.init();


// hide all faq's
// add navigation to page
CNU.faq = {}
CNU.faq.init = function () {

  CNU.faq.hide_all();
  CNU.faq.init_nav();

}

// activate behaviors for categories and questions
// add close/open navigation to each question as
// well as the entire page.
CNU.faq.init_nav = function () {

  $$('.faq_category').each(function (c) { CNU.faq.add_events(c); });
  $$('.faq_question').each(function (q) { CNU.faq.add_events(q); });
  $$('.faq_answer').each(function (a) { CNU.faq.add_nav(a); });
  $$('.questions').each(function (ql) { CNU.faq.add_global_nav(ql); });
  
}

// Basic show and hide functionality
CNU.faq.hide = function (e) { new Effect.BlindUp(e, { duration: 0.1, fps: 24 }) };
CNU.faq.show = function (e) { new Effect.BlindDown(e, { duration: 0.1, fps: 24 }) };

// Global show and hide functionality
CNU.faq.hide_all = function () { 
  $$('.faq').each(function (e) { 
    if (e.tagName != 'BODY') { CNU.faq.hide(e); } 
  });
};

CNU.faq.show_all = function () { 
  $$('.faq').each(function (e) { 
    if (e.tagName != 'BODY') { CNU.faq.show(e); } 
  });
};

// adds onclick event to element
// to show next sibling that has className "faq"
CNU.faq.add_events = function (e) { 
  e.onclick = function () { CNU.faq.toggle_sibling(e); };
  e.onmouseover = function () { e.style.cursor = 'pointer'; };
};

// Toggle the appropriate sibling, if it exists.
CNU.faq.toggle_sibling = function (e) {
  var sibling = CNU.faq.get_sibling(e);
  if (sibling != false) CNU.faq.toggle(sibling);
};

// Toggle the given element
CNU.faq.toggle = function (e) { 
  new Effect.toggle(e, 'blind', { duration: 0.1, fps: 24 }) 
};

// returns next closest sibling which has the classname 'faq'
// otherwise returns false
CNU.faq.get_sibling = function (e) {

  var siblings = e.nextSiblings();
  var sibling = false;

  for (var i = 0; i < siblings.length; i++) {
    if ($(siblings[i]).hasClassName('faq')) {
      sibling = siblings[i];
      i = siblings.length;
    }
  }

  return sibling;

}


CNU.faq.add_nav = function (e) { 

  var nav = document.createElement('div');
  var close = document.createElement('a');

  close.setAttribute('href', '#');
  close.onclick = function () { CNU.faq.toggle(e); return false; };
  close.onmouseover = function () { close.style.cursor = 'pointer'; };
  close.appendChild(document.createTextNode('Close'));
  
  $(nav).addClassName('nav');
  $(nav).appendChild(close);
  e.appendChild(nav);

};


CNU.faq.add_global_nav = function (e) { 

  var nav = document.createElement('p');
  var close = document.createElement('a');
  var open = document.createElement('a');

  close.setAttribute('href', '#');
  close.onclick = function () { CNU.faq.hide_all(); return false; };
  close.onmouseover = function () { close.style.cursor = 'pointer'; };
  close.appendChild(document.createTextNode('Collapse All'));

  open.onclick = function () { CNU.faq.show_all(); return false; };
  open.onmouseover = function () { open.style.cursor = 'pointer'; };
  open.appendChild(document.createTextNode('Expand All'));

  $(nav).addClassName('nav');
  nav.appendChild(open);
  nav.appendChild(document.createTextNode(" | "));
  nav.appendChild(close);
  
  e.parentNode.insertBefore(nav, e);

};


CNU.sms = {};

// disable the promotional_sms_flg checkbox 
//   if the account_sms_flg checkbox is not checked
CNU.sms.init = function () {
  CNU.ev.addEvent($('customer___sms_preference___account_sms_flg'), 'click', CNU.sms.toggle_sms_checkbox_conditions);
  CNU.ev.addEvent($('customer___sms_preference___terms_sms_flg'), 'click', CNU.sms.toggle_sms_checkbox_conditions);
  CNU.sms.toggle_sms_checkbox_conditions();
}

// Whenever account_sms_flg is checked
//  - mobile phone should be given a 'required' class
//  - promotional_sms_flg should be enabled
CNU.sms.toggle_sms_checkbox_conditions = function () {
  var terms_sms_flg = $('customer___sms_preference___terms_sms_flg');
  var account_sms_flg = $('customer___sms_preference___account_sms_flg');
  var promotional_sms_flg = $('customer___sms_preference___promotional_sms_flg');
  var mobile_phone = $('customer___person___mobile_phone');
  if (terms_sms_flg.checked) {
    account_sms_flg.enable();
  } else {
    account_sms_flg.checked = false;
    account_sms_flg.disable();
  }
  
  if (account_sms_flg.checked) {
    promotional_sms_flg.enable();

    $(mobile_phone).addClassName('required');
    var requiredNode = document.createElement('span');
    requiredNode.innerHTML = '*';
    $(requiredNode).addClassName('required');
    requiredNode.setAttribute('id', 'mobile_required');
    mobile_label = mobile_phone.parentNode.firstChild;
    mobile_phone.parentNode.insertBefore(requiredNode, mobile_label.nextSibling);

  } else {
    promotional_sms_flg.checked = false;
    promotional_sms_flg.disable();
    $(mobile_phone).removeClassName('required');
    $(mobile_phone).removeClassName('error');

    CNU.Assistant.validate(mobile_phone);
    if($('mobile_required'))
      $('mobile_required').remove(); 
  }
}

