﻿/*
* jQuery Co3 Scroll plugin
* 
* Version 1.0
* 08. March 2009
*
* Co3 Interaktivt kompetencebureau
* www.co3.dk
*
* Developer
* Rune Øllgaard Grønkjær
* rg@co3.dk
*
* Created with jQuery v1.3.2
* Tested with jQuery v1.3.2
*
* Useage:
* Wraps a scrollcontent in a very fexible scrollarea
*
* Settings:
* {
*    width: 400, (Ikke nødvendig. Man kan også style sig ud af det.)
*    height: 300, (Ikke nødvendig. Man kan også style sig ud af det.)
*    scrollSpeed: 500,
*    scrollInInterval: true, //True if the scroll should move in intervals
*    scrollIntervalY: 300, //The Y-axis interval
*    scrollIntervalX: 400, //The X-axis interval
*    upEvents: [{selector: "#scrollButton01UP",
*                startEvent: "mouseover",
*                endEvent: "mouseout" },
*                {selector: "#scrollButton01UP",
*                startEvent: "mousedown",
*                endEvent: "mouseup",
*                scrollSpeed: 1000 }],
*    downEvents: undefined,
*    leftEvents: undefined,
*    rightEvents: undefined,
*    scrollWrapperClasses: "class name or class names separated by space"
*    hideWhenNotNeeded: true/false
*    scrollInInterval: true,
*    scrollInIntervalEventsY: [{firstSelector: "#scrollButton01DOWN",
*                    secondSelector: "#scrollButton01UP",
*                    interval: 300,
*                    scrollNudge: { pixels: 30,
*                                   speed: 200 },
*                    event: "mousedown",
*                    scrollSpeed: 1000,
*                    hideWhenNotNeeded: false}]
* }
*/

/*---MouseWheel Plugin START---*/
eval(function(p, a, c, k, e, r) { e = function(c) { return (c < 62 ? '' : e(parseInt(c / 62))) + ((c = c % 62) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) }; if ('0'.replace(0, e) == 0) { while (c--) r[e(c)] = k[c]; k = [function(e) { return r[e] || e } ]; e = function() { return '[24-9f-zAB]' }; c = 1 }; while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); return p } ('(5(b){b.6.g.4={setup:5(){8 c=b.6.g.4.h;7(b.9.i){b(2).m(\'n.4\',5(a){b.f(2,\'j\',{o:a.o,p:a.p,q:a.q,r:a.r})})}7(2.s){2.s((b.9.i?\'t\':\'4\'),c,u)}v{2.w=c}},teardown:5(){8 a=b.6.g.4.h;b(2).x(\'n.4\');7(2.y){2.y((b.9.i?\'t\':\'4\'),a,u)}v{2.w=5(){}}b.removeData(2,\'j\')},h:5(a){8 c=Array.prototype.slice.call(arguments,1);a=b.6.fix(a||window.6);b.z(a,b.f(2,\'j\')||{});8 d=0,e=true;7(a.k){d=a.k/120}7(a.A){d=-a.A/3}7(b.9.opera){d=-a.k}a.f=a.f||{};a.type="4";c.B(d);c.B(a);l b.6.handle.apply(2,c)}};b.fn.z({4:5(a){l a?2.m("4",a):2.trigger("4")},unmousewheel:5(a){l 2.x("4",a)}})})(jQuery);', [], 38, '||this||mousewheel|function|event|if|var|browser||||||data|special|handler|mozilla|mwcursorposdata|wheelDelta|return|bind|mousemove|pageX|pageY|clientX|clientY|addEventListener|DOMMouseScroll|false|else|onmousewheel|unbind|removeEventListener|extend|detail|unshift'.split('|'), 0, {}))
/*---MouseWheel Plugin END---*/

/*---Scroll Plugin START---*/
jQuery.Co3Scroll = function() { };

//Initialiserer scrollarea
//Et scrollarea vil blive pakket rundt om scrollcontent
jQuery.fn.wrapInScrollbar = function(settings) {
  var co3Scrolls = [];

  this.each(function() {
    var co3Scroll = new jQuery.Co3Scroll();
    var scrollContent = jQuery(this);
    scrollContent.css("position", "relative");

    //Create a wrapper for the scrollcontent
    var scrollarea = co3Scroll.createScrollArea(settings);
    //Wrap element in scrollarea
    scrollContent.wrap(scrollarea);
    //Henter scrollarea ud igen for at sikre at alt er blevet sat af browseren.
    scrollarea = jQuery("#" + scrollarea.attr("id"));
    //Fylder settings i Co3Scroll og binder alle events
    co3Scroll.setupCo3Scroll(settings, scrollContent, scrollarea);
    //Ligge det nye co3Scroll objekt i returnarrayet
    co3Scrolls[co3Scrolls.length] = co3Scroll;
  });
  return co3Scrolls;
};

//Starter en mousewheel scroll
jQuery.Co3Scroll.prototype.startWheelScroll = function(scrollEventObj, delta) {
  var co3Scroll = this;

  switch (scrollEventObj.axis.toLowerCase() + delta) {
    case "y-1":
      if (co3Scroll.jQueryScrollContent.outerHeight() < co3Scroll.scrollarea.height()) { return; }
      scrollEventObj.direction = "down";
      break;
    case "y1":
      if (co3Scroll.jQueryScrollContent.outerHeight() < co3Scroll.scrollarea.height()) { return; }
      scrollEventObj.direction = "up";
      break;
    case "x-1":
      if (co3Scroll.jQueryScrollContent.outerWidth() < co3Scroll.scrollarea.width()) { return; }
      scrollEventObj.direction = "right";
      break;
    case "x1":
      if (co3Scroll.jQueryScrollContent.outerWidth() < co3Scroll.scrollarea.width()) { return; }
      scrollEventObj.direction = "left";
      break;
  }
  if (!co3Scroll.scrollInInterval) {
    co3Scroll.startScroll(scrollEventObj);
    co3Scroll.mouseWheelInProgress = true;
    co3Scroll.startWheelTimeout(scrollEventObj);
  } else {
    if (co3Scroll.lastEvent !== (scrollEventObj.direction + scrollEventObj.startEvent)) {
      co3Scroll.lastEvent = scrollEventObj.direction + scrollEventObj.startEvent;
      co3Scroll.startIntervalScroll(scrollEventObj);
    }
  }
};

//Sætter en timeout for en mousewheel scroll
//Gøres for at kunne stoppe mousewheel scrollen igen.
jQuery.Co3Scroll.prototype.startWheelTimeout = function(scrollEventObj) {
  var co3Scroll = this;
  window.setTimeout(function() {
    //Tjek om der er en mousewheel scroll i kø
    //Bruges til at sikre en flydende scrollbevægelse
    if (!co3Scroll.mouseWheelInQue) {
      co3Scroll.stop(scrollEventObj);
      co3Scroll.mouseWheelInProgress = false;
    } else {
      co3Scroll.mouseWheelInQue = false;
      co3Scroll.startWheelTimeout(scrollEventObj);
    }
  }, 150);
};

//Starter en scroll bevægelse
jQuery.Co3Scroll.prototype.startScroll = function(scrollEventObj) {
  jQuery("#testDiv").append("<br>startScroll: " + scrollEventObj.direction + " - " + scrollEventObj.startEvent);
  var directionArr = this.startedScrolls[scrollEventObj.direction];
  if (directionArr !== undefined) {
    //Finde ud af om en allerede kørende event skal pauses
    for (var startEvent in directionArr) {
      var eventObject = directionArr[scrollEventObj.startEvent];
      if (!eventObject || directionArr[startEvent].intervalID !== eventObject.intervalID) {
        this.pause(directionArr[startEvent].scrollEventObj);
      }
    }
  }

  this.startedScrolls[scrollEventObj.direction] = this.startedScrolls[scrollEventObj.direction] || [];
  var co3Scroll = this;
  //Tjek om en scroll magen til allerede er igang.
  //Hvis den er skal den stoppes, før en ny kan startes
  try {
    var lastEventObj = this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent];
    if (lastEventObj.intervalID > 0) {
      this.stop(lastEventObj.scrollEventObj);
    }
  } catch (ex) { }

  //Starte en ny scroll og gemme et beskrivende object i 
  this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent] = { intervalID: setInterval(function() {
    co3Scroll.scroll(scrollEventObj);
  }, co3Scroll.intervalTime),
    scrollEventObj: scrollEventObj,
    startTime: (new Date()).getTime()
  };
};

//Starter et interval scroll
jQuery.Co3Scroll.prototype.startIntervalScroll = function(scrollEventObj, eventName) {
  //jQuery("#testDiv").append("<br>startIntervalScroll: " + scrollEventObj.direction + " - " + scrollEventObj.startEvent);
  var co3Scroll = this;
  var co3Animate = { speed: scrollEventObj.scrollSpeed * co3Scroll.scrollSpeedModifier,
    interval: scrollEventObj.interval,
    scrollNudge: scrollEventObj.scrollNudge
  };
  var endFunction = function() {
    co3Scroll.lastEvent = "";
  };
  switch (scrollEventObj.direction) {
    //y aksen       
    case "y":
      //Nedknappen
      if (eventName === "first") {
        var co3Page = this.yPage();
        co3Page = this.yPage(co3Page.currentPage + 1, co3Animate, endFunction);
        if (scrollEventObj.hideWhenNotNeeded) {
          if (co3Page.currentPage === co3Page.pages) {
            co3Scroll.hideElement(scrollEventObj.firstSelector);
          }
          co3Scroll.showElement(scrollEventObj.secondSelector);
        }
        //Opknappen
      } else {
        var co3Page = this.yPage();
        co3Page = this.yPage(co3Page.currentPage - 1, co3Animate, endFunction);
        if (scrollEventObj.hideWhenNotNeeded) {
          if (co3Page.currentPage === 1) {
            co3Scroll.hideElement(scrollEventObj.secondSelector);
          }
          co3Scroll.showElement(scrollEventObj.firstSelector);
        }
      }
      break;
    //x aksen       
    case "x":
      //Højreknappen
      if (eventName === "first") {
        var co3Page = this.xPage();
        co3Page = this.xPage(co3Page.currentPage + 1, co3Animate, endFunction);
        if (scrollEventObj.hideWhenNotNeeded) {
          if (co3Page.currentPage === co3Page.pages) {
            co3Scroll.hideElement(scrollEventObj.firstSelector);
          }
          co3Scroll.showElement(scrollEventObj.secondSelector);
        }
        //Venstreknappen
      } else {
        var co3Page = this.xPage();
        co3Page = this.xPage(co3Page.currentPage - 1, co3Animate, endFunction);
        if (scrollEventObj.hideWhenNotNeeded) {
          if (co3Page.currentPage === 1) {
            co3Scroll.hideElement(scrollEventObj.secondSelector);
          }
          co3Scroll.showElement(scrollEventObj.firstSelector);
        }
      }
      break;
  }
};

//Stopper en scroll
jQuery.Co3Scroll.prototype.stop = function(scrollEventObj) {
  jQuery("#testDiv").append("<br>stop: " + scrollEventObj.direction + " - " + scrollEventObj.startEvent);
  //Stop det interval der er blevet startet for at scrolle
  try {
    clearInterval(this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent].intervalID);
  } catch (ex) {
    //Hvis dette fejler kan vi lige så godt returnere da der så ikke er noget at stoppe.
    return;
  }
  //Nulstille intervalID'et, så man kan se at denne event er stoppet
  this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent].intervalID = 0;
  //Hvis denne event også ligger som paused scroll skal denne også nulstilles
  if (this.pausedScrolls[scrollEventObj.direction] !== undefined && this.pausedScrolls[scrollEventObj.direction][scrollEventObj.startEvent] !== undefined) {
    this.pausedScrolls[scrollEventObj.direction][scrollEventObj.startEvent].intervalID = 0;
  }
  //Tjek om der er andre pausede scrolls til denne direction
  for (var id in this.pausedScrolls[scrollEventObj.direction]) {
    if (this.pausedScrolls[scrollEventObj.direction][id].intervalID > 0) {
      //Start den første pausede event
      this.startScroll(this.pausedScrolls[scrollEventObj.direction][id].scrollEventObj);
      break;
    }
  }
};

//Pauser en scroll
//Den kan så startes senere
//Bruges til fx mouseover der bliver pauset af en mousedown på samme knap
//Når mousedown'en stoppes, skal mouseoveren startes igen.
jQuery.Co3Scroll.prototype.pause = function(scrollEventObj) {
  //jQuery("#testDiv").append("<br>pause: " + scrollEventObj.direction + " - " + scrollEventObj.startEvent);
  //Stopper denne scrollevent
  clearInterval(this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent].intervalID);
  //Sørge for at der er et array klar til eventen
  this.pausedScrolls[scrollEventObj.direction] = this.pausedScrolls[scrollEventObj.direction] || [];
  //Gemmer eventen i pausearray'et, hvor den senere kan hentes frem.
  this.pausedScrolls[scrollEventObj.direction][scrollEventObj.startEvent] = { intervalID: this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent].intervalID,
    scrollEventObj: scrollEventObj,
    startTime: (new Date()).getTime()
  };
  //Nulstille intervalID'et, så man kan se at denne scroll er stoppet
  this.startedScrolls[scrollEventObj.direction][scrollEventObj.startEvent].intervalID = 0;
};

//Udfører en enkelt scrollning
jQuery.Co3Scroll.prototype.scroll = function(scrollEventObj) {
  speed = scrollEventObj.scrollSpeed || this.speedPerPixel;
  var moveDistance = speed * this.intervalTime;
  /*--IntervalCode Start--*/
  if (this.scrollInterval) {
    //Tjek om vi er nået til intervallets max
    if (this.scrollIntervalCount >= this.scrollInterval) {
      //Stoppe scroll'en og nulstille scrollIntervalCount
      this.stop(scrollEventObj);
      this.scrollIntervalCount = 0;
      return;
    }
    //Tælle op hvor langt vi har scroll'et
    this.scrollIntervalCount += moveDistance;
    //Tjek om den nye værdi er større en intervallets max
    if (this.scrollIntervalCount > this.scrollInterval) {
      //Sætter movedistance til ikke at overskride max
      moveDistance = this.scrollIntervalCount - this.scrollInterval;
      //Stoppe scroll'en
      this.stop(scrollEventObj);
    }
  }
  /*--IntervalCode End--*/
  //Tjek hvilken retning der skal scroll'es
  //Derefter udregnes den nye gotoX og gotoY
  //Til sidst udføres scroll'ningen med en ny css værdi
  switch (scrollEventObj.direction) {
    case "down":
      var maxScroll = this.getMaxHeight();
      if (this.jQueryScrollContent.position().top === maxScroll) { return; }

      var gotoX = this.jQueryScrollContent.position().top - moveDistance;
      if (gotoX < -maxScroll) {
        gotoX = -maxScroll;
        this.stop(scrollEventObj);
      }
      this.jQueryScrollContent.css("top", gotoX);
      break;
    case "up":
      if (this.jQueryScrollContent.position().top === 0) { return; }
      var gotoX = this.jQueryScrollContent.position().top + moveDistance;
      if (gotoX > 0) {
        gotoX = 0;
        this.stop(scrollEventObj);
      }
      this.jQueryScrollContent.css("top", gotoX);
      break;
    case "right":
      var maxScroll = this.getMaxWidth();
      if (this.jQueryScrollContent.position().left === maxScroll) { return; }
      var gotoY = this.jQueryScrollContent.position().left - moveDistance;
      if (gotoY < -maxScroll) {
        gotoY = -maxScroll;
        this.stop(scrollEventObj);
      }
      this.jQueryScrollContent.css("left", gotoY);
      break;
    case "left":
      if (this.jQueryScrollContent.position().left === 0) { return; }
      var gotoY = this.jQueryScrollContent.position().left + moveDistance;
      if (gotoY > 0) {
        gotoY = 0;
        this.stop(scrollEventObj);
      }
      this.jQueryScrollContent.css("left", gotoY);
      break;
  }
};

//Løber igennem et array af scrollEventObj'er
//Opdaterer dem og sætter gang i at binde events til deres selectors
jQuery.Co3Scroll.prototype.bindEvents = function(scrollEventObjs, direction) {
  //Hvis vi ikke har et array returneres der bare
  if (!scrollEventObjs) {
    return;
  }
  co3Scroll = this;
  //Hvis eventen er en mouseWheelEvent skal den behandles specielt
  if (direction === "mouseWheelEvent") {
    for (var i = 0; i < scrollEventObjs.length; i++) {
      var scrollEventObj = scrollEventObjs[i];
      //Scrollspeed beregnes ud fra en faktor
      scrollEventObj.scrollSpeed = scrollEventObj.scrollSpeed ? scrollEventObj.scrollSpeed / 250 : co3Scroll.speedPerPixel * 3;
      //Hvis der ikke er valgt en selector bliver denne scrollarea'ets ID
      scrollEventObj.selector = scrollEventObj.selector || "#" + co3Scroll.scrollareaID;
      scrollEventObj.startEvent = "mouseWheelEvent";
      //Der bindes en event 
      this.bindEvent(scrollEventObj);
    }
    return;
  }
  for (var i = 0; i < scrollEventObjs.length; i++) {
    var scrollEventObj = scrollEventObjs[i];
    //Omregner scrollSpeed til speedperpixel
    if (scrollEventObj.scrollSpeed) {
      scrollEventObj.scrollSpeed = scrollEventObj.scrollSpeed / co3Scroll.scrollSpeedModifier;
    }
    //Sætter direction på objektet
    scrollEventObj.direction = direction;
    this.bindEvent(scrollEventObj);
  }
};

//Binder events til et enkelt scrollEventObj
jQuery.Co3Scroll.prototype.bindEvent = function(scrollEventObj) {
  co3Scroll = this;
  //Er eventen en mouseWheelEvent skal den behandles speciels
  if (scrollEventObj.startEvent === "mouseWheelEvent") {
    //Binder en mouseWheelEvent til selectoren
    //Her benyttes mouseWheel plugin'et
    jQuery(scrollEventObj.selector).mousewheel(function(event, delta) {
      //Tjek om en mouseWheelEvent allerede er igang
      if (!co3Scroll.mouseWheelInProgress) {
        //Hvis ikke en scroll er igang startes en ny
        //Delta skal omformes til enten 1 eller -1
        co3Scroll.startWheelScroll(scrollEventObj, delta > 0 ? "1" : "-1");
      } else {
        //Hvis en scroll er igang sættes denne i kø
        //Den vil blive startet når den igangværende er færdig
        co3Scroll.mouseWheelInQue = true;
      }
      //Vi ønsker ikke at default mouseWheelEvent'en skal køres i browseren
      event.preventDefault();
    });
    return;
  }

  //Hvis scrollen er sat til interval skal vi behandle events på en måde
  if (co3Scroll.scrollInInterval) {
    //Tjek om intervalknapperne skal skjules
    switch (scrollEventObj.direction) {
      case "y":
        var maxScroll = this.getMaxHeight();
        var contentPos = this.jQueryScrollContent.position().top;
        if (scrollEventObj.hideWhenNotNeeded) {
          if (contentPos <= 0) {
            jQuery(scrollEventObj.secondSelector).css("display", "none");
          } else if (contentPos >= maxScroll) {
            jQuery(scrollEventObj.firstSelector).css("display", "none");
          }
        }
        break;
      case "x":
        var maxScroll = this.getMaxWidth();
        var contentPos = this.jQueryScrollContent.position().left;
        if (scrollEventObj.hideWhenNotNeeded) {
          if (contentPos <= 0) {
            jQuery(scrollEventObj.secondSelector).css("display", "none");
          } else if (contentPos >= maxScroll) {
            jQuery(scrollEventObj.firstSelector).css("display", "none");
          }
        }
        break;
    }
    //Tjek om begge selectors er valgt før vi binder events til dem
    //Hvis ikke de begge er der vil en scroll måske kunne startes, men ikke stoppes
    if (scrollEventObj.firstSelector && scrollEventObj.secondSelector) {
      jQuery(scrollEventObj.firstSelector).bind(scrollEventObj.event, function() {
        lala = "";
        if (co3Scroll.lastEvent !== scrollEventObj.direction + scrollEventObj.event) {
          co3Scroll.lastEvent = scrollEventObj.direction + scrollEventObj.event;
          co3Scroll.startIntervalScroll(scrollEventObj, "first");
        }
      });
      jQuery(scrollEventObj.secondSelector).bind(scrollEventObj.event, function() {
        lala = "";
        if (co3Scroll.lastEvent !== scrollEventObj.direction + scrollEventObj.event) {
          co3Scroll.lastEvent = scrollEventObj.direction + scrollEventObj.event;
          co3Scroll.startIntervalScroll(scrollEventObj, "second");
        }
      });
    }
  } else {
    jQuery(scrollEventObj.selector).bind(scrollEventObj.startEvent, function() {
      if (co3Scroll.lastEvent !== scrollEventObj.direction + scrollEventObj.startEvent) {
        co3Scroll.lastEvent = scrollEventObj.direction + scrollEventObj.startEvent;
        co3Scroll.startScroll(scrollEventObj);
      }
    });
    if (!co3Scroll.scrollInInterval) {
      jQuery(scrollEventObj.selector).bind(scrollEventObj.endEvent, function() {
        if (co3Scroll.lastEvent !== scrollEventObj.direction + scrollEventObj.endEvent) {
          co3Scroll.lastEvent = scrollEventObj.direction + scrollEventObj.endEvent;

          if (scrollEventObj.startEvent !== "mousedown") {
            //Hvis vi ikke slukker en mousedown skal vi alligevel forsøge at slukke en da mouseup eventen ikke bliver registreret hvis cursoren forlader knappen.
            try {
              co3Scroll.stop(co3Scroll.startedScrolls[scrollEventObj.direction].mousedown.scrollEventObj);
            } catch (ex) { }
          }
          co3Scroll.stop(scrollEventObj);
        }
      });
    }
  }
};

jQuery.Co3Scroll.prototype.hideEventElements = function(scrollEventObjs) {
  if (scrollEventObjs) {
    for (var i = 0; i < scrollEventObjs.length; i++) {
      var scrollEventObj = scrollEventObjs[i];
      if (scrollEventObj.hideWhenNotNeeded) {
        jQuery(scrollEventObj.selector).css("display", "none");
      }
    }
  }
};

//Sætter en timeout for en længere scroll bevægelse
//Gøres for at kunne stoppe scrollen igen.
jQuery.Co3Scroll.prototype.startLongTimeout = function(scrollEventObj, milliseconds) {
  co3Scroll = this;
  window.setTimeout(function() {
    co3Scroll.stop(scrollEventObj);
    co3Scroll.unstopableScrollInProgress = false;
  }, milliseconds);
};

/*---HelperFunctions START---*/
//Creates a scrollarea to be wrapped around  the scrollcontent
//Uses the jQuery.Co3Scroll.settings to fill out attributes and styles
jQuery.Co3Scroll.prototype.createScrollArea = function(settings) {
  var scrollareaID = (new Date()).getTime();
  var scrollarea = jQuery(document.createElement('div'));
  scrollarea.css("position", "relative");
  scrollarea.css("overflow", "hidden");
  if (settings.width) {
    scrollarea.css("width", settings.width);
  }
  if (settings.height) {
    scrollarea.css("height", settings.height);
  }
  scrollarea.attr("id", scrollareaID);
  scrollarea.addClass("co3Scroll");
  if (settings.scrollWrapperClasses) {
    scrollarea.addClass(settings.scrollWrapperClasses);
  }
  return scrollarea;
};

//Fylder settings i Co3Scroll og binder alle events
jQuery.Co3Scroll.prototype.setupCo3Scroll = function(settings, scrollContent, scrollarea) {
  var co3Scroll = this;
  if (!settings.height) {
    settings.height = scrollarea.height();
  }
  if (!settings.width) {
    settings.width = scrollarea.width();
  }
  //Giv scrollcontent et ID hvis den ikke har et
  co3Scroll.scrollContentID = scrollContent.attr("id");
  if (!co3Scroll.scrollContentID || co3Scroll.scrollContentID === "") {
    co3Scroll.scrollContentID = "sc" + scrollarea.attr("id");
  }
  co3Scroll.scrollSpeedModifier = 500;
  co3Scroll.speedPerPixel = settings.scrollSpeed / co3Scroll.scrollSpeedModifier;
  co3Scroll.speedPerPixelClick = settings.scrollSpeedClick / co3Scroll.scrollSpeedModifier;
  co3Scroll.jQueryScrollContent = scrollContent;
  co3Scroll.scrollContent = scrollContent[0];
  co3Scroll.scrollarea = scrollarea;
  co3Scroll.scrollareaID = scrollarea.attr("id");
  co3Scroll.xPos = scrollContent.position().top;
  co3Scroll.yPos = scrollContent.position().left;
  co3Scroll.intervalTime = 10; //Interval i milisekunder
  co3Scroll.startedScrolls = [];
  co3Scroll.pausedScrolls = [];
  co3Scroll.lastEvent = "";
  co3Scroll.settings = settings;
  co3Scroll.scrollbarsVertical = [];
  co3Scroll.scrollbarsHorizontal = [];
  co3Scroll.scrollInInterval = settings.scrollInInterval;

  //Setup scroll events
  if (settings.height < co3Scroll.jQueryScrollContent.outerHeight()) {
    co3Scroll.bindEvents(settings.upEvents, "up");
    co3Scroll.bindEvents(settings.downEvents, "down");
    co3Scroll.bindEvents(settings.scrollInIntervalEventsY, "y");
  } else {
    if (settings.upEvents && !settings.upEvents.hideWhenNotNeeded) {
      co3Scroll.bindEvents(settings.upEvents, "up");
    } else {
      co3Scroll.hideEventElements(settings.upEvents);
    }
    if (settings.downEvents && !settings.downEvents.hideWhenNotNeeded) {
      co3Scroll.bindEvents(settings.downEvents, "down");
    } else {
      co3Scroll.hideEventElements(settings.downEvents);
    }
  }
  if (settings.width < co3Scroll.jQueryScrollContent.outerWidth()) {
    co3Scroll.bindEvents(settings.leftEvents, "left");
    co3Scroll.bindEvents(settings.rightEvents, "right");
  } else {
    if (settings.leftEvents && !settings.leftEvents.hideWhenNotNeeded) {
      co3Scroll.bindEvents(settings.leftEvents, "left");
    } else {
      co3Scroll.hideEventElements(settings.leftEvents);
    }
    if (settings.rightEvents && !settings.rightEvents.hideWhenNotNeeded) {
      co3Scroll.bindEvents(settings.rightEvents, "right");
    } else {
      co3Scroll.hideEventElements(settings.rightEvents);
    }
  }
  co3Scroll.bindEvents(settings.scrollInIntervalEventsY, "y");
  co3Scroll.bindEvents(settings.scrollInIntervalEventsX, "x");
  //Bind mousewheel events
  co3Scroll.bindEvents(settings.mouseWheelEvent, "mouseWheelEvent");
};


//Skjuler et element med en animering
jQuery.Co3Scroll.prototype.hideElement = function(content) {
  jQuery(content).animate({
    opacity: 0
  }, 500, function() {
    jQuery(this).css("display", "none");
  });
};

//Viser et element med en animering
jQuery.Co3Scroll.prototype.showElement = function(content) {
  var element = jQuery(content);
  if (element.css("display") === "none") {
    element.css("opacity", 0).css("display", "block").animate({
      opacity: 1
    }, 500, function() {
      try {
        //Fjerner filter stylen fra elementet for at IE's cleartype kan gælde igen.
        this.style.removeAttribute('filter');
      } catch (ex) { }
    });
  }
};

//Finder max scrollbredden
//Den bredde der max kan scrolles før man skal stoppe
jQuery.Co3Scroll.prototype.getMaxWidth = function() {
  return this.jQueryScrollContent.outerWidth() - this.scrollarea.width();
};

//Finder max scrollhøjden
//Den højde der max kan scrolles før man skal stoppe
jQuery.Co3Scroll.prototype.getMaxHeight = function() {
  return this.jQueryScrollContent.outerHeight() - this.scrollarea.height();
};

//Udregner nudgeHastigheden
jQuery.Co3Scroll.prototype.getScrollNudgeSpeed = function(nudgeObj) {
  var nudgePixels = nudgeObj.pixels || 0;
  var rtnSpeed = 0;
  if (nudgePixels > 0) {
    rtnSpeed = (nudgeObj.speed || 200);
  }
  return rtnSpeed;
};

/*---HelperFunctions END---*/

/*---Interface functions START---*/

//Returnerer top positionen af scrollcontent
//Hvis der sendes en top parameter med sættes denne, som den nye top
//Hvis der sendes et co3Animate-objekt med kan der vælges hvordan en animering ønskes udført 
jQuery.Co3Scroll.prototype.top = function(top, co3Animate, fn) {
  var co3Scroll = this;
  var maxScroll = this.getMaxHeight();
  var pos = -co3Scroll.jQueryScrollContent.position().top;

  if (top && top !== pos) {
    top = top <= maxScroll ? top : maxScroll;
    var speed = co3Scroll.settings.scrollSpeed;
    var nudgePlacement = -pos;
    var nudgeSpeed = 0;
    if (co3Animate) {
      speed = co3Animate.speed || speed;
      if (co3Animate.scrollNudge) {
        var nudgePixels = (co3Animate.scrollNudge.pixels || 30);
        nudgePlacement = (top < pos ? -nudgePixels : nudgePixels) - pos;
        nudgeSpeed = co3Animate.scrollNudge.speed || 200;
      }
    }

    if (top !== pos) {
      //Animere flytningen
      co3Scroll.jQueryScrollContent.animate({
        top: nudgePlacement
      }, nudgeSpeed).animate({
        top: -top
      }, speed, function() {
        if (fn) {
          fn(top, co3Scroll);
        }
      });
    }
  }

  return top;
};

//Returnerer left positionen af scrollcontent
//Hvis der sendes en left parameter med sættes denne, som den nye left
jQuery.Co3Scroll.prototype.left = function(left, co3Animate, fn) {
  var co3Scroll = this;
  var maxScroll = this.getMaxWidth();
  var pos = -co3Scroll.jQueryScrollContent.position().left;

  if (left && left !== pos) {
    left = left <= maxScroll ? left : maxScroll;
    var speed = co3Scroll.settings.scrollSpeed;
    var nudgePlacement = -pos;
    var nudgeSpeed = 0;
    if (co3Animate) {
      speed = co3Animate.speed || speed;
      if (co3Animate.scrollNudge) {
        var nudgePixels = (co3Animate.scrollNudge.pixels || 30);
        nudgePlacement = (left < pos ? -nudgePixels : nudgePixels) - pos;
        nudgeSpeed = co3Animate.scrollNudge.speed || 200;
      }
    }

    if (left !== pos) {
      //Animere flytningen
      co3Scroll.jQueryScrollContent.animate({
        left: nudgePlacement
      }, nudgeSpeed).animate({
        left: -left
      }, speed, function() {
        if (fn) {
          fn(left, co3Scroll);
        }
      });
    }
  }

  return left;
};

//Returnerer et Co3Page-object med information om hvor mange sider der er på X-aksen, og hvilken side vi befinder os på
//Animerer scrollcontent til den ønskede side
jQuery.Co3Scroll.prototype.xPage = function(pageNo, co3Animate, fn) {
  var co3Scroll = this;

  var pos = -co3Scroll.jQueryScrollContent.position().left;

  var pages = Math.ceil(co3Scroll.jQueryScrollContent.width() / co3Scroll.settings.width);
  var pageSize = co3Scroll.settings.width;
  pageNo = pageNo < 1 ? 1 : pageNo;
  pageNo = pageNo > pages ? pages : pageNo;

  var currentPage = Math.floor(pos / pageSize) + 1;
  var extraPixels = pos - (currentPage - 1) * pageSize;
  var co3Page = { pages: pages, currentPage: currentPage, extraPixels: extraPixels };

  if (pageNo && pageNo !== currentPage) {
    pageNo = pageNo <= pages ? pageNo : pages;
    var speed = co3Scroll.settings.scrollSpeed;
    var nudgePlacement = -pos;
    var nudgeSpeed = 0;
    if (co3Animate) {
      speed = co3Animate.speed || speed;
      if (co3Animate.scrollNudge) {
        var nudgePixels = (co3Animate.scrollNudge.pixels || 30);
        nudgePlacement = (pageNo < currentPage ? -nudgePixels : nudgePixels) - pos;
        nudgeSpeed = co3Animate.scrollNudge.speed || 200;
      }
    }
    co3Page.currentPage = pageNo;
    co3Page.extraPixels = 0;

    if (pageNo !== currentPage) {
      rtnPos = pageNo;
      //Animere flytningen
      co3Scroll.jQueryScrollContent.animate({
        left: nudgePlacement
      }, nudgeSpeed).animate({
        left: -((pageNo - 1) * pageSize)
      }, speed, function() {
        if (fn) {
          fn(co3Page, co3Scroll);
        }
      });
    }
  } else {
    if (fn) {
      fn(co3Page, co3Scroll);
    }
  }

  return co3Page;
};

//Returnerer et Co3Page-object med information om hvor mange sider der er på Y-aksen, og hvilken side vi befinder os på
//Animerer scrollcontent til den ønskede side
jQuery.Co3Scroll.prototype.yPage = function(pageNo, co3Animate, fn) {
  var co3Scroll = this;

  var pos = -co3Scroll.jQueryScrollContent.position().top;

  var pages = Math.ceil(co3Scroll.jQueryScrollContent.height() / co3Scroll.settings.height);
  var pageSize = co3Scroll.settings.height;
  pageNo = pageNo < 1 ? 1 : pageNo;
  pageNo = pageNo > pages ? pages : pageNo;
  var currentPage = Math.floor(pos / pageSize) + 1;
  var extraPixels = pos - (currentPage - 1) * pageSize;
  var co3Page = { pages: pages, currentPage: currentPage, extraPixels: extraPixels };

  if (pageNo && pageNo !== currentPage) {
    pageNo = pageNo <= pages ? pageNo : pages;
    var speed = co3Scroll.settings.scrollSpeed;
    var nudgePlacement = -pos;
    var nudgeSpeed = 0;
    if (co3Animate) {
      speed = co3Animate.speed || speed;
      if (co3Animate.scrollNudge) {
        var nudgePixels = (co3Animate.scrollNudge.pixels || 30);
        nudgePlacement = (pageNo < currentPage ? -nudgePixels : nudgePixels) - pos;
        nudgeSpeed = co3Animate.scrollNudge.speed || 200;
      }
    }
    co3Page.currentPage = pageNo;
    co3Page.extraPixels = 0;

    if (pageNo !== currentPage) {
      //Animere flytningen
      co3Scroll.jQueryScrollContent.animate({
        top: nudgePlacement
      }, nudgeSpeed).animate({
        top: -((pageNo - 1) * pageSize)
      }, speed, function() {
        if (fn) {
          fn(co3Page, co3Scroll);
        }
      });
    }
  } else {
    if (fn) {
      fn(co3Page, co3Scroll);
    }
  }

  return co3Page;
};


/*---Interface functions END---*/


/*---Scroll Plugin END---*/