    $.extend({
      macro: function(name, fn)
      {
        $.fn[name] = fn;
      }
    });

    $.fn.extend({
      wait: function(duration, type)
      {
        duration = duration || 1000;
        type = type || "fx";

        var element = this;
        return this.queue(type, function()
        {
          setTimeout(function()
          {
            $(element).dequeue();
          }, duration);
        });
      }
    });

    $.fn.cycle = function(options, isFirst)
    {
      return this.each(function()
      {
        var me = $(this);
        me.children().hide();

        var args = $.extend({}, $.fn.cycle.defaults, options);

        if (!isFirst)
        {
          var obj = $(me.children()[0]);
          me.append(obj);
        }

        obj = $(me.children()[0]);
        obj[args.effect](args.duration);
      });
    };

    $.fn.cycleTimer = function(options)
    {
      return this.each(function()
      {
        var me = $(this);
        var args = $.extend({}, $.fn.cycle.defaults, options);

        me.cycle(args, true);
        window.setInterval(function(){me.cycle(args);}, args.delay);
      });
    };

    $.fn.cycleBehavior = function(options)
    {
      return this.each(function()
      {
        var me = $(this);
        var args = $.extend({}, $.fn.cycle.defaults, options);

        me.cycle(args, true);
        me.bind(args.events, function(e){me.stop(); me.cycle(args);});
      });
    }

    $.fn.cycle.defaults =
    {
      duration: 3000,
      delay: 3000,
      effect: "defaultCycleTransition",
      events: "mouseenter mouseleave"
    };

    $.macro("defaultCycleTransition", function(duration)
    {
      duration = (!duration || duration < 1500) ? 1500 : duration;

      this.fadeIn(1000)
          .wait(duration - 1500)
          .fadeOut(500);
    });