/*------------------------------------------------------------------------------------
  Compare Devices
------------------------------------------------------------------------------------*/

var CompareIE = null;
var Compare = {
  
  ////////// SET THESE OPTIONS //////////
  
  development: true, // Development?
  forwardLocation: 'product-attr-compare.jsp', // The url of the results page
  forwardParam: 'products', // The parameter to use to send to the results page
  maxPhones: 5, // Maximum number of phones to compare
  maxPhonesMessage: 'Maximum BlackBerry Smartphone limit reached', // Message to show if you reach the limit
  
  ///////////////////////////////////////
  
  
  phones: [],
  activePhone: null,
  
  init: function(){
    if (this.inited) return;
    this.wrapper = $('comparetool');
    if (!this.wrapper) return;
    this.selector = $('compare_selector_phones');
    this.bucket = $('compare_bucket_phones');
    
    this.inited = true;
    
    // Add all the phones
    var phones = this.selector.getElements('li');
    for(var i=0; i<phones.length; i++){
      if (!phones[i].id) continue;
      var phone = $(phones[i]);
      phone._selectedTop = -26; // The default top: value for the selected class
      phone.location = i;
      
      this.phones.push(phone);
      Compare.Selector.registerPhone(phone);
      
      if (phone.hasClassName('selected')) this.activePhone = phone;
    }    
    // Left/right scroll fun
    // A lot of this are specific effects for edge cases
    var moveDir = function(dir, options){
      if (options){
        if (options.noOutEffect) var no_out_effect = true;
      }
      
      // We've hit the end and tried to go further
      if (!this.activePhone.getBrother(dir)){
        return;
      }
      
      // shrink the phone moving out
      var old = this.activePhone;
      if (!no_out_effect){
        var effect = new Fx.Width(this.activePhone.getElement('img'), {duration:0.5*1000, onStart: function(){ old.removeClassName('selected'); }.bind(this) });
        effect.custom(100, 50);
        effect.toggle();
        /* IE's fake png background? */
        if (CompareIE){
          var effect = new Fx.Width(this.activePhone.getElement('.phoneimg'), {duration:0.5*1000, onComplete: function(){ if (this.activePhone) this.activePhone.addClassName('selected'); }.bind(this) });
          effect.custom(145*.68, 145/2*.68);
          effect.toggle();
          var effect = new Fx.Height(this.activePhone.getElement('.phoneimg'), {duration:0.5*1000 });
          effect.custom(239*.68, 239/2*.68);
          effect.toggle();
        }
        /* End IE */
        var effect = new Fx.Vertical(this.activePhone, {duration:0.5*1000});
        effect.custom(effect.el._selectedTop, 0);
      }
      
      this.activePhone = this.activePhone.getBrother(dir);
      
      // Enable buttons if disabled
      if (Compare.roller.buttonLeft.hasClassName('disabled')){
          Compare.roller.buttonLeft.removeClassName('disabled');
          Compare.roller.buttonLeft.removeClassName('disabled-previous');
      }
      if (Compare.roller.buttonRight.hasClassName('disabled')){
          Compare.roller.buttonRight.removeClassName('disabled');
          Compare.roller.buttonRight.removeClassName('disabled-next');
      }
    
      if (!this.activePhone.getBrother(dir)){
        // There's no phone in the other direction! This means we've hit the end of the line
        if (dir == 'previous'){
          Compare.roller.buttonLeft.addClassName('disabled');
          Compare.roller.buttonLeft.addClassName('disabled-previous');
        }
        if (dir == 'next'){
          Compare.roller.buttonRight.addClassName('disabled');
          Compare.roller.buttonRight.addClassName('disabled-next');
        }
      }
      
      // enlarge the phone moving in
      var effect = new Fx.Width(this.activePhone.getElement('img'), {duration:0.5*1000, onComplete: function(){ if (this.activePhone) this.activePhone.addClassName('selected'); }.bind(this) });
      effect.custom(50, 100);
      effect.toggle();
      /* IE's fake png background? */
      if (CompareIE){
        var effect = new Fx.Width(this.activePhone.getElement('.phoneimg'), {duration:0.5*1000, onComplete: function(){ if (this.activePhone) this.activePhone.addClassName('selected'); }.bind(this) });
        effect.custom(145/2*.68, 145*.68);
        effect.toggle();
        var effect = new Fx.Height(this.activePhone.getElement('.phoneimg'), {duration:0.5*1000 });
        effect.custom(239/2*.68, 239*.68);
        effect.toggle();
      }
      /* End IE */
      var effect = new Fx.Vertical(this.activePhone, {duration:0.5*1000});
      effect.custom(0, effect.el._selectedTop);
      effect.toggle();
      
    }.bind(this);
    
    var moveLeft = function(options){
      Compare.Selector._scrollLeft();
      moveDir('previous', options);
    }.bind(this);
    var moveRight = function(options){
      Compare.Selector._scrollRight();
      moveDir('next', options);
    }.bind(this);
    
    var cancelScroll = function(){
      var dir = this.roller.movingDirection;
      // We've hit the end and tried to go further
      if (!this.activePhone.getBrother(dir)){
        this.roller.cancelScroll = true;
      }
    }.bind(this);
    
    this.roller = new SideRoller('compare_selector_phones', {right: 'compare_selector_next', left: 'compare_selector_prev', increment: 72, margin: 25, duration: 0.5, onScrollRight: moveRight, onScrollLeft: moveLeft, cancelScroll:cancelScroll});
    this.roller.moveRight = moveRight;
    this.roller.moveLeft = moveLeft;
    
    // Compare button
    $('compare_btn').onclick = this.compare.bind(this);
    
    // Select the middle one and enlarge it, and show content
		this.activePhone= this.phones.length > 6 ? this.phones[3] : this.phones[Math.floor(this.phones.length/2)]
    this.activePhone.addClassName('selected');
    Compare.Selector.swapContent(this.activePhone)
    
    // Set up the filters
    Compare.Filters.init();
    
  },
  
  // Resets styles that javascript may have set
  resetPhone: function(phone){
    $(phone).getElement('img').style.width = '';
    if ($(phone).getElement('.phoneimg')) $(phone).getElement('.phoneimg').style.width = '';
    if ($(phone).getElement('.phoneimg')) $(phone).getElement('.phoneimg').style.height = '';
    phone.style.width = '';
    phone.style.marginLeft = '';
    phone.style.marginRight = '';
    phone.style.top = '';
    phone.style.left = ''
    phone.setOpacity(1)
    phone.removeClassName('selected')
  },
  
  // This will be used when filtering/dragging adds/removes phones and jerks the active phone out of center
  recenter: function(){
    // Step 1: Unactivate all phones in selector
    for (var i=0; i<Compare.Selector.phones.length; i++){
      var phone = Compare.Selector.phones[i];
      phone.active = false;
      Compare.resetPhone(phone);
      if (i == 3){
        $(phone).addClassName('selected');
        Compare.activePhone = phone;
        Compare.Selector.swapContent(phone)
      }
      $('compare_selector_phones').style.left = '0';
    }
    // Less than 3 phones. need to move over
    if (Compare.Selector.phones.length < 4) {
      $('compare_selector_phones').style.left = '216px';
      var phone = Compare.Selector.phones[0];
      $(phone).addClassName('selected');
      Compare.activePhone = phone;
      Compare.Selector.swapContent(phone)
    }
  },
  
  // If for some reason there isn't a phone selected, this will make a good decision of which one to activate
  // Really a part of the recenter method
  reactivate: function(){
    
  },
  
  // Collects the data and sends off the compare form action
  compare: function(e){
    if (e) Event.stop(e);
    var ids = [];
    var param;
    for (var i=0; i<Compare.Bucket.phones.length; i++){
      var phone = Compare.Bucket.phones[i];
      if (phone.active) ids.push(phone.getAttribute('id'));
    }
    
    var forwardLoc = this.forwardLocation + '?'
    for (var i=0; i<ids.length; i++){
      var id = ids[i];
      forwardLoc += this.forwardParam + '=' + id + '&'
    }
    
    /*
    // TODO: AJAX request for results
    
    // Slide up the selector
    $('comparetool').effect = new Fx.Slide('comparetool', {duration:0.5*1000});
    $('comparetool').effect.toggle();
    
    var afterAjax = function(responseText){
      $('compare_results').effect.toggle();
    }
    $('compare_results').effect = new Fx.Slide('compare_results', {duration:1*1000});
    $('compare_results').effect.hide()
    
    var ajaxURL = this.development == true ? 'compareResults.html' : forwardLoc;
    // MooTools is a pile of crap
    new Ajax(ajaxURL, {method: 'get', update:'compare_results', onComplete:afterAjax}).request()
    */
    document.location = forwardLoc;
    
  }
}

// The selector is the top section where phones can be scrolled and dragged from
Compare.Selector = {
  phones: [],
  
  // PUBLIC METHODS
  
  // Scroll the selector right
  scrollRight: function(){
    Compare.roller.scrollRight();
  },
  _scrollRight: function(){
    var oldPhone = Compare.activePhone;
    var newPhone = oldPhone.getBrother('next');
    if (newPhone) this.swapContent(newPhone);
  },
  
  // Scroll the selector left
  scrollLeft: function(){
    Compare.roller.scrollLeft();
  },
  _scrollLeft: function(){
    var oldPhone = Compare.activePhone;
    var newPhone = oldPhone.getBrother('previous');
    if (newPhone) this.swapContent(newPhone);
  },
  
  // Removes a phone from the selector
  removePhone: function(phone, options){
    // Transitions: Don't do if forced
    if (this.phones.length != 1){ // Are we removing the last phone?
      if (!options || !options.force){
        // Scroll the selector the appropriate amount according to the position of the phone
        var current_location = Compare.activePhone.location;
        //// Removing the selected phone
        if (current_location == phone.location){
          if (phone.getBrother('next')) Compare.roller.moveRight({noOutEffect:true});
          else Compare.roller.scrollLeft({noOutEffect:true});
        }
        /// To the right of the selected phone
        if (current_location < phone.location){
          // Nothing needs to be done
        }
        //// To the left of the selected phone
        if (current_location > phone.location){
          Compare.roller.moveRight();
        }
        if (current_location > phone.location && Compare.Selector.phones.length <= 4){
          Compare.roller.noScrollEvents = true;
          Compare.roller.scrollLeft();
        }
      }
    }else{ // We are removing the last phone!
      Compare.selector.style.left = 0;
      Compare.wrapper.addClassName('empty')
    }
    
    phone.active = false;
    
    this.phones.remove(phone)
    Compare.resetPhone(phone);
    
    // Only remove the phone immediately if we're forcing it
    if (options && options.force){
      try{phone.remove();}catch(e){}
    }else{
      phone.shrink = true;
    }
    
  },
  
  // Adds a phone to the selector
  addPhone: function(phone){
    this.registerPhone(phone);
    Compare.selector.appendChild(phone);
    if (Compare.Selector.phones.length <=3){
     Compare.recenter(); 
    }
  },
  
  // Registers all the functionality for a phone in the selector
  registerPhone: function(phone){
    // Are we adding the first phone?
    if (this.phones.length == 0){
      Compare.wrapper.removeClassName('empty')
    }
    
    phone.inside = 'selector';
    phone.shrink = false;
    Compare.resetPhone(phone);
    
    // Make it draggable
    this.phones.push(phone);
    Compare.Selector.draggableOptions.droppables = [$('compare_bucket').extend(Compare.Bucket.droppableOptions)];
    phone.dragObject = $(phone).addClassName('drag').makeDraggable(Compare.Selector.draggableOptions);
  },
  
  
  // PRIVATE METHODS
  
  // Swaps out the overview & features of the phone
  swapContent: function(phone){
    if (!this.containers){
      this.containers = {
        model: $('compare_model'),
        overview: $('compare_overview'),
        features: $('compare_features')
      }
    }
    
    this.containers.model.innerHTML = phone.getElement('h3').innerHTML;
    this.containers.overview.innerHTML = phone.getElement('.overview').innerHTML;
    this.containers.features.innerHTML = phone.getElement('.features').innerHTML;
  },
  
  // Enlarges & adjusts the top-margin of the phone
  enlargePhone: function(phone){
    
  },
  
  // Shrinks & adjusts the top-margin of the phone
  shrinkPhone: function(phone){
    
  }
  
}
Compare.Selector.draggableOptions = {
  onStart: function(){
    this.element.setOpacity(0.5);
    this.element.addClassName('dragging');
  },
  onComplete: function(){
    this.element.style.left = 0;
    this.element.style.top = this.element.hasClassName('selected') ? this.element._selectedTop + 'px' : 0;
    
    // I need to check if we're removing this phone, however the removePhone method
    // gets called AFTER this method, and this method fires the effects
    // So, we'll time a function to check for it.
    var after = function(){
      if (this.element.shrink == true){
        this.element.shrink = false;
        this.element.style.visibility = 'hidden';
        var effect = new Fx.Width(this.element, {duration:0.4*1000});
        effect.toggle();
        var after = function(){
          this.element.remove();
        }.bind(this)
        var effect2 = new Fx.HorizontalMargin(this.element, {duration:0.4*1000, onComplete:after})
        effect2.toggle();
        return;
      }
      var effect = new Fx.Opacity(this.element)
      effect.custom(0.5, 1);
      effect.toggle();
      this.element.removeClassName('dragging');      
      
    }.bind(this);
    setTimeout(after, 10);    
    
    // No blinking!!!!
    this.element.style.visibility = 'hidden'

  }
}

// The bucket is the section below where phones are dropped
Compare.Bucket = {
  phones: [],
  
  // Adds a phone to the bucket
  addPhone: function(phone){
    if (!Compare.bucket.visible()) Compare.bucket.show();
    if (!$(Compare.bucket.parentNode).hasClassName('hasPhones')) $(Compare.bucket.parentNode).addClassName('hasPhones');
    
    var oldphone = phone;
    phone = phone.clone();
    phone._selectedTop = oldphone._selectedTop;
    phone.inside = oldphone.inside;
    
    this.registerPhone(phone);
    
    Compare.bucket.appendChild(phone);
  },
  
  // Registers all the functionality for a phone in the selector
  registerPhone: function(phone){
    // Reset the img
    Compare.resetPhone(phone);
    phone.inside = 'bucket';
    phone.active = true;
    phone.shrink = false;
    
    // Make it draggable
    Compare.Bucket.draggableOptions.droppables = [$('compare_selector').extend(Compare.Selector.droppableOptions)];
    this.phones.push(phone);
    
    phone.dragObject = $(phone).makeDraggable(Compare.Bucket.draggableOptions);
    
    // Are we at the max allowed phones?
    if (this.phones.length >= Compare.maxPhones){
      $('message').innerHTML = Compare.maxPhonesMessage;
      $('message').show();
    }
  },
  
  // Removes a phone from the bucket
  removePhone: function(phone){
    $('message').hide();
    this.phones.remove(phone);
    phone.active = false;
    phone.remove();
  }
}
Compare.Bucket.draggableOptions = {
  onStart: function(){
    this.element.setOpacity(0.5);
    this.element.addClassName('dragging');
  },
  onComplete: function(){
    var effect = new Fx.Opacity(this.element)
    effect.custom(0.5, 1);
    effect.toggle();
    this.element.style.left = 0;
    this.element.style.top = 0;
    this.element.removeClassName('dragging');    
  }
}
Compare.Bucket.droppableOptions = {
  onOver: function(){
    this.addClassName('bucketover');
  },
  onLeave: function(){
    this.removeClassName('bucketover');
  },
  onDrop: function(dropped){
    if (Compare.Bucket.phones.length >= Compare.maxPhones) return;
    Compare.Selector.removePhone(dropped);
    Compare.Bucket.addPhone(dropped);
  }
}
Compare.Selector.droppableOptions = {
  onDrop: function(dropped){
    Compare.Bucket.removePhone(dropped);
    // TODO: Only add it if the phone is "active" (filters)
    Compare.Selector.addPhone(dropped);
  }
}


Compare.Filters = {
  // Note that all filters in these variables are the options NOT selected (should not show)
  activeFilters: {
    regions:[],
    carriers:[],
    features:[]
  },
  
  // Holds phones
  filters: {
    regions:{},
    carriers:{},
    features:{}
  },
  
  
  init: function(){
    this.element = $('compare_options');
    
    // Set up the three tabs & drop-downs
    this.tabs = $('compare_options').getElements('a');
    for (var i=0; i<this.tabs.length; i++){
      var tab = this.tabs[i];
      tab.options = $(tab.parentNode).getElement('.filters');
      if (!tab.options) continue;
      
      tab.effect = new Fx.Opacity(tab.options, {duration:300});
      tab.effect.set(0);
      tab.onclick = function(){
        if (Compare.activeTab && Compare.activeTab != this && $(Compare.activeTab).hasClassName('active')){
          Compare.activeTab.effect.toggle();
          $(Compare.activeTab).toggleClassName('active');
        }
        this.effect.toggle();
        $(this).toggleClassName('active');
        Compare.activeTab = this;
        return false;
      }
	  
	  var submitClick = function(){
	    if (Compare.activeTab && Compare.activeTab != this && $(Compare.activeTab).hasClassName('active')){
        Compare.activeTab.effect.toggle();
        $(Compare.activeTab).toggleClassName('active');
      }
      Compare.Filters.update();
	  }
 
      tab.options.getElement('.btnupdate').onclick = submitClick;
	  
      tab.options.getElement('.close').onclick = tab.onclick.bind(tab);
      //tab.options.getElement('.btnupdate').onclick = tab.onclick.bind(tab);
	  
      //tab.options.getElement('.btnupdate').onclick = Compare.Filters.update();
      // Check all the boxes on load (all options are checked)
      this.checkboxes = this.element.getElements('input');
      for (var k=0; k<this.checkboxes.length; k++){
        var checkbox = this.checkboxes[k];
        // Do not check by default
        //checkbox.checked = 'checked';
        
        // Initialize the array that will hold phones corresponding to this value
        this.filters[checkbox.name][checkbox.value] = [];
        
        checkbox.onclick = function(){
          !this.checked ? Compare.Filters.uncheck(this) : Compare.Filters.check(this);
        }
      }  
    }
    
    // Put phones in their corresponding filter categories
    for (var k=0; k<Compare.phones.length; k++){
      var phone = Compare.phones[k];
      
      // break up the regions
      var regions = this.split(phone.getAttribute('regions'));
      for (var j=0; j<regions.length; j++){
        if (!this.filters.regions[regions[j]]) continue;
        this.filters.regions[regions[j]].push(phone);
      }
      
      // break up the carriers
      var carriers = this.split(phone.getAttribute('carriers'));
      for (var j=0; j<carriers.length; j++){
        if (!this.filters.carriers[carriers[j]]) continue;
        this.filters.carriers[carriers[j]].push(phone);
      }
      
      // break up the features
      var features = this.split(phone.getAttribute('features'));
      for (var j=0; j<features.length; j++){
        if (!this.filters.features[features[j]]) continue;
        this.filters.features[features[j]].push(phone);
      }
    }
  },
  
  // The splitter function used by engineering to dissect the custom attributes
  split: function(str){
    return str.replace(/^\s*|\s*$/g,'').split(' ');
  },
  
  uncheck: function(input){
    this.activeFilters[input.name].remove(input.value);
    //this.update();
  },
  
  check: function(input){
    if (!this.activeFilters[input.name].test(input.value)) this.activeFilters[input.name].push(input.value);
    //this.update();
  },
  
  // Checks all the options and updates the phones displayed to reflect  the (not) selected options
  update: function(){
    
    // Hide Phones & Show the filtering screen
    $('selector_inner').hide();
    $$('.loader').first().show();

    // ADD ALL PHONES
    for (var i=0; i<Compare.phones.length; i++){
      var phone = Compare.phones[i];
      if (phone.inside != 'bucket' && !Compare.Selector.phones.test(phone)) Compare.Selector.addPhone(phone);
      if (phone.inside == 'bucket') Compare.resetPhone(phone);
    }
    
    
    // REMOVE PHONES FROM SELECTOR
    var orig = Compare.Selector.phones.copy(); // This changes as iterations go through, so let's make a copy
    for (var i=0; i<orig.length; i++){
      var phone = orig[i];
      // Check the regions
      var regions = this.split(phone.getAttribute('regions'));
      /* Old way -- if ANY features present, show 
      if (regions.subtract(this.activeFilters.regions).length == 0){
      */
      /* New way - if ANY features NOT present, remove */
      if (regions.length == regions.subtract(this.activeFilters.regions).length && this.activeFilters.regions.length > 0){
        Compare.Selector.removePhone(phone, {force:true});
      }
    
      // Check the carriers
      var carriers = this.split(phone.getAttribute('carriers'));
      /* Old way -- if ANY features present, show 
      if (carriers.subtract(this.activeFilters.carriers).length == 0){
      */
      /* New way - if ANY features NOT present, remove */
      if (carriers.length == carriers.subtract(this.activeFilters.carriers).length && this.activeFilters.carriers.length > 0){
        Compare.Selector.removePhone(phone, {force:true});
      }
    
      // Check the features
      var features = this.split(phone.getAttribute('features'));
      /* Old way -- if ANY features present, show 
      if (features.subtract(this.activeFilters.features).length == 0){
      */
      /* New way - if ANY features NOT present, remove */
      if (features.length == features.subtract(this.activeFilters.features).length && this.activeFilters.features.length > 0){
        Compare.Selector.removePhone(phone, {force:true});
      }
    }
    // DISABLE PHONES IN BUCKET
    for (var i=0; i<Compare.Bucket.phones.length; i++){
      var phone = Compare.Bucket.phones[i];
      // Check the regions
      var regions = this.split(phone.getAttribute('regions'));
      if (regions.subtract(this.activeFilters.regions).length == 0){
        phone.active = false;
        phone.setOpacity(0.2);
      }
    
      // Check the carriers
      var carriers = this.split(phone.getAttribute('carriers'));
      if (carriers.subtract(this.activeFilters.carriers).length == 0){
        phone.active = false;
        phone.setOpacity(0.2);
      }
    
      // Check the features
      var features = this.split(phone.getAttribute('features'));
      if (features.subtract(this.activeFilters.features).length == 0){
        phone.active = false;
        phone.setOpacity(0.2);
      }
    }
    // This prevents a "jerky" feel to the javascript ripping out elements and throwing them back
    // in. Instead we ease in and out with a loader (that really isn't processing anything) and an effect
    var showProducts = function(){
      Compare.recenter();

      $$('.loader').first().hide();
      $('selector_inner').show();
    }
    setTimeout(showProducts, 500)
  }
}

// Array subtracting
Array.prototype.subtract = function(arr){
  var tmp = this;
  for (var i=0; i<arr.length; i++){
    tmp.remove(arr[i]);
  }
  return tmp;
}




/*------------------------------------------------------------------------------------
  SideRoller
  This creates a sliding horizontal bar
  
  Usage:
    new SideRoller(element, options)
    
    element:  A string representing an element id or a DOM Object
    options:  An object containing any of these values properties:
    
      left:         The id/object of the left (or previous) arrow
      right:        The id/object of the right (or previous) arrow
      increment:    The amount each click of the scroll arrows scrolls the SideRoller
      margin:       The margin in between each element inside the sideroller
      duration:     The time it takes for the SideRoller to scroll one click of the 
                    scroll arrows
      padding:      An object (with properties left/right) that is really used for
                    hacking any "extra" space that appears at the end of a SideRoller
                    that prevents the arrows from being activated/deactivated.
                    Useful when you are setting a default margin, or offset on the
                    inner scrolling content.
------------------------------------------------------------------------------------*/

var SideRoller = Class.create();
SideRoller.DefaultOptions = {
  increment: 100,
  margin: 0,
  duration:1,
  padding:{right:0, left:0}
}
SideRoller.prototype = {
  initialize: function(element, options){
    this.element = $(element);
    this.options = Object.extend(SideRoller.DefaultOptions, options || {});
    // Handles
    this.buttonRight = $(this.options.right);
    this.buttonLeft = $(this.options.left);
    
    this.buttonRight.addEvent('click', this.scrollRight.bindAsEventListener(this));
    this.buttonLeft.addEvent('click', this.scrollLeft.bindAsEventListener(this));
    
    // inside element must have position:absolute
    $(this.element).setStyle('position', 'absolute');
    // outer wrapper must have either position:absolute or position:relative
    if ($(this.element.parentNode).getStyle('position') == ('static' || null)) $(this.element.parentNode).setStyle('position', 'relative');
    
    // Set the starting point (in case left is already defined)
    this.zero = parseInt(this.element.getStyle('left')) || 0;
    
    var afterCleanup = function(){
      this.moving = false;
    }.bind(this);

    // Define the effect used
    this.effect = new Fx.Horizontal(this.element, {duration:this.options.duration*1000, onComplete:afterCleanup});
    
    // Disable buttons
    var x_pos = parseInt(this.element.getStyle('left'));
    this.scrollDifference(x_pos, 'left', null, true);
    this.scrollDifference(x_pos, 'right', null, true);
  },
  
  getViewable: function(){
    // Find length of elements to estabilish starting/ending points
    var length = 0;
    var children = $A(this.element.childNodes);
    for (var i=0;i<children.length;i++){
      var child = children[i];
      if (child.nodeType == 1) length += child.offsetWidth + this.options.margin;
    };
    this.width = length - this.options.margin;
    this.viewableWidth = this.element.parentNode.offsetWidth - this.options.padding.right;
  },
  
  scrollDifference: function(x_pos, direction, checking, onlydisable){
    this.getViewable();
    
    if (direction == 'left'){
      //var diff = x_pos + this.options.increment < this.zero ?  this.options.increment : (this.zero - x_pos);
      // Always go left
      var diff = this.options.increment
    }
    if (direction == 'right'){
      //var diff = x_pos - this.options.increment > (this.width*-1 + this.viewableWidth) ?  -1*this.options.increment : (this.width*-1 + this.viewableWidth - x_pos)
      // Always go right
      var diff =  -1*this.options.increment;
    }
    
    // Might use this snippet later for continuous phone line
    if (!checking){
      // Check to see if we can scroll again, and set disabling classes on arrows
      if (this.scrollDifference(x_pos + diff, 'left', true) == 0){
        // We've reached the end of the left (visually)
        
        //this.buttonLeft.addClassName('disabled');
        //this.buttonLeft.addClassName('disabled-previous');
      }
      
      if (this.scrollDifference(x_pos + diff, 'right', true) == 0){
        // We've reached the end of the right (visually)
        
        //this.buttonRight.addClassName('disabled');
        //this.buttonRight.addClassName('disabled-next');
      }
    }
    
    return diff;
  },
  
  scrollRight: function(e){
    if (e) Event.stop(e);
    
    if (!this.element.visible()) return;
    
    if (this.moving) return;
    this.moving = true;
        
    this.movingDirection = 'next';
    this.event('cancelScroll');
    if (this.cancelScroll){
      this.cancelScroll = false;
      this.moving = false;
      if (e) Event.stop(e);
      return
    }
    this.movingDirection = null;
    
    this.getViewable();
    
    var x_pos = parseInt(this.element.getStyle('left'));
    var end_pos = x_pos + this.scrollDifference(x_pos, 'right');
    
    this.effect.custom(x_pos, end_pos);
    this.effect.toggle();
    if (this.noScrollEvents)
      this.noScrollEvents = false;
    else
      this.event('onScrollRight');
  },
  
  scrollLeft: function(e){
    if (e) Event.stop(e);
    
    if (!this.element.visible()) return;
    
    if (this.moving) return;
    this.moving = true;
    
    this.movingDirection = 'previous';
    this.event('cancelScroll');
    if (this.cancelScroll){
      this.cancelScroll = false;
      this.moving = false;
      return
    }
    this.movingDirection = null;
    
    this.getViewable();
    
    var x_pos = parseInt(this.element.getStyle('left'));
    var end_pos = x_pos + this.scrollDifference(x_pos, 'left')
    this.effect.custom(x_pos, end_pos);
    this.effect.toggle();
    if (this.noScrollEvents)
      this.noScrollEvents = false;
    else
      this.event('onScrollLeft');
    
  },
  
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  }
}


// Generic horizontal positioning, mootools style
Fx.Position = Fx.Base.extend({
	initialize: function(el, options) {
		this.el = $(el);
		this.iniX = this.el.getStyle('left');
		this.iniY = this.el.getStyle('top');
		this.setOptions(options);
	}
});

Fx.Horizontal = Fx.Position.extend({	
	increase: function() {
		this.el.style.left = this.now + "px";
	},

	toggle: function(){
	  this.el.leftPos = this.el.getStyle('left');
		if (this.el.leftPos > 0) this.custom(this.el.leftPos, 0);
		else this.custom(0, this.iniX);
	}
});

Fx.Vertical = Fx.Position.extend({	
	increase: function() {
		this.el.style.top = this.now + "px";
	},

	toggle: function(){
	  this.el.topPos = this.el.getStyle('top');
		if (this.el.topPos > 0) this.custom(this.el.topPos, 0);
		else this.custom(0, this.iniY);
	}
});

// Generic margin styling
Fx.Margin = Fx.Base.extend({
	initialize: function(el, options) {
		this.el = $(el);
		this.iniX = parseInt(this.el.getStyle('margin-left')) + parseInt(this.el.getStyle('margin-right'));
		this.iniY = parseInt(this.el.getStyle('margin-top')) + parseInt(this.el.getStyle('margin-bottom'));
		this.setOptions(options);
	}
});
Fx.HorizontalMargin = Fx.Position.extend({	
	increase: function() {
	  this.el.setStyle('margin-left', this.now/2 + 'px');
	  this.el.setStyle('margin-right', this.now/2 + 'px');
	},

	toggle: function(){
	  this.el.marginWidth = parseInt(this.el.getStyle('margin-left')) + parseInt(this.el.getStyle('margin-right'));
		if (this.el.marginWidth > 0) this.custom(this.el.marginWidth, 0);
		else this.custom(0, this.iniX);
	}
});

// Mootools doesn't have this?
if (!Event) var Event = {}
Event.stop = function(event) {
  if (event.preventDefault) {
    event.preventDefault();
    event.stopPropagation();
  } else {
    event.returnValue = false;
    event.cancelBubble = true;
  }
}

function checkedAll (thisLink, checked) {
	var el = thisLink.parentNode.parentNode;
	for (i = 0; i < el.elements.length; i++) {
	  if(el.elements[i].checked || !el.elements[i].checked){
		  el.elements[i].checked = checked;
	  }
	}
}