jQuery(document).ready(function(){
	//стили последних, первых и родительских пунктов меню
	jQuery('.menu ul li:first-child').addClass('first');
	jQuery('.menu ul li:last-child').addClass('last');
	jQuery('.menu.menu_bottom li').has('ul').addClass('parent');

	
	
	//рассчет размера блока при увеличении толщины букв в нем
	/*if(jQuery('.menu_2').length > 0){
		jQuery('.menu_2 ul.level_1 > li.item').each(function(i){
			if (jQuery(this).hasClass('active')){
				mas_ww = jQuery(this).width();
				jQuery(this).removeClass('active');
				mas_w = jQuery(this).width();
				jQuery(this).addClass('active');
				jQuery(this).width(mas_ww);
			}
			else{
				mas_w = jQuery(this).width();
				jQuery(this).addClass('active');
				mas_ww = jQuery(this).width();
				jQuery(this).removeClass('active');
				jQuery(this).width(mas_w);
			}
			def_pad_left=parseInt(jQuery(this).css('padding-left'));
			def_pad_right=parseInt(jQuery(this).css('padding-right'));
			new_pad_left=def_pad_left-(mas_ww - mas_w)/2;
			new_pad_right=def_pad_right-(mas_ww - mas_w)/2;
			
			//запись размеров блоков в пользовательские переменные объекта
			jQuery(this).data('w',mas_w);
			jQuery(this).data('ww',mas_ww);
			jQuery(this).data('p_l',def_pad_left);
			jQuery(this).data('p_r',def_pad_right);
			jQuery(this).data('np_l',new_pad_left);
			jQuery(this).data('np_r',new_pad_right);
			
			
			if (jQuery(this).hasClass('active')){
				jQuery(this).css('padding-left', new_pad_left +'px');
				jQuery(this).css('padding-right', new_pad_right +'px');
			}
		})
	}*/
	
	
	
	jQuery('.menu_fade li.item').has('ul').hover(function(){
		jQuery(this).addClass('hover').children('ul').fadeIn(200);
	},function(){
		jQuery(this).removeClass('hover').children('ul').fadeOut(100);
	})
	
	/*jQuery('.menu_2 ul.level_1 > li.item').hover(function(){
		jQuery(this).width(jQuery(this).data('ww'));
		jQuery(this).css('padding-left',jQuery(this).data('np_l'));
		jQuery(this).css('padding-right',jQuery(this).data('np_r'));
			
	},function(){
		if (!jQuery(this).hasClass('active')){
			jQuery(this).width(jQuery(this).data('w'));
			jQuery(this).css('padding-left',jQuery(this).data('p_l'));
			jQuery(this).css('padding-right',jQuery(this).data('p_r'));
		}
	})*/
	
	//для элементов поиска
	def_text="Поиск по сайту";
	jQuery(".cont_search input[type='submit']").val("");
	jQuery(".cont_search input[type='text']").val(def_text);
	
	jQuery(".cont_search input[type='text']").focus(function(){
		if (jQuery(this).val() == def_text) {
			jQuery(this).val('');
		}	
	});	
		
	jQuery(".cont_search input[type='text']").blur(function(){
		if (jQuery(this).val()==""){
			jQuery(this).val(def_text);
		}
	});

	jQuery(".cont_search input[type='submit']").click(function() {
      if (jQuery(".cont_search input[type='text']").val() == def_text) return false;
      return true;
    }); 
	
	//для опросов
	
	jQuery(".vote label").each(function(){
		var for_id=jQuery(this).prev("input").attr("id");
		jQuery(this).attr('for',for_id);
	})
	
	jQuery(".vote input[checked='checked']").each(function(){
	jQuery(this).next("label").addClass("checked");
	})
	
	jQuery('.vote input').click(function(){
		jQuery(this).parents('.votemodule_answer').find('label.checked').removeClass('checked');
		jQuery(this).next("label").addClass("checked");
	})
	

	//jQuery('form#comment-form input[type="submit"][id^="edit-preview"]').css('display','none');
	//jQuery('form.webform-client-form input.form-submit').addClass('button');
	//jQuery('form#comment-form input[type="submit"]').addClass('button');
	
	//класс кнопок
	jQuery('input[type="submit"], input[type="button"], button').addClass('button');
	//убираем подчеркивание у ссылок, в которые вложено изображение
	jQuery('a').has('img').css('text-decoration','none');
	
	//если на странице в контенте только текст (без тегов) IE<9 не понимает trim, но и не ставит лишних пробелов
	if(jQuery.browser.msie && jQuery.browser.version < 9){
		jQuery(".block_center").contents().each(function(){
			if (this.nodeType==3 && jQuery(this).text()!='' && jQuery(this).text()!=' ')
				jQuery(this).wrap('<div class="bl_standart"><div class="padd"></div></div>');
		});
	}
	else{
		jQuery(".block_center").contents().each(function(){
			if (this.nodeType==3 && jQuery(this).text().trim()!='')
				jQuery(this).wrap('<div class="bl_standart"><div class="padd"></div></div>');
		});
	}
	
	jQuery('#edit-delete-avatar').attr('title','Удалить изображение');
	
	//высота баннеров в IE и Chrome
	jQuery(window).load(function(){
		if(jQuery.browser.msie || jQuery.browser.webkit)
		{
			// если картинки на сервере нет, то в IE всех версий отображается рамка с шириной и высотой примерно одинакового размера
			// поэтому проверяем в случае баннеров их высоту
			if (jQuery(".wrapper_banner img").height()>1000){
				jQuery(".wrapper_banner img").height(0);
			}
		}
	})
	
	
	
	//в IE 7,8 при нажатии на календарь происходит скролл наверх, сделаем скролл на позицию календаря
	if (jQuery.browser.msie && jQuery.browser.version < 9){
		jQuery('.click.to_calendar').click(function(){
			var y =jQuery(this).offset().top-100;
			jQuery(document).scrollTop(y);
		})
	}
	
	
	//высота страницы
	var dif=jQuery("body").innerHeight()-jQuery(window).height();
	if (dif<0){
		var mb=parseInt(jQuery(".footer").css("margin-bottom"))-dif;
		jQuery(".footer").css("margin-bottom",mb)
	}
	
	//расширенный раскрытый поиск
	 if (location.href.indexOf('?advanced=1')!=-1)
	{
		jQuery('fieldset.search-advanced').removeClass('collapsed');
	}
	
	
	
	//слайдер с акциями
	if (jQuery('.news_list').hasClass('data_top')){
		jQuery('.news_list.data_top .new_item').each(function(){
			limit=150;
			text=jQuery(this).find('a.title').text();
			if (text.length>limit){
				copy_text=text.substr(0,limit);
				reg=/[\wА-Яа-яЁё-]/;
				//два граничащих символа не должны быть одновременно буквой, цифрой, - или _, иначе слово разорвано
				if (text.charAt(limit).match(reg) && text.charAt(limit-1).match(reg)){
					reg=/(.*[\wА-Яа-яЁё-])([^\wА-Яа-яЁё-]+[\wА-Яа-яЁё-]+)/;
					arr=copy_text.match(reg);
					copy_text=arr[1];
				}
				//последний символ должен быть буквой, цифрой, - или _
				else {
					reg=/[\wА-Яа-яЁё-]/;
					if(!text.charAt(limit-1).match(reg)){
						reg=/(.*[\wА-Яа-яЁё-])([^\wА-Яа-яЁё-]+)/;
						arr=copy_text.match(reg);
						copy_text=arr[1];
					}
				}

				copy_text+='...';
				jQuery(this).find('a.title').text(copy_text);
			}
			
			limit=250;
			text=jQuery(this).find('.anons span').text();
			if (text.length>limit){
				copy_text=text.substr(0,limit);
				reg=/[\wА-Яа-яЁё-]/;
				//два граничащих символа не должны быть одновременно буквой, цифрой, - или _, иначе слово разорвано
				if (text.charAt(limit).match(reg) && text.charAt(limit-1).match(reg)){
					reg=/(.*[\wА-Яа-яЁё-])([^\wА-Яа-яЁё-]+[\wА-Яа-яЁё-]+)/;
					arr=copy_text.match(reg);
					copy_text=arr[1];
				}
				//последний символ должен быть буквой, цифрой, - или _
				else {
					reg=/[\wА-Яа-яЁё-]/;
					if(!text.charAt(limit-1).match(reg)){
						reg=/(.*[\wА-Яа-яЁё-])([^\wА-Яа-яЁё-]+)/;
						arr=copy_text.match(reg);
						copy_text=arr[1];
					}
				}
				copy_text+='...';
				jQuery(this).find('.anons span').text(copy_text);
			}			
		});
		
		h=0;
		jQuery('.news_list.data_top .new_item').each(function(){
			if (jQuery(this).innerHeight()>h){
				h=jQuery(this).innerHeight();
			}
		})
		
		jQuery('.news_list.data_top').height(h);
		count=jQuery('.news_list.data_top .new_item').length;
		cur=0;
		jQuery('.news_list.data_top .new_item').css('display','none').css('position','absolute');
		jQuery('.news_list.data_top .new_item').eq(cur).css('display','block');
		if (count>1){
			interval_animate = 15000;
			int_def_m=setInterval(function(){
				cur_prev=cur;
				cur+=1
				if (cur>=count){
					cur=0;
				}
				jQuery('.news_list.data_top .new_item').eq(cur).fadeIn(200);
				jQuery('.news_list.data_top .new_item').eq(cur_prev).fadeOut(200);
			
			},interval_animate);
		}
	}


	//слайдер с передачами (картинками)
	if (jQuery('.bl_standart').hasClass('bl_slider_img')){
		var c_img=jQuery('.image_wrap_slide').length;
		var k_img=3;
		if (k_img>=c_img){k_img=c_img;}
		else{jQuery('#to_top_image, #to_bottom_image').css('display','block');}
		
		//настройка размеров изображения
		jQuery(window).load(function(){
			var h_p_i=parseInt(jQuery('.image_wrap_slide').css('height'),10);
			hh=h_p_i;
			ww=jQuery('.image_wrap_slide').width();
			jQuery('.image_wrap_slide img').each(function(){
				w=jQuery(this).width();
				h=jQuery(this).height();
				if (w != ww){
					h=h*ww/w;
					w=ww;
				}
				if (h < hh){
					w=w*hh/h;
					h=hh;
					ml=(w-ww)/2;
					jQuery(this).css('margin-left',-ml);
				}
				else{
					if (h > hh){
						mt=(h-hh)/2;
						jQuery(this).css('margin-top',-mt);
					}
				}
				jQuery(this).width(w);
				jQuery(this).height(h);
			})
			
			m_p_i=parseInt(jQuery('.image_wrap_slide').css('margin-top'));
			h_list=parseInt(k_img*h_p_i+m_p_i*(k_img+1));
			jQuery('.slider_images').height(h_list);
			jQuery('.slider_images .images_move').css('top',0);
			j=0;

			jQuery('#to_bottom_image').click(function(){
				if (parseInt(j + k_img) < c_img){
					j+=1;
					h_m_i=(-1)*j*(h_p_i+m_p_i);
					jQuery(this).prev('.slider_images').children('.images_move').animate({top:h_m_i},200);
				}
			})
			
			jQuery('#to_top_image').click(function(){
				if (j>0){
					j-=1;
					h_m_i=(-1)*j*(h_p_i+m_p_i);
					jQuery(this).next('.slider_images').children('.images_move').animate({top:h_m_i},200);
				}
			})
		})
		
	}
	
	//слайдер с диджеями
	//урезаем ссылки, чтобы поместилась в одну строчку с картинкой, иначе будет разная высота
	if (!jQuery('.bl_standart').hasClass('people_spec')){
		limit_dj_link=30;
		jQuery('.people_name').each(function(){
			if (jQuery(this).text().length>limit_dj_link){
				new_text=jQuery(this).text().substr(0,limit_dj_link)+'...';
				jQuery(this).text(new_text);
			}
		})
		
		//равняем по высоте все блоки с людьми
		h=0;
		jQuery('.list_peoples .people').each(function(){
			if (jQuery(this).height()>h){
				h=jQuery(this).height();
			}
		})
		jQuery('.list_peoples .people').height(h);
		var c=jQuery('#list_peoples #people').length;
		var k=3;
		if (k>=c){k=c;}
		else{jQuery('#to_top_people, #to_bottom_people').css('display','block');}
		  
		var h_p=jQuery('#list_peoples #people').innerHeight();
		h_list=k*h_p;
		jQuery('#list_peoples').height(h_list);
		jQuery('#list_peoples #peoples_move').css('top',0);
		i=0;

		jQuery('#to_bottom_people').click(function(){
			if (parseInt(i + k) < c){
				i+=1;
				h_m=(-1)*i*h_p;
				jQuery(this).prev('#list_peoples').children('#peoples_move').animate({top:h_m},200);
			}
		})
		
		jQuery('#to_top_people').click(function(){
			if (i>0){
				i-=1;
				h_m=(-1)*i*h_p;
				jQuery(this).next('#list_peoples').children('#peoples_move').animate({top:h_m},200);
			}
		})
	}
	
	
	/*var UseFlash = 0;
	if (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"] ) {
		var plugin = navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin;
		if (plugin && parseInt(plugin.description.substring(plugin.description.indexOf(".")-1))>=4)
			UseFlash = 1;
	} else if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && 
		  navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
		UseFlash = 1;
	}
	if ( UseFlash ) {
		alert("yes");
	} else if (!(navigator.appName && navigator.appName.indexOf("Netscape")>=0 && navigator.appVersion.indexOf("2.")>=0)) {
		alert("no");
	}*/
	
	
})


;
// ожидаем загрузку
window.onload = function(){
	  // рисуем часы
	  
	   var hr=parseInt(jQuery('#hr').text(),10);
	   var min=parseInt(jQuery('#min').text(),10);
	   //отнимаем, так как ф-ция clock сразу инкрементирует секунду и отображает уже с ней
	   var sec=parseInt(jQuery('#sec').text(),10)-1;
	   var c=0;
	   
	   clock_dial();
	   clock_arrow(hr,min,sec,c);
	}


	function clock_dial() {

	  // получаем контекст canvas
	  // получаем контекст canvas
	  var ctx = document.getElementById("canvas").getContext("2d");
	  
	  // сохраняем состояние
	  ctx.save();
	  // инициализируем холст
	  ctx.clearRect(0,0,42,42);
	  // рисуя в точке 0,0 фактически
	  // рисуем в точке 75,75
	  ctx.translate(21,21);
	  // при рисовании линии в 100px
	  // фактически рисуем линию в 40px
	  ctx.scale(0.1,0.1);
	  // начинаем вращать с 12:00
	  ctx.rotate(-Math.PI/2);
	 
	  // инициализируем свойства рисунка
	  // контуры рисуем черным
	  ctx.strokeStyle = "black";
	  // заливка тоже черная
	  ctx.fillStyle = "black";
	  // ширина линии 8px
	  ctx.lineWidth = 8;
	  // будем рисовать по кругу
	  ctx.lineCap = "round";
	  
	  
	  // сохраняем состояние
	  ctx.save();
	  // рисуем внешнюю окружность
	  // шириной 14px
	  ctx.lineWidth = 70;
	  // синим цветом
	  ctx.strokeStyle = "#ffa200";
	  ctx.beginPath();
	  // рисуем окружность, отступающую
	  // от центра на 142px
	  ctx.arc(0,0,175,0,Math.PI*2,true);
	  //рисуем контур
	  ctx.stroke();
	  ctx.restore();
	 
	  // начинаем рисовать часовые метки
	  // сохраняем предыдущее состояние
	  ctx.save();
	  ctx.strokeStyle = "#fff";
	  ctx.beginPath();
	  // для каждого часа
	  for(var i = 0; i < 12; i++) {
	    // поворачиваем на 1/12
	    ctx.rotate(Math.PI/6);
	    // перемещаем курсор
	    ctx.moveTo(180,0);
	    // рисуем черточку 20px
	    ctx.lineTo(160,0);
	    // рисуем черточку 20px
	  }
	  ctx.stroke();
	  ctx.restore();
	 
	  ctx.restore();  
}

	function clock_arrow(hr,min,sec, c) {
		
	  // получаем текущие дату и время
		if (sec<60){
			sec=sec+1;
		}
		else{
			sec=0;
			if (min<60){
				min=min+1;
			}
			else{
				min=0;
				if(hr<13){
					hr=hr+1;
				}
				else{
					hr=0;
				}
			}
		}
		

	  // получаем контекст canvas
	  // получаем контекст canvas
	  var ctx = document.getElementById("canvas_arrow").getContext("2d");
	  
	  // сохраняем состояние
	  ctx.save();
	  // инициализируем холст
	  ctx.clearRect(0,0,42,42);
	  // рисуя в точке 0,0 фактически
	  // рисуем в точке 75,75
	  ctx.translate(21,21);
	  // при рисовании линии в 100px
	  // фактически рисуем линию в 40px
	  ctx.scale(0.1,0.1);
	  // начинаем вращать с 12:00
	  ctx.rotate(-Math.PI/2); 
	 
	  // сохраняем состояние
	  ctx.save();
	  // начинаем рисовать минутную стрелку
	  // вращаем холст на текущую позицию
	  ctx.rotate((Math.PI/30)*min +
	             (Math.PI/1800)*sec);
	  // ширина линии 10px
	  ctx.lineWidth = 5;
	  ctx.strokeStyle = "#000";
	  ctx.beginPath();
	  // двигаем курсор
	  ctx.moveTo(-28,-5);
	  // рисуем линию
	  ctx.lineTo(112,0);
	  ctx.lineTo(-28,10);
	  ctx.lineTo(-28,-5);
	  ctx.fillStyle = '#f00';
	  ctx.fill();
	  ctx.stroke();
	  ctx.restore(); 
	  
	  // сохраняем состояние
	  ctx.save();
	  // начинаем рисовать секундную стрелку
	  // вращаем холст на текущую позицию
	  ctx.rotate(sec * Math.PI/30);
	  // контур и заливка красного цвета
	  ctx.strokeStyle = "#000";
	  ctx.fillStyle = "#000";
	  // ширина линии 6px
	  ctx.lineWidth = 6;
	  ctx.beginPath();
	  // двигаем курсор
	  ctx.moveTo(-30,0);
	  // рисуем линию
	  ctx.lineTo(100,0);
	  ctx.stroke();
	  ctx.restore();
	  
	   // сохраняем состояние
	  ctx.save();
	  // начинаем рисовать часовую стрелку
	  // вращаем холст на текущую позицию
	  ctx.rotate((Math.PI/6)*hr +
	             (Math.PI/360)*min +
	             (Math.PI/21600)*sec);
	  // устанавливаем ширину линии 14px
	  ctx.lineWidth = 5;
	  ctx.strokeStyle = "#f00";
	  ctx.beginPath();
	  // сдвигаем курсор несколько назад
	  // стобы было похоже на стрелку
	  ctx.moveTo(-20,-5);
	  // рисуем линию почти до часовых меток
	  ctx.lineTo(80,0);
	  ctx.lineTo(-20,10);
	  ctx.lineTo(-20,-5);
	  ctx.fillStyle = '#f00';
	  //заливаем
	  ctx.fill();
	  //рисуем линии
	  ctx.stroke();
	  ctx.restore();
	 
	  ctx.restore();

	  
	  
		setTimeout(function(){
		  clock_arrow(hr,min,sec,c);
		  
		}, 1000);  
	  
};
// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Known Issues:
//
// * Patterns are not implemented.
// * Radial gradient are not implemented. The VML version of these look very
//   different from the canvas one.
// * Clipping paths are not implemented.
// * Coordsize. The width and height attribute have higher priority than the
//   width and height style values which isn't correct.
// * Painting mode isn't implemented.
// * Canvas width/height should is using content-box by default. IE in
//   Quirks mode will draw the canvas using border-box. Either change your
//   doctype to HTML5
//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
//   or use Box Sizing Behavior from WebFX
//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
// * Non uniform scaling does not correctly scale strokes.
// * Optimize. There is always room for speed improvements.

// Only add this code if we do not already have a canvas implementation
if (!document.createElement('canvas').getContext) {

(function() {

  // alias some functions to make (compiled) code shorter
  var m = Math;
  var mr = m.round;
  var ms = m.sin;
  var mc = m.cos;
  var abs = m.abs;
  var sqrt = m.sqrt;

  // this is used for sub pixel precision
  var Z = 10;
  var Z2 = Z / 2;

  /**
   * This funtion is assigned to the <canvas> elements as element.getContext().
   * @this {HTMLElement}
   * @return {CanvasRenderingContext2D_}
   */
  function getContext() {
    return this.context_ ||
        (this.context_ = new CanvasRenderingContext2D_(this));
  }

  var slice = Array.prototype.slice;

  /**
   * Binds a function to an object. The returned function will always use the
   * passed in {@code obj} as {@code this}.
   *
   * Example:
   *
   *   g = bind(f, obj, a, b)
   *   g(c, d) // will do f.call(obj, a, b, c, d)
   *
   * @param {Function} f The function to bind the object to
   * @param {Object} obj The object that should act as this when the function
   *     is called
   * @param {*} var_args Rest arguments that will be used as the initial
   *     arguments when the function is called
   * @return {Function} A new function that has bound this
   */
  function bind(f, obj, var_args) {
    var a = slice.call(arguments, 2);
    return function() {
      return f.apply(obj, a.concat(slice.call(arguments)));
    };
  }

  var G_vmlCanvasManager_ = {
    init: function(opt_doc) {
      if (/MSIE/.test(navigator.userAgent) && !window.opera) {
        var doc = opt_doc || document;
        // Create a dummy element so that IE will allow canvas elements to be
        // recognized.
        doc.createElement('canvas');
        doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
      }
    },

    init_: function(doc) {
      // create xmlns
      if (!doc.namespaces['g_vml_']) {
        doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
                           '#default#VML');

      }
      if (!doc.namespaces['g_o_']) {
        doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
                           '#default#VML');
      }

      // Setup default CSS.  Only add one style sheet per document
      if (!doc.styleSheets['ex_canvas_']) {
        var ss = doc.createStyleSheet();
        ss.owningElement.id = 'ex_canvas_';
        ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
            // default size is 300x150 in Gecko and Opera
            'text-align:left;width:300px;height:150px}' +
            'g_vml_\\:*{behavior:url(#default#VML)}' +
            'g_o_\\:*{behavior:url(#default#VML)}';

      }

      // find all canvas elements
      var els = doc.getElementsByTagName('canvas');
      for (var i = 0; i < els.length; i++) {
        this.initElement(els[i]);
      }
    },

    /**
     * Public initializes a canvas element so that it can be used as canvas
     * element from now on. This is called automatically before the page is
     * loaded but if you are creating elements using createElement you need to
     * make sure this is called on the element.
     * @param {HTMLElement} el The canvas element to initialize.
     * @return {HTMLElement} the element that was created.
     */
    initElement: function(el) {
      if (!el.getContext) {

        el.getContext = getContext;

        // Remove fallback content. There is no way to hide text nodes so we
        // just remove all childNodes. We could hide all elements and remove
        // text nodes but who really cares about the fallback content.
        el.innerHTML = '';

        // do not use inline function because that will leak memory
        el.attachEvent('onpropertychange', onPropertyChange);
        el.attachEvent('onresize', onResize);

        var attrs = el.attributes;
        if (attrs.width && attrs.width.specified) {
          // TODO: use runtimeStyle and coordsize
          // el.getContext().setWidth_(attrs.width.nodeValue);
          el.style.width = attrs.width.nodeValue + 'px';
        } else {
          el.width = el.clientWidth;
        }
        if (attrs.height && attrs.height.specified) {
          // TODO: use runtimeStyle and coordsize
          // el.getContext().setHeight_(attrs.height.nodeValue);
          el.style.height = attrs.height.nodeValue + 'px';
        } else {
          el.height = el.clientHeight;
        }
        //el.getContext().setCoordsize_()
      }
      return el;
    }
  };

  function onPropertyChange(e) {
    var el = e.srcElement;

    switch (e.propertyName) {
      case 'width':
        el.style.width = el.attributes.width.nodeValue + 'px';
        el.getContext().clearRect();
        break;
      case 'height':
        el.style.height = el.attributes.height.nodeValue + 'px';
        el.getContext().clearRect();
        break;
    }
  }

  function onResize(e) {
    var el = e.srcElement;
    if (el.firstChild) {
      el.firstChild.style.width =  el.clientWidth + 'px';
      el.firstChild.style.height = el.clientHeight + 'px';
    }
  }

  G_vmlCanvasManager_.init();

  // precompute "00" to "FF"
  var dec2hex = [];
  for (var i = 0; i < 16; i++) {
    for (var j = 0; j < 16; j++) {
      dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
    }
  }

  function createMatrixIdentity() {
    return [
      [1, 0, 0],
      [0, 1, 0],
      [0, 0, 1]
    ];
  }

  function matrixMultiply(m1, m2) {
    var result = createMatrixIdentity();

    for (var x = 0; x < 3; x++) {
      for (var y = 0; y < 3; y++) {
        var sum = 0;

        for (var z = 0; z < 3; z++) {
          sum += m1[x][z] * m2[z][y];
        }

        result[x][y] = sum;
      }
    }
    return result;
  }

  function copyState(o1, o2) {
    o2.fillStyle     = o1.fillStyle;
    o2.lineCap       = o1.lineCap;
    o2.lineJoin      = o1.lineJoin;
    o2.lineWidth     = o1.lineWidth;
    o2.miterLimit    = o1.miterLimit;
    o2.shadowBlur    = o1.shadowBlur;
    o2.shadowColor   = o1.shadowColor;
    o2.shadowOffsetX = o1.shadowOffsetX;
    o2.shadowOffsetY = o1.shadowOffsetY;
    o2.strokeStyle   = o1.strokeStyle;
    o2.globalAlpha   = o1.globalAlpha;
    o2.arcScaleX_    = o1.arcScaleX_;
    o2.arcScaleY_    = o1.arcScaleY_;
    o2.lineScale_    = o1.lineScale_;
  }

  function processStyle(styleString) {
    var str, alpha = 1;

    styleString = String(styleString);
    if (styleString.substring(0, 3) == 'rgb') {
      var start = styleString.indexOf('(', 3);
      var end = styleString.indexOf(')', start + 1);
      var guts = styleString.substring(start + 1, end).split(',');

      str = '#';
      for (var i = 0; i < 3; i++) {
        str += dec2hex[Number(guts[i])];
      }

      if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
        alpha = guts[3];
      }
    } else {
      str = styleString;
    }

    return {color: str, alpha: alpha};
  }

  function processLineCap(lineCap) {
    switch (lineCap) {
      case 'butt':
        return 'flat';
      case 'round':
        return 'round';
      case 'square':
      default:
        return 'square';
    }
  }

  /**
   * This class implements CanvasRenderingContext2D interface as described by
   * the WHATWG.
   * @param {HTMLElement} surfaceElement The element that the 2D context should
   * be associated with
   */
  function CanvasRenderingContext2D_(surfaceElement) {
    this.m_ = createMatrixIdentity();

    this.mStack_ = [];
    this.aStack_ = [];
    this.currentPath_ = [];

    // Canvas context properties
    this.strokeStyle = '#000';
    this.fillStyle = '#000';

    this.lineWidth = 1;
    this.lineJoin = 'miter';
    this.lineCap = 'butt';
    this.miterLimit = Z * 1;
    this.globalAlpha = 1;
    this.canvas = surfaceElement;

    var el = surfaceElement.ownerDocument.createElement('div');
    el.style.width =  surfaceElement.clientWidth + 'px';
    el.style.height = surfaceElement.clientHeight + 'px';
    el.style.overflow = 'hidden';
    el.style.position = 'absolute';
    surfaceElement.appendChild(el);

    this.element_ = el;
    this.arcScaleX_ = 1;
    this.arcScaleY_ = 1;
    this.lineScale_ = 1;
  }

  var contextPrototype = CanvasRenderingContext2D_.prototype;
  contextPrototype.clearRect = function() {
    this.element_.innerHTML = '';
  };

  contextPrototype.beginPath = function() {
    // TODO: Branch current matrix so that save/restore has no effect
    //       as per safari docs.
    this.currentPath_ = [];
  };

  contextPrototype.moveTo = function(aX, aY) {
    var p = this.getCoords_(aX, aY);
    this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
    this.currentX_ = p.x;
    this.currentY_ = p.y;
  };

  contextPrototype.lineTo = function(aX, aY) {
    var p = this.getCoords_(aX, aY);
    this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});

    this.currentX_ = p.x;
    this.currentY_ = p.y;
  };

  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
                                            aCP2x, aCP2y,
                                            aX, aY) {
    var p = this.getCoords_(aX, aY);
    var cp1 = this.getCoords_(aCP1x, aCP1y);
    var cp2 = this.getCoords_(aCP2x, aCP2y);
    bezierCurveTo(this, cp1, cp2, p);
  };

  // Helper function that takes the already fixed cordinates.
  function bezierCurveTo(self, cp1, cp2, p) {
    self.currentPath_.push({
      type: 'bezierCurveTo',
      cp1x: cp1.x,
      cp1y: cp1.y,
      cp2x: cp2.x,
      cp2y: cp2.y,
      x: p.x,
      y: p.y
    });
    self.currentX_ = p.x;
    self.currentY_ = p.y;
  }

  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
    // the following is lifted almost directly from
    // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes

    var cp = this.getCoords_(aCPx, aCPy);
    var p = this.getCoords_(aX, aY);

    var cp1 = {
      x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
      y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
    };
    var cp2 = {
      x: cp1.x + (p.x - this.currentX_) / 3.0,
      y: cp1.y + (p.y - this.currentY_) / 3.0
    };

    bezierCurveTo(this, cp1, cp2, p);
  };

  contextPrototype.arc = function(aX, aY, aRadius,
                                  aStartAngle, aEndAngle, aClockwise) {
    aRadius *= Z;
    var arcType = aClockwise ? 'at' : 'wa';

    var xStart = aX + mc(aStartAngle) * aRadius - Z2;
    var yStart = aY + ms(aStartAngle) * aRadius - Z2;

    var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
    var yEnd = aY + ms(aEndAngle) * aRadius - Z2;

    // IE won't render arches drawn counter clockwise if xStart == xEnd.
    if (xStart == xEnd && !aClockwise) {
      xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
                       // that can be represented in binary
    }

    var p = this.getCoords_(aX, aY);
    var pStart = this.getCoords_(xStart, yStart);
    var pEnd = this.getCoords_(xEnd, yEnd);

    this.currentPath_.push({type: arcType,
                           x: p.x,
                           y: p.y,
                           radius: aRadius,
                           xStart: pStart.x,
                           yStart: pStart.y,
                           xEnd: pEnd.x,
                           yEnd: pEnd.y});

  };

  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
  };

  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
    var oldPath = this.currentPath_;
    this.beginPath();

    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.stroke();

    this.currentPath_ = oldPath;
  };

  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
    var oldPath = this.currentPath_;
    this.beginPath();

    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.fill();

    this.currentPath_ = oldPath;
  };

  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
    var gradient = new CanvasGradient_('gradient');
    gradient.x0_ = aX0;
    gradient.y0_ = aY0;
    gradient.x1_ = aX1;
    gradient.y1_ = aY1;
    return gradient;
  };

  contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
                                                   aX1, aY1, aR1) {
    var gradient = new CanvasGradient_('gradientradial');
    gradient.x0_ = aX0;
    gradient.y0_ = aY0;
    gradient.r0_ = aR0;
    gradient.x1_ = aX1;
    gradient.y1_ = aY1;
    gradient.r1_ = aR1;
    return gradient;
  };

  contextPrototype.drawImage = function(image, var_args) {
    var dx, dy, dw, dh, sx, sy, sw, sh;

    // to find the original width we overide the width and height
    var oldRuntimeWidth = image.runtimeStyle.width;
    var oldRuntimeHeight = image.runtimeStyle.height;
    image.runtimeStyle.width = 'auto';
    image.runtimeStyle.height = 'auto';

    // get the original size
    var w = image.width;
    var h = image.height;

    // and remove overides
    image.runtimeStyle.width = oldRuntimeWidth;
    image.runtimeStyle.height = oldRuntimeHeight;

    if (arguments.length == 3) {
      dx = arguments[1];
      dy = arguments[2];
      sx = sy = 0;
      sw = dw = w;
      sh = dh = h;
    } else if (arguments.length == 5) {
      dx = arguments[1];
      dy = arguments[2];
      dw = arguments[3];
      dh = arguments[4];
      sx = sy = 0;
      sw = w;
      sh = h;
    } else if (arguments.length == 9) {
      sx = arguments[1];
      sy = arguments[2];
      sw = arguments[3];
      sh = arguments[4];
      dx = arguments[5];
      dy = arguments[6];
      dw = arguments[7];
      dh = arguments[8];
    } else {
      throw Error('Invalid number of arguments');
    }

    var d = this.getCoords_(dx, dy);

    var w2 = sw / 2;
    var h2 = sh / 2;

    var vmlStr = [];

    var W = 10;
    var H = 10;

    // For some reason that I've now forgotten, using divs didn't work
    vmlStr.push(' <g_vml_:group',
                ' coordsize="', Z * W, ',', Z * H, '"',
                ' coordorigin="0,0"' ,
                ' style="width:', W, 'px;height:', H, 'px;position:absolute;');

    // If filters are necessary (rotation exists), create them
    // filters are bog-slow, so only create them if abbsolutely necessary
    // The following check doesn't account for skews (which don't exist
    // in the canvas spec (yet) anyway.

    if (this.m_[0][0] != 1 || this.m_[0][1]) {
      var filter = [];

      // Note the 12/21 reversal
      filter.push('M11=', this.m_[0][0], ',',
                  'M12=', this.m_[1][0], ',',
                  'M21=', this.m_[0][1], ',',
                  'M22=', this.m_[1][1], ',',
                  'Dx=', mr(d.x / Z), ',',
                  'Dy=', mr(d.y / Z), '');

      // Bounding box calculation (need to minimize displayed area so that
      // filters don't waste time on unused pixels.
      var max = d;
      var c2 = this.getCoords_(dx + dw, dy);
      var c3 = this.getCoords_(dx, dy + dh);
      var c4 = this.getCoords_(dx + dw, dy + dh);

      max.x = m.max(max.x, c2.x, c3.x, c4.x);
      max.y = m.max(max.y, c2.y, c3.y, c4.y);

      vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
                  'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
                  filter.join(''), ", sizingmethod='clip');")
    } else {
      vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
    }

    vmlStr.push(' ">' ,
                '<g_vml_:image src="', image.src, '"',
                ' style="width:', Z * dw, 'px;',
                ' height:', Z * dh, 'px;"',
                ' cropleft="', sx / w, '"',
                ' croptop="', sy / h, '"',
                ' cropright="', (w - sx - sw) / w, '"',
                ' cropbottom="', (h - sy - sh) / h, '"',
                ' />',
                '</g_vml_:group>');

    this.element_.insertAdjacentHTML('BeforeEnd',
                                    vmlStr.join(''));
  };

  contextPrototype.stroke = function(aFill) {
    var lineStr = [];
    var lineOpen = false;
    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
    var color = a.color;
    var opacity = a.alpha * this.globalAlpha;

    var W = 10;
    var H = 10;

    lineStr.push('<g_vml_:shape',
                 ' filled="', !!aFill, '"',
                 ' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
                 ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
                 ' stroked="', !aFill, '"',
                 ' path="');

    var newSeq = false;
    var min = {x: null, y: null};
    var max = {x: null, y: null};

    for (var i = 0; i < this.currentPath_.length; i++) {
      var p = this.currentPath_[i];
      var c;

      switch (p.type) {
        case 'moveTo':
          c = p;
          lineStr.push(' m ', mr(p.x), ',', mr(p.y));
          break;
        case 'lineTo':
          lineStr.push(' l ', mr(p.x), ',', mr(p.y));
          break;
        case 'close':
          lineStr.push(' x ');
          p = null;
          break;
        case 'bezierCurveTo':
          lineStr.push(' c ',
                       mr(p.cp1x), ',', mr(p.cp1y), ',',
                       mr(p.cp2x), ',', mr(p.cp2y), ',',
                       mr(p.x), ',', mr(p.y));
          break;
        case 'at':
        case 'wa':
          lineStr.push(' ', p.type, ' ',
                       mr(p.x - this.arcScaleX_ * p.radius), ',',
                       mr(p.y - this.arcScaleY_ * p.radius), ' ',
                       mr(p.x + this.arcScaleX_ * p.radius), ',',
                       mr(p.y + this.arcScaleY_ * p.radius), ' ',
                       mr(p.xStart), ',', mr(p.yStart), ' ',
                       mr(p.xEnd), ',', mr(p.yEnd));
          break;
      }


      // TODO: Following is broken for curves due to
      //       move to proper paths.

      // Figure out dimensions so we can do gradient fills
      // properly
      if (p) {
        if (min.x == null || p.x < min.x) {
          min.x = p.x;
        }
        if (max.x == null || p.x > max.x) {
          max.x = p.x;
        }
        if (min.y == null || p.y < min.y) {
          min.y = p.y;
        }
        if (max.y == null || p.y > max.y) {
          max.y = p.y;
        }
      }
    }
    lineStr.push(' ">');

    if (!aFill) {
      var lineWidth = this.lineScale_ * this.lineWidth;

      // VML cannot correctly render a line if the width is less than 1px.
      // In that case, we dilute the color to make the line look thinner.
      if (lineWidth < 1) {
        opacity *= lineWidth;
      }

      lineStr.push(
        '<g_vml_:stroke',
        ' opacity="', opacity, '"',
        ' joinstyle="', this.lineJoin, '"',
        ' miterlimit="', this.miterLimit, '"',
        ' endcap="', processLineCap(this.lineCap), '"',
        ' weight="', lineWidth, 'px"',
        ' color="', color, '" />'
      );
    } else if (typeof this.fillStyle == 'object') {
      var fillStyle = this.fillStyle;
      var angle = 0;
      var focus = {x: 0, y: 0};

      // additional offset
      var shift = 0;
      // scale factor for offset
      var expansion = 1;

      if (fillStyle.type_ == 'gradient') {
        var x0 = fillStyle.x0_ / this.arcScaleX_;
        var y0 = fillStyle.y0_ / this.arcScaleY_;
        var x1 = fillStyle.x1_ / this.arcScaleX_;
        var y1 = fillStyle.y1_ / this.arcScaleY_;
        var p0 = this.getCoords_(x0, y0);
        var p1 = this.getCoords_(x1, y1);
        var dx = p1.x - p0.x;
        var dy = p1.y - p0.y;
        angle = Math.atan2(dx, dy) * 180 / Math.PI;

        // The angle should be a non-negative number.
        if (angle < 0) {
          angle += 360;
        }

        // Very small angles produce an unexpected result because they are
        // converted to a scientific notation string.
        if (angle < 1e-6) {
          angle = 0;
        }
      } else {
        var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
        var width  = max.x - min.x;
        var height = max.y - min.y;
        focus = {
          x: (p0.x - min.x) / width,
          y: (p0.y - min.y) / height
        };

        width  /= this.arcScaleX_ * Z;
        height /= this.arcScaleY_ * Z;
        var dimension = m.max(width, height);
        shift = 2 * fillStyle.r0_ / dimension;
        expansion = 2 * fillStyle.r1_ / dimension - shift;
      }

      // We need to sort the color stops in ascending order by offset,
      // otherwise IE won't interpret it correctly.
      var stops = fillStyle.colors_;
      stops.sort(function(cs1, cs2) {
        return cs1.offset - cs2.offset;
      });

      var length = stops.length;
      var color1 = stops[0].color;
      var color2 = stops[length - 1].color;
      var opacity1 = stops[0].alpha * this.globalAlpha;
      var opacity2 = stops[length - 1].alpha * this.globalAlpha;

      var colors = [];
      for (var i = 0; i < length; i++) {
        var stop = stops[i];
        colors.push(stop.offset * expansion + shift + ' ' + stop.color);
      }

      // When colors attribute is used, the meanings of opacity and o:opacity2
      // are reversed.
      lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
                   ' method="none" focus="100%"',
                   ' color="', color1, '"',
                   ' color2="', color2, '"',
                   ' colors="', colors.join(','), '"',
                   ' opacity="', opacity2, '"',
                   ' g_o_:opacity2="', opacity1, '"',
                   ' angle="', angle, '"',
                   ' focusposition="', focus.x, ',', focus.y, '" />');
    } else {
      lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
                   '" />');
    }

    lineStr.push('</g_vml_:shape>');

    this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
  };

  contextPrototype.fill = function() {
    this.stroke(true);
  }

  contextPrototype.closePath = function() {
    this.currentPath_.push({type: 'close'});
  };

  /**
   * @private
   */
  contextPrototype.getCoords_ = function(aX, aY) {
    var m = this.m_;
    return {
      x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
      y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
    }
  };

  contextPrototype.save = function() {
    var o = {};
    copyState(this, o);
    this.aStack_.push(o);
    this.mStack_.push(this.m_);
    this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
  };

  contextPrototype.restore = function() {
    copyState(this.aStack_.pop(), this);
    this.m_ = this.mStack_.pop();
  };

  function matrixIsFinite(m) {
    for (var j = 0; j < 3; j++) {
      for (var k = 0; k < 2; k++) {
        if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
          return false;
        }
      }
    }
    return true;
  }

  function setM(ctx, m, updateLineScale) {
    if (!matrixIsFinite(m)) {
      return;
    }
    ctx.m_ = m;

    if (updateLineScale) {
      // Get the line scale.
      // Determinant of this.m_ means how much the area is enlarged by the
      // transformation. So its square root can be used as a scale factor
      // for width.
      var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
      ctx.lineScale_ = sqrt(abs(det));
    }
  }

  contextPrototype.translate = function(aX, aY) {
    var m1 = [
      [1,  0,  0],
      [0,  1,  0],
      [aX, aY, 1]
    ];

    setM(this, matrixMultiply(m1, this.m_), false);
  };

  contextPrototype.rotate = function(aRot) {
    var c = mc(aRot);
    var s = ms(aRot);

    var m1 = [
      [c,  s, 0],
      [-s, c, 0],
      [0,  0, 1]
    ];

    setM(this, matrixMultiply(m1, this.m_), false);
  };

  contextPrototype.scale = function(aX, aY) {
    this.arcScaleX_ *= aX;
    this.arcScaleY_ *= aY;
    var m1 = [
      [aX, 0,  0],
      [0,  aY, 0],
      [0,  0,  1]
    ];

    setM(this, matrixMultiply(m1, this.m_), true);
  };

  contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
    var m1 = [
      [m11, m12, 0],
      [m21, m22, 0],
      [dx,  dy,  1]
    ];

    setM(this, matrixMultiply(m1, this.m_), true);
  };

  contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
    var m = [
      [m11, m12, 0],
      [m21, m22, 0],
      [dx,  dy,  1]
    ];

    setM(this, m, true);
  };

  /******** STUBS ********/
  contextPrototype.clip = function() {
    // TODO: Implement
  };

  contextPrototype.arcTo = function() {
    // TODO: Implement
  };

  contextPrototype.createPattern = function() {
    return new CanvasPattern_;
  };

  // Gradient / Pattern Stubs
  function CanvasGradient_(aType) {
    this.type_ = aType;
    this.x0_ = 0;
    this.y0_ = 0;
    this.r0_ = 0;
    this.x1_ = 0;
    this.y1_ = 0;
    this.r1_ = 0;
    this.colors_ = [];
  }

  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
    aColor = processStyle(aColor);
    this.colors_.push({offset: aOffset,
                       color: aColor.color,
                       alpha: aColor.alpha});
  };

  function CanvasPattern_() {}

  // set up externs
  G_vmlCanvasManager = G_vmlCanvasManager_;
  CanvasRenderingContext2D = CanvasRenderingContext2D_;
  CanvasGradient = CanvasGradient_;
  CanvasPattern = CanvasPattern_;

})();

} // if
;
/**
* author Remy Sharp
* url http://remysharp.com/tag/marquee
*/

(function ($) {
    $.fn.marquee = function (klass) {
        var newMarquee = [],
            last = this.length;

        // works out the left or right hand reset position, based on scroll
        // behavior, current direction and new direction
        function getReset(newDir, marqueeRedux, marqueeState) {
            var behavior = marqueeState.behavior, width = marqueeState.width, dir = marqueeState.dir;
            var r = 0;
            if (behavior == 'alternate') {
                r = newDir == 1 ? marqueeRedux[marqueeState.widthAxis] - (width*2) : width;
            } else if (behavior == 'slide') {
                if (newDir == -1) {
                    r = dir == -1 ? marqueeRedux[marqueeState.widthAxis] : width;
                } else {
                    r = dir == -1 ? marqueeRedux[marqueeState.widthAxis] - (width*2) : 0;
                }
            } else {
                r = newDir == -1 ? marqueeRedux[marqueeState.widthAxis] : 0;
            }
            return r;
        }

        // single "thread" animation
        function animateMarquee() {
            var i = newMarquee.length,
                marqueeRedux = null,
                $marqueeRedux = null,
                marqueeState = {},
                newMarqueeList = [],
                hitedge = false;
                
            while (i--) {
                marqueeRedux = newMarquee[i];
                $marqueeRedux = $(marqueeRedux);
                marqueeState = $marqueeRedux.data('marqueeState');
                
                if ($marqueeRedux.data('paused') !== true) {
                    // TODO read scrollamount, dir, behavior, loops and last from data
                    marqueeRedux[marqueeState.axis] += (marqueeState.scrollamount * marqueeState.dir);

                    // only true if it's hit the end
                    hitedge = marqueeState.dir == -1 ? marqueeRedux[marqueeState.axis] <= getReset(marqueeState.dir * -1, marqueeRedux, marqueeState) : marqueeRedux[marqueeState.axis] >= getReset(marqueeState.dir * -1, marqueeRedux, marqueeState);
                    
                    if ((marqueeState.behavior == 'scroll' && marqueeState.last == marqueeRedux[marqueeState.axis]) || (marqueeState.behavior == 'alternate' && hitedge && marqueeState.last != -1) || (marqueeState.behavior == 'slide' && hitedge && marqueeState.last != -1)) {                        
                        if (marqueeState.behavior == 'alternate') {
                            marqueeState.dir *= -1; // flip
                        }
                        marqueeState.last = -1;

                        $marqueeRedux.trigger('stop');

                        marqueeState.loops--;
                        if (marqueeState.loops === 0) {
                            if (marqueeState.behavior != 'slide') {
                                marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir, marqueeRedux, marqueeState);
                            } else {
                                // corrects the position
                                marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir * -1, marqueeRedux, marqueeState);
                            }

                            $marqueeRedux.trigger('end');
                        } else {
                            // keep this marquee going
                            newMarqueeList.push(marqueeRedux);
                            $marqueeRedux.trigger('start');
                            marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir, marqueeRedux, marqueeState);
                        }
                    } else {
                        newMarqueeList.push(marqueeRedux);
                    }
                    marqueeState.last = marqueeRedux[marqueeState.axis];

                    // store updated state only if we ran an animation
                    $marqueeRedux.data('marqueeState', marqueeState);
                } else {
                    // even though it's paused, keep it in the list
                    newMarqueeList.push(marqueeRedux);                    
                }
            }

            newMarquee = newMarqueeList;
            
            if (newMarquee.length) {
                setTimeout(animateMarquee, 25);
            }            
        }
        
        // TODO consider whether using .html() in the wrapping process could lead to loosing predefined events...
        this.each(function (i) {
            var $marquee = $(this),
                width = $marquee.attr('width') || $marquee.width(),
                height = $marquee.attr('height') || $marquee.height(),
                $marqueeRedux = $marquee.after('<div ' + (klass ? 'class="' + klass + '" ' : '') + 'style="display: block-inline; width: ' + width + 'px; height: ' + height + 'px; overflow: hidden;"><div style="float: left; white-space: nowrap;">' + $marquee.html() + '</div></div>').next(),
                marqueeRedux = $marqueeRedux.get(0),
                hitedge = 0,
                direction = ($marquee.attr('direction') || 'left').toLowerCase(),
                marqueeState = {
                    dir : /down|right/.test(direction) ? -1 : 1,
                    axis : /left|right/.test(direction) ? 'scrollLeft' : 'scrollTop',
                    widthAxis : /left|right/.test(direction) ? 'scrollWidth' : 'scrollHeight',
                    last : -1,
                    loops : $marquee.attr('loop') || -1,
                    scrollamount : $marquee.attr('scrollamount') || this.scrollAmount || 2,
                    behavior : ($marquee.attr('behavior') || 'scroll').toLowerCase(),
                    width : /left|right/.test(direction) ? width : height
                };
            
            // corrects a bug in Firefox - the default loops for slide is -1
            if ($marquee.attr('loop') == -1 && marqueeState.behavior == 'slide') {
                marqueeState.loops = 1;
            }

            $marquee.remove();
            
            // add padding
            if (/left|right/.test(direction)) {
                $marqueeRedux.find('> div').css('padding', '0 ' + width + 'px');
            } else {
                $marqueeRedux.find('> div').css('padding', height + 'px 0');
            }
            
            // events
            $marqueeRedux.bind('stop', function () {
                $marqueeRedux.data('paused', true);
            }).bind('pause', function () {
                $marqueeRedux.data('paused', true);
            }).bind('start', function () {
                $marqueeRedux.data('paused', false);
            }).bind('unpause', function () {
                $marqueeRedux.data('paused', false);
            }).data('marqueeState', marqueeState); // finally: store the state
            
            // todo - rerender event allowing us to do an ajax hit and redraw the marquee

            newMarquee.push(marqueeRedux);

            marqueeRedux[marqueeState.axis] = getReset(marqueeState.dir, marqueeRedux, marqueeState);
            $marqueeRedux.trigger('start');
            
            // on the very last marquee, trigger the animation
            if (i+1 == last) {
                animateMarquee();
            }
        });            

        return $(newMarquee);
    };
}(jQuery));
;

