(function($) {
$.fn.announce = function(options) {
  
var options = $.extend({
  open : 10,           // Порядковый номер открытого элемента (по-умолчанию первый)
  openNum : false,       // Количество видимых элементов (по-умолчанию все видимы)
  speed : 150,           // Скорость движения по-умолчанию
  maxHeight : false,     // Высота открытого элемента
  minHeight : false,     // Высота скрытого элемента
  more : false           // Кнопка "ещё"
}, options);

var thisOpen = false;
var prevOpen = false;
var queueOpen = false;
var hasAnimate = false;  // Флаг анимации
var maxH = false;   // Максимальная высота - высота открытого блока
var minH = false;   // Минимальная высота - высота закрытого блока

function mItem(id) {
  this.itemId = id;
  this.body = false;
}

// Слушатель - следит за тем, когда кончится анимация, чтобы вызвать функцию move для объекта в очереди
function listener() {
  var interval1 = setInterval(function() {
    if (queueOpen.itemId && !hasAnimate) {
      thisOpen.itemId = queueOpen.itemId;
      thisOpen.body = queueOpen.body;
      queueOpen.itemId = false;
      move();
      clearInterval(interval1);
    }
  }, options.speed);
}

// Функция движения слайдов
function move() {
  // Если анимация ещё продолжается - текущий объект ставится в очередь, вызывается слушатель
  if (hasAnimate) {
    queueOpen.itemId = thisOpen.itemId;
    queueOpen.body = thisOpen.body;
    listener();
    return;
  }
  
  if (thisOpen.itemId != prevOpen.itemId) {
    hasAnimate = true;
    
    thisOpen.body.animate({aanim : maxH}, {
      easing : "linear",
      duration : options.speed,
      prev : prevOpen.body,
      height : minH,
      complete : function() {
        hasAnimate = false;
      }
    })
    
    thisOpen.body.removeClass("close");
    prevOpen.body.addClass("close");
    prevOpen.itemId = thisOpen.itemId;
    prevOpen.body = thisOpen.body;
  }
}

return this.each(function() {
  /*Открытый - закрываем (animation), наведённый - открываем.
    По завершению анимации - удаляем класс close у открытого, добавляем класс close - к закрытому  
  */
  var container = $(this);
  var items = $("div.item", container);
  var len = items.length;
  if (!options.openNum) {
    options.openNum = len;
  } else {
    len = options.openNum;
  }
  
  // Инициализация - расставляем порядковые номера элементам, вычисляем минимальную и максимальную высоту
  items.each(function(e) {
    var t = $(this);
    t.attr("item", e+1);
    
    if (e+1 > options.openNum) {
      t.css("display", "none");
    } else {
      if (e+1 == options.open) {
        t.removeClass("close");
        maxH = (options.maxHeight ? options.maxHeight : t.css("height")).slice(0,-2)*1;
      } else {
        t.addClass("close");
        if (!minH) {
          minH = (options.minHeight ? options.minHeight : t.css("height")).slice(0,-2)*1;
        }      
      }
    }
  })
  
  // Задаём общую высоту для блока
  container.css("height", ((len-1)*minH + maxH) + "px");
  
  // Создаём объекты текущего, предыдущего и очерёдного элементов
  thisOpen = new mItem(0);
  prevOpen = new mItem(options.open);
  queueOpen = new mItem(false);
  
  prevOpen.body = $("div.item[item="+options.open+"]", container);
  
  // обработчик наведения мыши
  items.mouseover(function() {
    var t = $(this);
    thisOpen.itemId = t.attr("item");
    thisOpen.body = t;
    move();
  })
  
  // Если есть кнопка "ещё"
  if (options.more) {
    $(options.more).toggle(function() {
      len = items.length;
      container.css("height", ((len-1)*minH + maxH) + "px");
      items.each(function(e) {
        var t = $(this);       
        if (e+1 > options.openNum) {
          t.css("display", "block");
        }
      })
    }, function() {
      len = options.openNum;
      thisOpen.itemId = options.open;
      thisOpen.body = $("div.item[item="+options.open+"]", container);
      move();
      container.css("height", ((len-1)*minH + maxH) + "px");
      items.each(function(e) {
        var t = $(this);       
        if (e+1 > options.openNum) {
          t.css("display", "none");
        }
      })
    })
  }
})
}


// Расширенная анимация
$.fx.step.aanim = function(fx) {
  var h1 = 0;
  var h2 = 0;
  
  // Расширяем стандартные опции animate
  fx.options = $.extend({
    prev : false,   // Получаем предыдущий элемент (открытый)
    height : 47
  }, fx.options);
  
  // Получаем начальный элемент
  if (fx.pos == 0 ) {
    fx.start = fx.options.height;
  }
  
  // Вычисление высоты для открывающегося элемента
  h1 = Math.round((fx.end - fx.start)*fx.pos) + fx.start;
  
  // Вычисление высоты для закрывающегося элемента
  h2 = Math.round((fx.end - fx.start)*(1-fx.pos)) + fx.start;
  if (h2 == 0) {
    h2 = fx.options.height;
  }
  
  // Изменяем высоту открывающегося элемента (текущий)
  $(fx.elem).css('height', h1 + "px");
  
  // Изменяем высоту закрывающегося элемента (предыдущий)
  $(fx.options.prev).css('height', h2 + "px");
  
};
})($);
