/* GLOBAL CONSTANTS */

  var BASE_URL = '';                // 'http://www.fmailapp.com/apps/gfmail2'
  var RELATIVE_URL = '';            // '/apps/gfmail2'
  var DOUBLEKEY_TIMEOUT = 1500;
  var MAXNUM_SEARCH_RESULTS = 20;
  var SAVED_POPUP_DATA = '';



/* COMMON FUNCTIONS */

var common =
{

/* BINDINGS */

  bindings_and_initial_tasks: function() {
    // Bindings
    bindings.all();
    if (!jQuery('body#application').length) bindings.non_application(); // non-application pages
    if (jQuery('form#login_form').length) bindings.login(); // login
    if (jQuery('div#page_content.products').length) bindings.products(); // products page
    if (jQuery('div#syphir_rules.content').length) bindings.accounts(); // accounts page
    if (jQuery('form#rules_container').length) { // accounts page
      bindings.rules();
      bindings.rules_and_admin_cp();
    }
    if (jQuery('div#page_content.admin').length) { // admin cp
      bindings.admin_cp();
      bindings.rules_and_admin_cp();
    }
    if (jQuery('div#rules_tour').length) bindings.tour(); // guided tour

    // Suggestion Textboxes
    if (jQuery('input[suggestion]').length) common.populate_suggestions();

    // YFT
    jQuery('.yft').each(function() {
      common.flash(jQuery(this));
    });
  },

/* SUGGESTION TEXTBOXES */

  populate_suggestions: function() {
    bindings.suggestions();
    jQuery('input[suggestion]').each(function() {
      if ((jQuery(this).val().length == 0) || (jQuery(this).val() == jQuery(this).attr('suggestion'))) {
        //jQuery(this).val(jQuery(this).attr('suggestion')).css({'color':'#AAAAAA', 'font-style':'italic', 'font-size':'12px'});
        jQuery(this).val(jQuery(this).attr('suggestion')).css({'color':'#AAAAAA', 'font-style':'italic'});
      } else if (jQuery(this).val() != jQuery(this).attr('suggestion')) {
        jQuery(this).css({'color':'', 'font-style':'', 'font-size':''});
      }
    });
  },

/* CHECKBOXES */

  trim: function(subject) {
    if (!subject) return "";
    return subject.replace(new RegExp("^[\\s]+", "g"), "").replace(new RegExp("[\\s]+$", "g"), "");
  },

/* SYPHIR RULES TOUR */

  change_pane: function(new_pane) {
    jQuery('div#pane1').stop();
    jQuery('div#pane2').stop();
    jQuery('div#pane3').stop();
    jQuery('img#pane_selector_image').stop();
    var status1 = (parseInt(jQuery('div#pane1').css('marginLeft')) < 0) ? 'hidden' : 'visible';
    var status2 = (parseInt(jQuery('div#pane2').css('marginLeft')) < 0) ? 'hidden' : 'visible';
    var status3 = (parseInt(jQuery('div#pane3').css('marginLeft')) < 0) ? 'hidden' : 'visible';
    var time_1 = 667;
    var time_2 = 1200;
    if (new_pane == 1) {
      jQuery('div#pane3').animate({marginLeft:'0px'}, (status3=='hidden' ? time_1 : 0), 'linear', function() {
        jQuery('div#pane2').animate({marginLeft:'0px'}, (status2=='hidden' ? time_1 : 0), 'linear', function() {
          jQuery('div#pane1').animate({marginLeft:'0px'}, time_1, 'linear');
        });
      });
      jQuery('img#pane_selector_image').animate({marginLeft:'56px'}, time_2, 'swing');
    } else if (new_pane == 2) {
      if (status2 == 'hidden') { // this pane is hidden, we're moving backwards to get to it
        jQuery('div#pane3').animate({marginLeft:'0px'}, (status3=='hidden' ? time_1 : 0), 'linear', function() {
          jQuery('div#pane2').animate({marginLeft:'0px'}, time_1, 'linear');
        });
      } else {
        jQuery('div#pane1').animate({marginLeft:'-700px'}, (status1=='hidden' ? 0 : time_1), 'linear');
      }
      jQuery('img#pane_selector_image').animate({marginLeft:'208px'}, time_2, 'swing');
    } else if (new_pane == 3) {
      if (status3 == 'hidden') { // this pane is hidden, we're moving backwards to get to it
        jQuery('div#pane3').animate({marginLeft:'0px'}, time_1);
      } else {
        jQuery('div#pane1').animate({marginLeft:'-700px'}, (status1=='hidden' ? 0 : time_1), 'linear', function() {
          jQuery('div#pane2').animate({marginLeft:'-700px'}, (status2=='hidden' ? 0 : time_1), 'linear');
        });
      }
      jQuery('img#pane_selector_image').animate({marginLeft:'357px'}, time_2, 'swing');
    } else if (new_pane == 4) {
      jQuery('div#pane1').animate({marginLeft:'-700px'}, (status1=='hidden' ? 0 : time_1), 'linear', function() {
        jQuery('div#pane2').animate({marginLeft:'-700px'}, (status2=='hidden' ? 0 : time_1), 'linear', function() {
          jQuery('div#pane3').animate({marginLeft:'-700px'}, (status3=='hidden' ? 0 : time_1), 'linear');
        });
      });
      jQuery('img#pane_selector_image').animate({marginLeft:'507px'}, time_2, 'swing');
    }
  },

  make_scrollable: function(this_wrapper, this_scrollable) {
    // height of area at the top at bottom, that don't respond to mousemove
    var inactiveMargin = 30;
    // Cache for performance
    var wrapperWidth = this_wrapper.width();
    var wrapperHeight = this_wrapper.height();
    // Using outer height to include padding too
    var scrollableHeight = this_scrollable.outerHeight() + 2*inactiveMargin;
    // Do not cache wrapperOffset, because it can change when user resizes window
    // We could use onresize event, but it's just not worth doing that
    // var wrapperOffset = this_wrapper.offset();
    //When user move mouse over menu
    this_wrapper.unbind('mousemove');
    this_wrapper.bind('mousemove', function(e){
      var wrapperOffset = this_wrapper.offset();
      // Scroll menu
      var top = (e.pageY -  wrapperOffset.top) * (scrollableHeight - wrapperHeight) / wrapperHeight  - inactiveMargin;
      if (top < 0) top = 0;
      this_wrapper.scrollTop(top);
    });
  },

  update_rules_area: function(key, path) {
    if (path == 'indirect deselect') jQuery('div.selected_step div.rules_list a[key='+key+']').removeClass('selected');
    // Toggle display of basic instructions.
    if (jQuery('div.selected_step div.rules_list a.selected').length) {
      jQuery('div.selected_step p.nothing_selected').hide();
      jQuery('div.selected_step p.something_selected').show();
    } else {
      jQuery('div.selected_step p.something_selected').hide();
      jQuery('div.selected_step p.nothing_selected').show();
    }
    // Show popup with form options.
    var option = jQuery('div.selected_step div.rules_list a[key='+key+']');
    var popup = jQuery('div.selected_step div.popup');
    if (path == 'edit') {
      // CLICKING THE HIGHLIGHT (on an existing rule)
      common.show_popup(key);
    } else {
      // CLICKING THE OPTION (in the list)
      if (option.hasClass('selected') && path == 'select') {
        // Open the popup.
        common.show_popup(key);
      } else {
        // Close the popup if it's open.
        if (popup.attr('key') == key) {
          common.close_popup(key);
        }
        // "Unchoose" the corresponding fieldset.
        jQuery('div.selected_step fieldset#'+key).removeClass('chosen');
      }
    }
    // Modify the "selected list".
    common.modify_selected_list(key);
  },

  modify_selected_list: function(key) {
    var option = jQuery('div.selected_step div.rules_list a[key='+key+']');
    if ((key != 'coverage') && !option.hasClass('selected')) {
      jQuery('div.selected_step ul.selected li[key='+key+']').remove();
    } else {
      switch(key) {

        // CONDITIONS

        case 'coverage':
          var label_val = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[coverage_1\\]]').val();
          var label_name = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[coverage_1\\]] option[value="'+label_val+'"]').text();
          var prefix = ((label_val == 'INBOX') || (label_val == '[Gmail]/Trash')) ? 'the ' : '';
          var content = 'Your rule will target emails in ' + prefix + '<span id="coverage_highlight" class="rounded_corners highlight">' + label_name + '</span> matching the following condition(s):';
          break;
        case 'from':
          var terms = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[from\\]]').val();
          var arr_terms = common.split_search_terms(terms);
          for (var i=0; i<arr_terms.length; i++) {
            arr_terms[i] = '<b>' + arr_terms[i] + '</b>';
          }
          terms = common.to_sentence(arr_terms);
          var content = 'from field contains <span class="rounded_corners highlight">' + terms + '</span>';
          break;
        case 'to':
          var terms = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[to\\]]').val();
          var arr_terms = common.split_search_terms(terms);
          for (var i=0; i<arr_terms.length; i++) {
            arr_terms[i] = '<b>' + arr_terms[i] + '</b>';
          }
          terms = common.to_sentence(arr_terms);
          var content = 'to, cc, or bcc fields contain <span class="rounded_corners highlight">' + terms + '</span>';
          break;
        case 'subject':
          var terms = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[subject\\]]').val();
          var arr_terms = common.split_search_terms(terms);
          for (var i=0; i<arr_terms.length; i++) {
            arr_terms[i] = '<b>' + arr_terms[i] + '</b>';
          }
          terms = common.to_sentence(arr_terms);
          var content = 'subject contains <span class="rounded_corners highlight">' + terms + '</span>';
          break;
        case 'body':
          var terms = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[body\\]]').val();
          var arr_terms = common.split_search_terms(terms);
          for (var i=0; i<arr_terms.length; i++) {
            arr_terms[i] = '<b>' + arr_terms[i] + '</b>';
          }
          terms = common.to_sentence(arr_terms);
          var content = 'body contains <span class="rounded_corners highlight">' + terms + '</span>';
          break;
        case 'attachments':
          var comparison = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[attachments_1\\]]').val();
          var num_attachments = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[attachments_2\\]]').val();
          var display_num = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[attachments_2\\]] option[value="'+num_attachments+'"]').text();
          var terms = comparison + ' ' + display_num;
          var content = 'there are <span class="rounded_corners highlight"><b>' + terms + '</b></span>';
          break;
        case 'arrival':
          var time1 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[arrival_1\\]]').val();
          var term_1 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[arrival_1\\]] option[value="'+time1+'"]').text();
          var time2 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[arrival_2\\]]').val();
          var term_2 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[arrival_2\\]] option[value="'+time2+'"]').text();
          var terms = term_1 + ' and ' + term_2;
          var content = 'arrives between <span class="rounded_corners highlight"><b>' + terms + '</b></span>';
          break;
        case 'stagnant':
          var number = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[stagnant_1\\]]').val();
          var scale = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[stagnant_2\\]]').val();
          var terms = number + ' ' + scale;
          var content = 'at least <span class="rounded_corners highlight"><b>' + terms + '</b></span>';
          break;
        case 'recipients':
          var term_1 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[recipients_1\\]]').val();
          var term_2 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[recipients_2\\]]').val();
          var term_3 = (parseInt(term_2) == 1) ? 'recipient' : 'recipients';
          var term_0 = (parseInt(term_2) == 1) ? 'is' : 'are';
          var terms = '<b>' + term_1 + ' ' + term_2 + ' ' + term_3 + '</b>';
          var content = 'there ' + term_0 + ' <span class="rounded_corners highlight">' + terms + '</span>';
          break;
        case 'reply':
          var arr_terms = []
          if (jQuery('input[name=rule\\[conditions\\]\\[reply_1\\]]:checked').length) arr_terms.push('<b>needs a reply</b>');
          if (jQuery('input[name=rule\\[conditions\\]\\[reply_2\\]]:checked').length) arr_terms.push('<b>might need a reply</b>');
          if (jQuery('input[name=rule\\[conditions\\]\\[reply_3\\]]:checked').length) arr_terms.push('<b>doesn\'t need a reply</b>');
          var terms = common.to_sentence(arr_terms, 'or');
          var content = 'any email that <span class="rounded_corners highlight">' + terms + '</span>';
          break;

        // ACTIONS

        case 'archive':
          var content = 'they will be <span class="rounded_corners highlight inactive"><b>archived</b></span>';
          break;
        case 'read':
          var content = 'they will be <span class="rounded_corners highlight inactive"><b>marked as read</b></span>';
          break;
        case 'star':
          var content = 'they will be <span class="rounded_corners highlight inactive"><b>starred</b></span>';
          break;
        case 'delete':
          var content = 'they will be <span class="rounded_corners highlight inactive"><b>deleted</b></span>';
          break;
        case 'label':
          var new_or_existing = jQuery('div.selected_step input[name=rule\\[actions\\]\\[label_1\\]]:checked').val();
          var existing_name_val = jQuery('div.selected_step select[name=rule\\[actions\\]\\[label_2\\]]').val();
          var existing_name = jQuery('div.selected_step select[name=rule\\[actions\\]\\[label_2\\]] option[value="'+existing_name_val+'"]').text();
          var new_name = jQuery('div.selected_step input[name=rule\\[actions\\]\\[label_3\\]]').val();
          var terms = (new_or_existing.toLowerCase() == 'existing') ? existing_name : new_name;
          var content = 'the ' + new_or_existing + ' label <span class="rounded_corners highlight"><b>' + terms + '</b></span> will be applied';
          break;
        case 'mobile':
          var terms = 'iPhone via Syphir SmartPush';
          var content = 'a notification will be sent to your <span class="rounded_corners highlight"><b>' + terms + '</b></span>';
          break;
        case 'delay':
          var term_1 = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_1\\]]').val();
          if (term_1 == 'until') {
            var time = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_2\\]]').val();
            var term_2 = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_2\\]] option[value="'+time+'"]').text();
          } else if (term_1 == 'for') {
            var time = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_3\\]]').val();
            var term_2 = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_3\\]] option[value="'+time+'"]').text();
          }
          var terms = term_1 + ' ' + term_2;
          var content = 'they won\'t appear in your inbox <span class="rounded_corners highlight"><b>' + terms + '</b></span>';
          break;
      }
      if (content) {
        if (key == 'coverage') {
          jQuery('div.selected_step p.something_selected').html(content);
        } else {
          if (jQuery('div.selected_step ul.selected li[key='+key+']').length) {
            jQuery('div.selected_step ul.selected li[key='+key+']').html(content);
          } else {
            jQuery('div.selected_step ul.selected').append('<li key="'+key+'">'+content+'</li>');
          }
        }
      }
    }
  },

  test_search: function() {
    var conditions = '?';
    jQuery('div#step1 fieldset.chosen').each(function() {
      var key = jQuery(this).attr('id');
      switch(key) {
        case 'from':
        case 'to':
        case 'subject':
        case 'body':
          conditions += 'rule[conditions]['+key+']='+common.capture_condition_values(key)+'&';
          break;
        case 'attachments':
          conditions += 'rule[conditions][attachments_1]='+common.capture_condition_values('attachments_1')+'&';
          conditions += 'rule[conditions][attachments_2]='+common.capture_condition_values('attachments_2')+'&';
          break;
        case 'arrival':
          conditions += 'rule[conditions][arrival_1]='+common.capture_condition_values('arrival_1')+'&';
          conditions += 'rule[conditions][arrival_2]='+common.capture_condition_values('arrival_2')+'&';
          break;
        case 'recipients':
          conditions += 'rule[conditions][recipients_1]='+common.capture_condition_values('recipients_1')+'&';
          conditions += 'rule[conditions][recipients_2]='+common.capture_condition_values('recipients_2')+'&';
          break;
        case 'reply':
          var reply_1 = common.capture_condition_values('reply_1');
          var reply_2 = common.capture_condition_values('reply_2');
          var reply_3 = common.capture_condition_values('reply_3');
          if (reply_1) conditions += 'rule[conditions][reply_1]='+reply_1+'&';
          if (reply_2) conditions += 'rule[conditions][reply_2]='+reply_2+'&';
          if (reply_3) conditions += 'rule[conditions][reply_3]='+reply_3+'&';
          break;
        case 'stagnant':
          conditions += 'rule[conditions][stagnant_1]='+common.capture_condition_values('stagnant_1')+'&';
          conditions += 'rule[conditions][stagnant_2]='+common.capture_condition_values('stagnant_2')+'&';
          break;
      }
    });
    if (conditions.charAt(conditions.length-1) == '&') {
      conditions = conditions.substring(0, conditions.length-1);
    }
    return conditions;
  },

  capture_condition_values: function(key) {
    switch(key) {
      case 'coverage':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[coverage_1\\]]').val();
        break;
      case 'from':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[from\\]]').val();
        break;
      case 'to':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[to\\]]').val();
        break;
      case 'subject':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[subject\\]]').val();
        break;
      case 'body':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[body\\]]').val();
        break;
      case 'attachments_1':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[attachments_1\\]]').val();
        break;
      case 'attachments_2':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[attachments_2\\]]').val();
        break;
      case 'arrival_1':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[arrival_1\\]]').val();
        break;
      case 'arrival_2':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[arrival_2\\]]').val();
        break;
      case 'recipients_1':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[recipients_1\\]]').val();
        break;
      case 'recipients_2':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[recipients_2\\]]').val();
        break;
      case 'stagnant_1':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[stagnant_1\\]]').val();
        break;
      case 'stagnant_2':
        return jQuery('div#step1 select[name=rule\\[conditions\\]\\[stagnant_2\\]]').val();
        break;
      case 'reply_1':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[reply_1\\]]:checked').val();
      case 'reply_2':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[reply_2\\]]:checked').val();
      case 'reply_3':
        return jQuery('div#step1 input[name=rule\\[conditions\\]\\[reply_3\\]]:checked').val();
        break;
    }
  },

  show_popup: function(key) {
    // Hide any errors.
    jQuery('div.selected_step p.popup_err').text('');
    // Ensure that previous popup exited gracefully.
    var fieldset = jQuery('div.selected_step fieldset#'+key);
    var old_key = jQuery('div.selected_step div.popup').attr('key');
    if (old_key && !fieldset.hasClass('chosen') && (fieldset.attr('id') != 'coverage')) {
      jQuery('div.selected_step div.rules_list a[key='+old_key+']').removeClass('selected');
      common.modify_selected_list(old_key);
    }
    // Hide all fieldsets.
    jQuery('div.selected_step fieldset').hide();
    // If necessary, show the popup with appropriate text. Otherwise, just add option directly.
    var option_link = jQuery('div.rules_list a[key='+key+']');
    if (option_link.hasClass('nopopup')) {
      common.close_popup(key, true);
    } else {
      var popup = jQuery('div.selected_step div.popup');
      popup.stop().css({opacity:'1'}).show().attr('key',key);
      popup.find('h3').text(fieldset.attr('header'));
      popup.find('p.subheader').text(fieldset.attr('subheader'));
      if (fieldset.attr('unavailable')) {
        popup.find('.popup_save').hide();
        popup.find('.popup_remove').hide();
      } else {
        popup.find('.popup_save').show();
        popup.find('.popup_remove').show();
      }
      // Show the appropriate fieldset.
      fieldset.fadeIn();
    }
    // Store this fieldset's form data.
    SAVED_POPUP_DATA = fieldset.find('[name*=rule\\[conditions\\]\\['+key+']').serializeArray();
  },


  // i'm in the middle of JS validation of rules wizard popups.
  // there is a weird bug happening in FF that crashes the browser when I open a popup then click "cancel".
  // in the function below, everything documented below "Close the popup" used to be at the very beginning of the func.

  close_popup: function(key, save_changes) {
    key = (!key) ? jQuery('div.selected_step div.popup').attr('key') : key;
    var fieldset = jQuery('div.selected_step fieldset#'+key);
    // Make changes based on whether or not we're saving the data.
    if (!save_changes) {
      // Close the popup.
      jQuery('div.selected_step div.popup').fadeOut('normal').attr('key','');
      // Hide the specified fieldset.
      fieldset.hide();
      // We're not saving things, so revert any changes to the data.
      for (var i=0; i<SAVED_POPUP_DATA.length; i++) {
        var name = SAVED_POPUP_DATA[i].name.replace(/\[/g,'\\[').replace(/\]/g,'\\]');
        fieldset.find('[name='+name+']').val(SAVED_POPUP_DATA[i].value);
      }
      common.populate_suggestions();
      if (!fieldset.hasClass('chosen') && (fieldset.attr('id') != 'coverage')) common.update_rules_area(key, 'indirect deselect');
      return true;
    } else if (common.validate_popup(key)) {
      if (fieldset.attr('id') != 'coverage') fieldset.addClass('chosen');
      // Clear the saved data.
      SAVED_POPUP_DATA = '';
      // Close the popup.
      jQuery('div.selected_step div.popup').fadeOut('normal').attr('key','');
      // Hide the specified fieldset.
      fieldset.hide();
      return true;
    } else {
      return false;
    }
  },

  validate_popup: function(key) {
    switch(key) {
      case 'from':
      case 'to':
      case 'subject':
      case 'body':
        var input = jQuery('div.selected_step input[name=rule\\[conditions\\]\\['+key+'\\]]');
        if (!input.val() || !common.trim(input.val()) || (common.trim(input.val()) == input.attr('suggestion'))) {
          jQuery('div.selected_step p.popup_err').text('Please fill out the textbox above.');
          return false;
        }
        break;
      case 'attachments':
      case 'recipients':
        var val_1 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\['+key+'_1\\]]').val();
        var val_2 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\['+key+'_2\\]]').val();
        if (!val_1 || !common.trim(val_1) || !val_2 || !common.trim(val_2)) {
          jQuery('div.selected_step p.popup_err').text('Please make selections from the dropdown menus above.');
          return false;
        }
        break;
      case 'arrival':
        var time_1 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[arrival_1\\]]').val();
        var time_2 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[arrival_2\\]]').val();
        if (!time_1 || !common.trim(time_1) || !time_2 || !common.trim(time_2)) {
          jQuery('div.selected_step p.popup_err').text('Please select times from the dropdown menus above.');
          return false;
        } else if (time_1 == time_2) {
          jQuery('div.selected_step p.popup_err').text('Please choose different times.');
          return false;
        }
        break;
      case 'reply':
        var reply_1 = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[reply_1\\]]:checked').val();
        var reply_2 = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[reply_2\\]]:checked').val();
        var reply_3 = jQuery('div.selected_step input[name=rule\\[conditions\\]\\[reply_3\\]]:checked').val();
        if (!reply_1 && !reply_2 && !reply_3) {
          jQuery('div.selected_step p.popup_err').text('Please check at least one box.');
          return false;
        }
        break;
      case 'coverage':
        var coverage_1 = jQuery('div.selected_step select[name=rule\\[conditions\\]\\[coverage_1\\]]').val();
        if (!coverage_1 || !common.trim(coverage_1)) {
          jQuery('div.selected_step p.popup_err').text('Please select a folder or label.');
          return false;
        }
        break;
      case 'label':
        var label_1 = jQuery('div.selected_step input[name=rule\\[actions\\]\\[label_1\\]]:checked').val();
        if (label_1 == 'existing') {
          if (!jQuery('div.selected_step select[name=rule\\[actions\\]\\[label_2\\]]').val()) {
            jQuery('div.selected_step p.popup_err').text('Please choose an existing label.');
            return false;
          }
        } else {
          var label_3 = jQuery('div.selected_step input[name=rule\\[actions\\]\\[label_3\\]]');
          if (!label_3.val() || !common.trim(label_3.val()) || (label_3.val() == label_3.attr('suggestion'))) {
            jQuery('div.selected_step p.popup_err').text('Please enter a new label name.');
            return false;
          }
        }
        break;
      case 'mobile':
        var mobile_val = jQuery('div.selected_step select[name=rule\\[actions\\]\\[mobile\\]]').val();
        if (!mobile_val || !common.trim(mobile_val)) {
          jQuery('div.selected_step p.popup_err').text('Please make selections from the dropdown menu.');
          return false;
        }
        break;
      case 'delay':
        var delay_1 = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_1\\]]').val();
        var delay_2 = jQuery('div.selected_step select[name=rule\\[actions\\]\\[delay_2\\]]').val();
        if (!delay_1 || !common.trim(delay_1) || !delay_2 || !common.trim(delay_2)) {
          jQuery('div.selected_step p.popup_err').text('Please make selections from the dropdown menus above.');
          return false;
        }
        break;
    }
    return true;
  },

  to_sentence: function(arr, word) {
    if (!word) {
      word = 'AND';
    }
    if (arr.length <= 1) {
      return arr.toString();
    } else if (arr.length == 2) {
      return arr[0] + ' ' + word + ' ' + arr[1];
    } else {
      for (var i=0; i<arr.length; i++) {
        if (i < arr.length-2) {
          arr[i] = arr[i] + ', ';
        } else if (i == arr.length-2) {
          arr[i] = arr[i] + ', ' + word + ' ';
        }
      }
      return arr.join('');
    }
  },

  /*
   *  Given a string with search terms separated by spaces or commas, break it into an array of terms. 
   *  Make sure this method stays up-to-date with Common.rb's version.
   */
  split_search_terms: function(search_terms) {
    // Ensure terms were provided in the right format.
    if (!search_terms || search_terms.length==0) return [];
    // Break terms apart by commas or spaces.
    var temp_array_terms = (search_terms.search(",") != -1) ? search_terms.split(',') : search_terms.split(' ');
    // Remove extra spacing.
    var final_array_terms = [];
    for (var i=0; i<temp_array_terms.length; i++) {
      var temp_term = temp_array_terms[i];
      if (temp_term && common.trim(temp_term).length > 0) {
        final_array_terms.push(common.trim(temp_term));
      }
    }
    // Return the broken-apart terms.
    return final_array_terms;
  },

  flash: function(obj, color, delay) {
    if (!color) color = '#FFFD6C';
    if (!delay) delay = 1200;
    obj.stop().css({background:'none',backgroundColor:color});
    setTimeout(function() {
      obj.animate({backgroundColor:'#FFFFFF'},1600,'swing');
    }, delay);
    /*
    if (!color) color = '#FFFD6C';
    var og_color = obj.css('backgroundColor');
    var og_image = obj.css('backgroundImage');
    var og_repeat = obj.css('backgroundRepeat');
    obj.stop().css({background:'none',backgroundColor:color}).animate({backgroundColor:'#FFFFFF'},1600,'swing', function() {
      jQuery(this).css({backgroundColor:og_color, backgroundImage:og_image, backgroundRepeat:og_repeat});
    });
    */
  }
};