/* *****************************
 * jquery extensions:
 * ***************************** */

/**
 * Provides support for expandable forms. Invoke on form container, and provide an selector for the collapsable items.
 * @author bernhard.frauendienst@markt.de
 */
(function($){
  $.fn.expandableForm = function(expandableSelector, options) {
    var config = {
      teaseTime: 500,
      teaseSpeed: "fast",
      teaseHeight: 25,
      expandSpeed: "slow",
      expandAfterTease: 750,
      expandCallback: null,
      hideOnExpand: null,
      hideOnExpandSpeed: null,
      collapseSpeed: null,
      collapseOnLoad: false,
      collapseOnLoadCallback: null
    };

    if (options) $.extend(config, options);
    if (config.hideOnExpandSpeed === null) {
      config.hideOnExpandSpeed = config.expandSpeed;
    }
    if (config.collapseSpeed === null) {
      config.collapseSpeed = config.expandSpeed;
    }

    this.each(function() {
      var expandable = $(this).find(expandableSelector);
      var targetHeight = expandable.height();

      var expanded = false;

      var teaseTimeout = null;
      var expandTimeout = null;

      var untease = function() {
        if (expanded) return;
        expandable.animate({height: "0" }, config.teaseSpeed);
      };

      var queueUntease = function() {
        if (expanded) return;

        if (expandTimeout) {
          window.clearTimeout(expandTimeout);
          expandTimeout = null;
        }

        var tempThis = this;

        var timeout = window.setTimeout(function() { untease.call(tempThis); }, config.teaseTime);
        if (teaseTimeout) {
          window.clearTimeout(teaseTimeout);
          teaseTimeout = timeout;
          return;
        }
        teaseTimeout = timeout;
      };

      var tease = function() {
        if (expanded) return;

        var tempThis = this;

        if (config.expandAfterTease) {
          if (!expandTimeout) {
            expandTimeout = window.setTimeout(function() { expand.call(tempThis); }, config.expandAfterTease);
          }
        }

        expandable.stop().show().animate({height: config.teaseHeight}, config.teaseSpeed);
      };

      var expand = function(evt) {
        if (expanded) return;
        if (teaseTimeout) {
          window.clearTimeout(teaseTimeout);
          teaseTimeout = null;
        }

        expanded = true;
        $(this).unbind(".loadEvents");

        expandable.stop().show().animate({height: targetHeight}, config.expandSpeed, function() {
          // IE 6 hack
          if (!($.browser.msie && $.browser.version.indexOf('6') == 0)) {
              $(this).css("height", "");
          }
          if (config.expandCallback) {
            config.expandCallback();
          }
        });

        if (config.hideOnExpand) {
          $(this).find(config.hideOnExpand).stop().slideUp(config.hideOnExpandSpeed);
        }
      };

      function bind(elem) {
        $(elem)
          .bind("mouseenter.loadEvents focusin.loadEvents", tease)
          .bind("mouseleave.loadEvents focusout.loadEvents", queueUntease)
          .bind("keypress.loadEvents change.loadEvents click.loadEvents", expand);
      }

      expandable.css("overflow", "hidden");
      if (config.collapseOnLoad) {
        var thisExForm = this;
        var collapsable = $(this).find(config.hideOnExpand);
        // slide up
        $(document).ready(function() {
          expandable.animate({height: 0}, config.collapseSpeed, function() {
            bind(thisExForm);
            config.collapseOnLoadCallback();
          });
          if (config.hideOnExpand) {
            collapsable.slideDown();
          }
        });
      } else {
        // just hide it
        expandable.css("height", "0").hide();
        if (config.hideOnExpand) {
          $(this).find(config.hideOnExpand).show();
        }
        bind(this);
      }
    });

    return this;
  };

})(jQuery);

/* *****************************
 * :jquery extensions
 * ***************************** */

