// JavaScript Document

Fx.ScrollArea = new Class({
  Extends: Fx,

  options: {
    wrapper: 'scroll_wrapper',
    elements: '.scroll_element',
    loadtype: 'none',
    stripelement: false,
    tag: 'div',
    copy: false,
    padding: 0,
    margin: 0,
    mode: 'horizontal',
    smooth: true,
    fixedwidth: true,
    fixedheight: true,
    perpage: 1,
    loopmode: 'stop',
    snap: true,
    indicateTillSuccess: false,
    indicateSuccess: false,
    tabindex: 0,
    writeHash: false
  },
 
  initialize: function(element,options) {
    this.element = this.subject = $(element);
    this.parent(options);
    this.element = this.element || $(this.options.wrapper);
    if (!this.element) {
      return false;
    }
    this.element.addEvent('scroll', function() { this.scrollTo(0,0); }.bind(this.element));
    this.elements = (this.options.copy ? $$(this.options.elements).clone() : $$(this.options.elements)).setStyles({padding:0,margin:0,border:0});
    if (this.elements == undefined || this.elements.length == 0) {
      return false;
    }
    if (this.options.indicateSuccess) {
      this.addEvent('initializing',this.indicateLoading.bind(this));
      this.addEvent('initialized',this.indicateStopLoading.bind(this));
    }
    this.fireEvent('initializing');
    this.element.setStyles({'overflow':'hidden'});
    this.width = this.options.width || this.element.getStyle('width').toInt();
    this.height = this.options.height || this.element.getStyle('height').toInt();
    this.count = this.elements.length;
    this.tweak = 1;
    if (this.options.loopmode == 'loop') {
      if (this.count > 1) {
        this.elements.push(this.elements[0].clone());
	      this.tweak = 0;
      }
      else
        this.options.loopmode == 'stop';
    }
    if (this.options.mode == 'vertical') {
      this.elementheight = ((this.height - (this.options.padding * (this.options.perpage - 1))) / this.options.perpage);
      this.elementwidth = this.width;
      this.offset = this.elementheight + this.options.padding + this.options.margin;
      this.innerheight = this.offset * this.elements.length;
      this.innerwidth = this.elementwidth;
      this.elements.setStyles({'margin-bottom': this.options.margin+'px','padding-bottom': this.options.padding+'px','float':'none','display':'block'});
      this.maxscroll = this.innerheight - this.offset;
    } else {
      this.elementheight = this.height;
      this.elementwidth = ((this.width - (this.options.padding * (this.options.perpage - 1))) / this.options.perpage);
      this.innerheight = this.elementheight;
      this.offset = this.elementwidth + this.options.padding + this.options.margin;
      this.innerwidth = this.offset * this.elements.length;
      this.elements.setStyles({'margin-right': this.options.margin+'px','padding-right': this.options.padding+'px', 'float':'left'});
      this.maxscroll = this.innerwidth - this.offset;
    }
    this.element.adopt((this.inner = new Element('div', {'class': 'inner'})
                       .setStyles({border:0, margin: 0,padding:0,width: (this.options.fixedwidth ? this.innerwidth+'px' : 'auto'), height: (this.options.fixedheight ? this.innerheight+'px' : 'auto'), overflow: 'hidden'})).adopt(this.elements));
    if (this.options.fixedwidth) {
      this.elements.setStyles({'width': this.elementwidth+'px', 'overflow':'hidden'});    
      this.element.setStyles({'width': this.width+'px'});    
    } else {
     this.elements.setStyles({'width': 'auto','overflow':'visible'});
    }
    if (this.options.fixedheight) {
      this.elements.setStyles({'height':this.elementheight+'px','overflow':'hidden'});
      this.element.setStyles({'height': this.height+'px'});    
    } else {
      this.elements.setStyles({'height': 'auto','overflow':'visible'});
    }
    var wrappers = this.element.retrieve('wrappers');
    this.wrappers = wrappers || this.elements.map(function(el) {
      el.addEvent('loading',this.indicateLoadingElement.bind(el));
      el.addEvent('loaded',this.indicateStopLoadingElement.bind(el));
      el.store('scrollarea',this);
      return el.retrieve('wrapper',new Element('div', {
	      styles: $extend(el.getStyles('padding-left','padding-right','padding-top','padding-bottom','margin-left','margin-right','margin-top','margin-bottom','position','float',(this.options.fixedheight ? 'height' : 'h'), (this.options.fixedwidth ? 'width' : 'w')), {'overflow': 'hidden'})
      })).wraps(el.setStyles({'margin':0,'padding':0,'position':'relative','float':'none','overflow':'visible'}));
    }.bind(this));
    this.element.store('wrappers', this.wrappers);
    this.toload = 0;
    if (this.options.loadtype == 'html') {
      this.addEvent('initialized',function() { this.elements = $$(this.options.elements); }.bind(this));
      this.loadHtml();
    } else if (this.options.loadtype == 'img') {
      this.loadImg();
    } 
    this.addEvent('initialized',this.addFocusActions.bind(this));
    if (this.options.writeHash) {
      this.addEvent('initialized',this.addHashActions.bind(this));
    }
    if (this.count <= 1 || (this.options.loadtype != 'html' && this.options.loadtype != 'img') || !this.options.indicateTillSuccess) {
      this.fireEvent('initialized');  
    }
    this.closedelements = 0;
    this.position = this.newposition = 0;
    this.scrolled = 0;
    this[this.options.mode]();
    this.snapped = true;
    this.addEvent('complete',this.compEvent);
  },
  
  indicateLoadingElement: function() {
    var p = this.retrieve('scrollarea');
    if (p.options.indicateSuccess) {
      var w = this.retrieve('temp_wrapper',new Element('div')
          .setStyles({'background':'#000000','opacity':'0.3','filter':'alpha(opacity=30)','overflow':'hidden','position':'relative'}))
          .wraps(this);
      w.grab(new Element('img',{'src':'system/modules/dma_ultimateslider/html/img/loading.gif','class':'temp_indicator','styles':{'position':'absolute'}}),'top');
    }
    p.toload = p.toload + 1;
  },
  
  indicateStopLoadingElement: function() {
    var p = this.retrieve('scrollarea');
    if (p.options.indicateSuccess) {
      var w = this.retrieve('temp_wrapper');
      if (w) {
        this.replaces(w);
      }
      this.eliminate('temp_wrapper');
    }
    p.toload = p.toload - 1;
    if (p.toload <= 0) {
      p.fireEvent('initialized');
    }     
  },
  
  indicateLoading: function() {
    var w = this.element.retrieve('temp_wrapper',new Element('div')
          .setStyles({'background':'#000000 left top no-repeat','opacity':'0.3','filter':'alpha(opacity=30)','overflow':'hidden','position':'relative'})
          .wraps(this.element));
    w.grab(new Element('img',{'src':'system/modules/dma_ultimateslider/html/img/loading.gif','styles':{'position':'absolute'}}),'top');
  },
  
  indicateStopLoading: function() {
    var w = this.element.retrieve('temp_wrapper');
    if (w)
      this.element.replaces(w);
    this.element.eliminate('temp_wrapper');
  },
  
  addFocusActions: function() {
    this.element.getElements('a').each(function(el) { 
      el.store('scrollarea',this); 
      el.setProperty('tabindex',this.options.tabindex);
      el.store('pos',this.options.mode == 'horizontal' ? el.getPosition(this.element).x : el.getPosition(this.element).y);
      el.addEvent('focus', this.whenFocus); 
    }.bind(this));   
  },
  
  addHashActions: function() {
    this.elements.each(function (el,i) {
      var id = el.get('id');
      if (!el.retrieve('hashed')) {
        if (!id) {
          id = (this.element.get('id') || this.element.get('class') || this.get('class') || this.tag) +'_'+i;
        }
        el.set('id','sl_'+id);
        if (window.location.hash.substr(1) == id) {
          this.setPos(i);
        }
      } else if (window.location.hash.substr(1) == id.substr(3)) {
        this.setPos(i);
      }
    },this);
    this.addEvent('complete',this.setHash.bind(this));
  },
  
  whenFocus: function(ev) {
   //    ev.stop();
   // ev.event.preventDefault();
   // ev.event.returnValue = false;
    var scrollarea = this.retrieve('scrollarea');
    if (!scrollarea) return;
    var pos = this.retrieve('pos');
    scrollarea.toPos((pos / scrollarea.offset).round() % scrollarea.count - 1);
  },
  
  loadHtmlSuccess: function(rt,ra,e) {
    // alert (this + " " + rt);
    var n;
    var s = this.options.stripelement;
    var id = e.getProperty('id');
    if (s === true) {
      s = id ? this.options.tag+'#'+id : this.options.elements;
      for (var i = 0;i < ra.length;i++) {
       // alert(ra[i]);
      	if (ra[i].nodeType == 1) {
     	  // alert(i + "/" + rt.length + ": " + rt[i].nodeType + "/" + e + "  " + e.getProperty('id'));
     	    n = ra[i];
	        if (s) {
            n = $(ra[i]).getFirst(s);
            if (n) {
              break;
            }
	        } else { 
            break;
          }
        }
      }
      // if (n == null) n = ra[i];
    } else {
      for (i = 0; i < rt.length;i++) {
        if (rt[i].nodeType == 1) {
          n = rt[i];
          break;
        }
      }
    } 
    // if (!n) return;
    var id = n.get('id');
    var pre = this.options.writeHash ? 'sl_' : '';
    e.set('id',pre+id).store('hashed',true);
    n.set('id',pre+id).store('hashed',true);
    e.fireEvent('loaded');
    if (n) { 
      n.replaces(e);
    }
  },
  
  
  loadHtml: function(){
    this.elements.each(function (e) {
      var a = e.getElement('a');
      if (a) {
        e.fireEvent('loading');
        new Request.HTML({'url':a.toString(),'onSuccess':this.loadHtmlSuccess.bindWithEvents(this,e,2),'evalScripts': false}).send();
      }
    }.bind(this));
  },
  
  loadImg: function(){
  
  },
  
  setHash: function() {
    window.location.hash = this.elements[this.position].get('id').substr(3);
  },
  
  compEvent: function(ev){
    //  alert('comp'+ev.type);
      if (this.options.snap && !this.snapped) {
        this.toPos((this.scrolled / this.offset).round() % this.count);
      } else {
        this.newposition = this.position;
      }
    },
    
  compSnapped: function(){
 //   alert('snapped');
    this.snapped = true;
    this.removeEvent('complete',this.compSnapped);
    this.addEvent('complete',this.compEvent);
    this.compEvent();
  },

  vertical: function(){
    this.margin = 'margin-top';
    this.layout = 'height';
  },

  horizontal: function(){
    this.margin = 'margin-left';
    this.layout = 'width';
  },

  set: function(now,fire){
    fire = fire || true;
    if (now < 0)
      this.scrolled = this.maxscroll + now;
    else
      this.scrolled = (now - this.tweak) % this.maxscroll + this.tweak;
    this.position = (this.scrolled / this.offset).toInt() % this.count;
    var m = - (this.scrolled % this.offset);
    var l = m + this.offset;
    if (now > this.scrolled) {
      this.changeelements(0,this.count,0,this.offset);
      this.closedelements = 0;
    } else if (this.position > this.closedelements) {
      this.changeelements(this.closedelements,this.position,-this.offset,0);
      this.closedelements = this.position;
    } 
    else if (this.position < this.closedelements) {
      this.changeelements(this.position,this.closedelements+1,0,this.offset);
      this.closedelements = this.position;
    }
    this.changeelement(this.position,m,l);
    if (fire)
      this.fireEvent('change',this.scrolled);
    this.snapped = false;
    return this;
  },
  
  changeelements: function(from,to,m,l) {
    for (x = from; x < to;x++) {
      this.changeelement(x,m,l);
    }
  },

  changeelement: function(x,m,l) {
    this.wrappers[x].setStyle(this.margin,m)
  //  this.elements[x].setStyle(this.layout,l);
  },
  
  start: function(scrollto){
    if (scrollto > this.maxscroll) {
      switch (this.options.loopmode) {
        case 'jump':
	        scrollto = 0;
	         break;
	      case 'loop':
	        break;
	    default:
	       scrollto = this.maxscroll;
       }
     }
    else if (scrollto < 0) {
      switch (this.options.loopmode) {
        case 'jump':
	        scrollto = this.maxscroll;
	        break;
	      case 'loop':
	        break;
	      default:
	        scrollto = 0;
       }
     }
     return this.parent(this.scrolled,scrollto);
  },
  
  toNext: function(){
    return this.toPos(this.newposition +1);
  },
  
  toPrev: function(){
    return this.toPos(this.newposition -1);
  },
  
  toPos: function(pos){
    this.newposition = pos;
    this.removeEvent('complete',this.compEvent);
    this.addEvent('complete',this.compSnapped);
    return this.start((this.newposition) * this.offset);
  },
  
  setPos: function(pos){
    this.set(pos*this.offset);
    this.newposition = this.position = pos;
  }
});

Fx.ScrollArea.createAuto = function(wrappers,options) {
  var r = new Array();
  $$(wrappers).each(function(el) {
    r.push (new Fx.ScrollArea(el,options));
  });
  return(r);
}

Function.implement({
	create2: function(options){
		var self = this;
		options = options || {};
		return function(){
			var args = options.arguments;
//			args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0);
//			if (options.event) args = [event || window.event].extend(args);
			var evs = options.event ? 1 : (!$defined(args) ? arguments.length : (options.events || 0));
			var events = $A(arguments).slice(0, evs);
			while(events.length != evs) events.push(undefined);
			args = events.concat($splat(args));
			var returns = function(){
				return self.apply(options.bind || null, args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.periodical) return setInterval(returns, options.periodical);
			if (options.attempt) return $try(returns);
			return returns();
		};
	},

	bindWithEvents: function(bind, args,numEv){
		return this.create2({bind: bind, arguments: args, events: numEv});
	}
});  

