// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults

jQuery.browser.msie7 = /msie 7\./.test(navigator.userAgent.toLowerCase());

function controllerUrl(action){
  var meta = jQuery('meta[name=controller_url]');
  if(meta.size() == 0) return action;
  return meta[0].content + action;
}

String.prototype.controllerUrl = function(){
  return controllerUrl(this);
};

// This table-striping function is only run after you change a table via Ajax.
// We run ApplicationController#raprocess (Hpricot) for inital class striping.
jQuery.fn.stripeTable = function() {
  jQuery("> tbody", this).each(function() { jQuery("> tr:not(.no_stripe):visible:odd", this).addClass("odd"); })
    .each(function() { jQuery("> tr:not(.no_stripe):visible:even", this).removeClass("odd"); });
    
  jQuery("> tbody > tr.no_stripe:visible", this).each(function() {
    jQuery(this).removeClass("odd");
    if(jQuery(this).prevAll('tr:not(.no_stripe):first').hasClass('odd'))
      jQuery(this).addClass("odd")
  });
};

var ajaxStart = function() { jQuery.event.trigger( "ajaxStart" ); };
var ajaxStop = function() { jQuery.event.trigger( "ajaxStop" ); };

jQuery.fn.selectOption = function() {
  return this.jsAttr("selected", true);
};

jQuery.fn.unselectOption = function() {
  return this.jsAttr("selected", false);
};

jQuery.fn.toggleOption = function() {
  return this.each(function() { this.selected = !this.selected; });
};

jQuery.fn.moveToSelect = function(el) {
  this.unselectOption().appendTo(jQuery(el));

  if(jQuery("div.select_mover input[name=" + el.id + "].sort_text:checked").length == 1) {
    jQuery(el).sortSelectBy("html");
  } else if(jQuery("div.select_mover input[name=" + el.id + "].sort_parens:checked").length == 1) {
    jQuery(el).sortSelectBy("sortCompany");
  }

  return this;
};

jQuery.fn.jsAttr = function(attr, value) {
  var toR = {};
  if(attr.constructor == String) {
    if(value || value === false) {
      return this.each(function() { this[attr] = value; });
    } else {
      return jQuery.map(this, function(el) { return el[attr]; });
    }
  } else if(attr.constructor == Object) {
    for(a in attr) { toR[a] = this.jsAttr(attr[a]); }
    return toR;
  }
};

jQuery.fn.getCompany = function() {
  company = this[0].innerHTML.match(/\(([^\)]*)\)/);
  if(company) { return company[1]; }
};

jQuery.fn.sortArrayBy = function(sort, parent) {
  if(!parent)
    parent = jQuery(this).parent();
  
  var mapFunc = null;
  if(sort.constructor == String){
    mapFunc = jQuery.fn[sort];
  } else if(sort.constructor == Function){
    mapFunc = sort;
  }
  
  sorted = jQuery(this).get().sort(function(a,b) { 
    return mapFunc.apply([a]) > mapFunc.apply([b]) ? 1 : -1; 
  });
  jQuery(sorted).remove();
  parent.append(sorted);
  
  return this;
};

jQuery.fn.sortSelectBy = function(sort){
  return jQuery(this).find('option').sortArrayBy(sort).css("width", "100%").css("width", "43%");
};

jQuery.fn.sortCompany = function() {
  return jQuery.fn.getCompany.apply(this) + this[0].innerHTML;
};

jQuery.fn.sortLastName = function() {
  return jQuery(this).html().gsub(/\(.*\)/, '').match(/(\w*\W)*(\w+)/).slice(-1);
};

jQuery.fn.sortLastNameInList = function() {
  return jQuery(this).html().gsub(/\(.*\)/, '').match(/(\w*\W)*(\w+)/).slice(0,1);
};

jQuery(function($) {
  $("a.toggle").click(function() {
    $(this.rel).toggle();
    return false;
  });
});

genericBindings = function(context) {
  jQuery("form.edit input[type=checkbox]", context).change(toggleCheckStuff).click(toggleCheckStuff).each(toggleCheckStuff);
  jQuery("form.edit span.show_with_select", context).siblings("select").each(toggleSelectStuff).change(toggleSelectStuff);
  jQuery("div.select_mover", context).selectMover();
  jQuery("div.select_mover input.sort_text", context).click(function() { 
    var selectBox = jQuery("#" + this.name);
    if(jQuery("option", selectBox).length > 0) jQuery("#" + this.name).sortSelectBy("sortLastName"); 
  }).each(function() { this.click(); });
  jQuery("div.select_mover input.sort_parens", context).click(function() { 
    var selectBox = jQuery("#" + this.name);
    if(jQuery("option", selectBox).length > 0) jQuery("#" + this.name).sortSelectBy("sortCompany"); 
  });

  // the following selectors act differently across the different jQuery versions, so we need to support both ways
  jQuery("form.edit:has(div.select_mover) button[type=submit], form.edit:has(div.select_mover) input[type=submit], " +
        "form.edit[div.select_mover] button[type=submit], form.edit[div.select_mover] input[type=submit]", context)
    .click(function() {
      jQuery("select[multiple].second option", this.form).selectOption();
    });
};

startupDoc = function(context) {
  jQuery("div.date_picker").appendTo("body");
  context = context || document;
  genericBindings(context);

  // Disable submit buttons when submitting a form to prevent duplicate submission
  jQuery("form", context).submit(function() {
    jQuery("button[type=submit], input[type=submit]").each(function() { this.className='clicked'; });
  });

  /* jQuery("div.date_nav a", context).tooltip({showURL: false}); */

  if(!jQuery.browser.msie) { jQuery("form.edit label span :input, form.edit label small :input", context).click(blockAction); }

  jQuery("form.edit span.inline_documentation", context).prev(":input").focus(function() {
    var offset = jQuery(this).offset();
    theOff = offset;
    obj = this;
    jQuery(this).next("span.inline_documentation")
      .appendTo("body")
      .css({top: offset.top - offset.height - 35 + "px", left: offset.left - 110 + "px" })
      .fadeIn("fast");
  });

  jQuery("form.edit :input:not([type=hidden])", context).blur(function() {
    var self = this;
    var doc = jQuery("body > span.inline_documentation").fadeOut("fast", function() { jQuery(self).after(doc); });
  });

  /* Advanced filter binding. Depends on format of _advanced_filter.rhtml, and a 
   * filter specification in some javascript that gets included.
   * jQuery.procore_filters = {rfis_filter:{
   *   location: 5 // The name 'location' in the filters, 6th column in the table
   * }}
   */
  jQuery("div.advanced_filters label select", context).change(function(event) {
    var el = event.target;
    var container = jQuery(el).ancestors('.advanced_filters');
    var filterName = container.id();
    var tableName = filterName.split("_").slice(0,-1).join("_");
    var filters = jQuery("label select", container[0]);
    jQuery("#" + tableName + " > tbody > tr").show();
    
    filters.each(function() {
      var filter = jQuery.procore_filters[filterName][this.id.gsub(tableName + "_", "")];
      var filterVal = jQuery(this).val().replace(/\s+\([^\)]*\)/, "");
      if(filterVal != '') {
        var selector;
        var not_selector;
        if(filter.constructor == Array){
          selector = "#" + tableName + " tbody tr:has(table)";
          not_selector = ":has(table td.meta_col:contains(" + filterVal + "))";
        } else {
          //selector = "#" + tableName + " tbody tr:has(td:nth-child(" + (filter) + "))";
          selector = "#" + tableName + " tbody tr:has(td)";
          not_selector = ":has(.meta_col:contains(" + filterVal + "))";
        }
        jQuery(selector).not(not_selector).hide();
      }
    });
    jQuery("#" + tableName).stripeTable();
  });
  
  jQuery("div.advanced_filters a.clear_filters").click(function() {
    var filters = jQuery("label select", this.parentNode);
    var tableName = this.parentNode.id.split("_").slice(0,-1).join("_");
    filters.each(function() {
      jQuery("option:selected", this)[0].selected = false;
      jQuery("#" + tableName + " tbody tr").show();
      jQuery("#" + tableName).stripeTable();
    });     
  });

  jQuery("p.filters button.filter_change", context).click(function() {
    jQuery(this).parent().css("display", "none").next().css("display", "block");
        return false;
  });

  jQuery("div.filters button.filter_change", context).click(function() {
    jQuery(this).parent().css("display", "none").prev().css("display", "block");
        return false;
  });
  
  jQuery("a.additional_features").click(function() {
    if(jQuery(this).html() == "(+) Additional Features")
      jQuery(this).html("(-) Additional Features");
    else
      jQuery(this).html("(+) Additional Features");
    
    jQuery("div.motd div.hidden").slideToggle("slow");
    return false;
  });

  var turnOnDatePicker = function(jQueryEl) {
    var parent = jQueryEl.parent();
    var future = parent.is(".future_only");
    DatePicker.toggleDatePicker(parent.find("input.date_picker_input").id(), jQueryEl[0], {future_only: future});
  };

  jQuery.fn.applyDatePicker = function() {
    return this.click(function(){
      var jThis = jQuery(this);
      if(jThis.is(".input_field")) {
        turnOnDatePicker(jThis.parent().find("a.demo_link.with_img"));
      } else if(jThis.is(".with_img")) {
        turnOnDatePicker(jThis);
      }
      return false;
    });
  };

  jQuery("span.date_picker_tag").unbind().click(function(evt) {
    if(jQuery(evt.target).is("button")) { evt.stopPropagation(); jQuery(evt.target).parents('form').submit(); return false; }
    turnOnDatePicker(jQuery("a.demo_link.with_img", this));
    return false;
  });

  jQuery("form a.reset").click(function() { this.form.reset(); return false; });

  if(jQuery.fn.tooltip){
    jQuery("span.tip, a.tip").tooltip({ showURL: false });
  }

};

jQuery.fn.selectMover = function() {
  return this.each(function(i, self) {
    jQuery("select:last", this).parent().find("p[button]").remove();
    jQuery("select:last", this).after('<p class="top"><button type="button" class="ltr selected">' +
                        '&gt;</button><button type="button" class="ltr all">&gt;&gt;' +
                        '</button></p><p><button type="button" class="rtl selected">&lt;' +
                        '</button><button class="rtl all">&lt;&lt;</button></p>');
    var moveTo = function(self, side, selected) {
      var width = jQuery("div.select_mover select.first").width();
      // XXX: jQuery 1.2 reports 4px off for width in IE7.
      if(/^1\.2/.test(jQuery.fn.jquery) && jQuery.browser.msie7){
        width += 4;
      }
      jQuery("select:" + side + " option" + (selected ? ":selected" : ""), self)
      .moveToSelect(jQuery("select:" + ((side == "first") ? "last" : "first"), self)[0]);
      jQuery("div.select_mover select").width(width);
    };

    jQuery("p button.ltr.selected", self).click(function() { moveTo(self, "last", true); return false; });
    jQuery("p button.ltr.all", self).click(function() { moveTo(self, "last", false); return false; });
    jQuery("p button.rtl.selected", self).click(function() { moveTo(self, "first", true); return false; });
    jQuery("p button.rtl.all", self).click(function() { moveTo(self, "first", false); return false; });

  });

};


/**
 * Check and selectbox tricks for hiding and showing related boxes
 * To make this work, checkboxes:
 *  * should have a sibling with a child span of class 'show_with_check'
 * Selectboxes:
 *  * should have a sibling input box with class 'inline_box'
 */

blockAction = function() { return false; };

toggleCheckStuff = function() {
  jQuery(this).siblings().find("span.show_with_check").css("display", this.checked ? "inline" : "none");
};

toggleSelectStuff = function() {
  jQuery(this).css("marginRight", "0");
  box = jQuery(this).next("span.show_with_select").css("marginRight", "0");
  box.css("display", (this.value == 1) ? "inline" : "none").find("input").val(this.value == 1 ? box[0].value : "");
};

// jQuery(document).bind("sortStart", ajaxStart)
//         .bind("sortStop", ajaxStop);


jQuery.unescape_html = function(string) {
  var div = document.createElement('div');
  div.innerHTML = string.stripTags();
  return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
};

var restoreButtons = function() {
  jQuery("button").each(function() { this.disabled = false; });
};

jQuery(function($){
  jQuery.fn.disable = function() {
    return this.each(function() { if(this.disabled !== undefined) this.disabled = true; });
  };

  jQuery.fn.enable = function() {
    return this.each(function() { if(this.disabled !== undefined) this.disabled = false; });
  };

  jQuery.fn.delay = function(time,func){
    return this.each(function(){
        setTimeout(func,time);
    });
  };
});

jQuery(document).ready(function() {
  startupDoc();
  jQuery("div.filters select").each(function() { if(this.form) { this.form.reset(); } });
  if(jQuery.ImageBox){
   jQuery.ImageBox.denit(); 
   jQuery.ImageBox.init(); 
  }

  // format currency if class is currency
  jQuery('.currency').blur(function() {
      jQuery('.currency').formatCurrency();
  });
  
  
  //jQuery("tr:nth-child(even)").addClass("odd");


  jQuery('div#notice').delay(2000, function(){
    jQuery('div#notice').fadeOut();
  });
});

var parseCurrency = function(val) {
  return parseFloat(val.gsub(/[^0-9.-]/,'') || 0.0);
};

// // Fun debugging!
// var oldBind = jQuery.fn.bind;
// jQuery.fn.bind = function(){
//   console.log(['bind', this, arguments])
//   return oldBind.apply(this, arguments);
// }
// 
// var oldUnbind = jQuery.fn.unbind;
// jQuery.fn.unbind = function(){
//   console.log(['unbind', this, arguments])
//   return oldUnbind.apply(this, arguments);
// }


// Drag and Drop
// Makes elements draggable, ghosts the element to drag it (so layout doesn't
// freak out), lets it revert (snap back into position).
//
// TODO: Change magic constant "98" below to something based on computed values.
jQuery(function($){
  jQuery.fn.bindDraggable = function(){
    $(this).DraggableDestroy().Draggable({
      revert:   true,
      fx:       100,
      ghosting: true,
      opacity:  0.5,
      onStart: function(ghost){
        var magicConstant = 98;
        if($.browser.msie){
          magicConstant = 0;
        }

        // Problem: dragger doesn't calculate the right x and y coords for this
        // element if it's inline, so we fix it up by using our own offsets and
        // a magicConstant which is browser specific.
        if($(this).css('display') == 'inline'){
          oOffset = $(this).offset();
          gOffset = $(ghost).offset();
          this.dragCfg.oC.x += oOffset.left - gOffset.left;
          this.dragCfg.oC.y += oOffset.top - gOffset.top - magicConstant;
        }
      }
    });
  };

  jQuery.fn.bindDroppable = function(){
    $(this).DroppableDestroy().Droppable({
      accept:       'thumbnail',
      activeclass:  'dropactive', 
      hoverclass:   'drophover',
      tolerance:    'pointer',
      onDrop: function(dropped){
        var self = $(this);
        var indicator = $("<img src=\"/images/indicator.gif\" />");

        $.ajax({
          url: $(this).metadata().action,
          data: $.extend($(dropped).metadata(), $(this).metadata()),
          beforeSend: function(xhr){
            self.append(indicator);
            xhr.setRequestHeader("Accept", "text/javascript");
          },
          complete: function(){indicator.remove();},
          dataType: 'script'
        });
      }
    });
  };
  
  // Autosave fields
  $(document).ready(function() {
    $('select.autosave').change(function(){
      var indicator = $("<img src=\"/images/indicator.gif\" />");
      $(this).after(indicator);
      var d = $(this).metadata();   
      d[$(this).attr('name')] = $(this).find('option[selected]').val();      
      $.post(d.action, d, function(){indicator.remove();});
    });
    
    $('input[type=checkbox].autosave').click(function(){
      var indicator = $("<img src=\"/images/indicator.gif\" />");
      $(this).after(indicator);
      var d = $(this).metadata();      
      d[$(this).attr('name')] = $(this).is(':checked');      
      $.post(d.action, d, function(){indicator.remove();});
    });
  });
  
  
});
