// JavaScript Document
//const TICKER_DEBUG = true;
var TICKER_DEBUG = true;

var mcTicker = Class.create({
options: {},
mousePosition: null,
internal: {},
ready: false,
i: false,
events: {},
initialize: function(element, options) {
var self = this;

//get element
if(element.hide)
this.element = element;
else {
element = $(element);
if(!element)
throw 'ticker element-node not found!';
this.element = element;
}

//init events
if(options && options.events) {
this.events = options.events;
delete options.events;
}

this.fireEvent('beforInit');

//init options
this.options = (function() {
var o = Object.extend({
from: 'right',
onhover: 'toggle',
drag: true,
bindonmouse: false,
pp: false,
speed: 100,
append: 8,
debug: TICKER_DEBUG
}, options);

TICKER_DEBUG = (o.debug == true);

switch(o.onhover.toLowerCase()) {
case 'stop':
case 'toggle':
break;
case 'bind':
if(o.bindonmouse === true)
break;
default: o.onhover = 'none';
}

o.bind = (o.bind === true);
o.pp = (o.pp === true);
o.drag = (o.drag === true && o.onhover != 'none');
o.from = o.from.toLowerCase();

self.onDragCursor = 'e-resize';
switch(o.from) {
case 'left':
o.to = 'right';
break;
case 'right':
o.to = 'left';
break;
case 'top':
o.to = 'bottom';
self.onDragCursor = 'n-resize';
break;
case 'bottom':
o.to = 'top';
self.onDragCursor = 'n-resize';
break;
case 'top_left':
case 'bottom_left':
case 'top_right':
case 'bottom_right':
self.onDragCursor = 'move';
break;
default: o.from = 'right';
}

return o;
})();

if(this.options.bindonmouse === true) { 
this.element.style.position = 'absolute';
this.eventBind = this.mouseBinder.bindAsEventListener(this);
document.observe('mousemove', this.eventBind);

//doubleclick will stop binding element on mousepointer
document.observe('dblclick', function(event) {
self.detachMouse(event);
});
} //else 

//okay, we can handle "drag" and "bindonmouse" at the same time
if(this.options.drag === true && this.options.onhover != 'bind') {
this.eventDrag = this.textDrag.bindAsEventListener(this);

//init event "drag"
this.element.onmousedown = function() {
self.initializeTextDrag();
document.observe('mousemove', self.eventDrag);
};

this.element.onmouseup = function() {
document.stopObserving('mousemove', self.eventDrag);
self.uninitializeTextDrag();
}
}

//set events on element
if(this.options.onhover == 'bind') {
//bind element on mouse 
this.element.observe('mouseover', this.detachMouse.bindAsEventListener(this));
} 

//ticker will stop on mouseover
else if(this.options.onhover == 'stop')
this.element.observe('mouseover', this.stop.bindAsEventListener(this));

//ticker will stop and go on mouseover/out (default)
else if(this.options.onhover != 'none') {
this.element.observe('mouseover', this.stop.bindAsEventListener(this));
this.element.observe('mouseout', this.resume.bindAsEventListener(this));
}

if(TICKER_DEBUG && !$('debug'))
document.body.appendChild(new Element('span', { id: 'debug' }));

this.fireEvent('afterInit');
this.start();
},

fireEvent: function(event) {
if(typeof this.events[event] == 'function')
this.events[event](this);
},

start: function() {
if(this.ready !== true) {
this.element.style.overflow = 'hidden'; //overflow will be hidden
this.element.style.whiteSpace = 'nowrap'; //ignore overflow-breaks
this.element.style.width = ((this.element.style.width != '')
? this.element.style.width
: this.element.getWidth() + 'px'
);

//ie only hide childnodes in the "hidden-overflow" of the parent-element 
//when his position is "relative" or "absolute" (with z-index > 0)
if(Prototype.Browser.IE) 
this.element.style.position = 'relative';

var span = new Element('span');
span.update(/* we need al contents */ this.element.innerHTML);

//delete contents
this.element.innerHTML = ''; 

//set span position to "relative"
span.style.position = 'relative'; 

//update "left" and "top" in inline-css stuff
span.style.top = 0;
span.style.left = 0;

//insert element into "parent"
this.element.update(span);

//move text out of parent-element
if(this.options.from == 'left')
span.style.left = this.element.getWidth() + 'px';
else if(this.options.from == 'right')
span.style.left = (0 - span.getWidth()) + 'px';

//define ticker element
this.ticker = span;
this.ready = true;
}

this.setInterval();
this.fireEvent('afterStart');
},

stop: function(event) {
if(this.i == false)
return false;

clearInterval(this.i);
this.i = false;
},

resume: function(event) {
if(this.i !== false)
return false;

this.setInterval();
},

setInterval : function() {
var self = this;

//function ready?
if(!this.intervalFunction) {
if(['left', 'right'].indexOf(this.options.from) > -1) {
this.intervalFunction = function(dir) {
if(self.moveText_lr(dir, self.options.append) == false) {
if(self.options.pp === true) {
clearInterval(self.i);
self.options.from = self.options.to;
self.options.to = dir;
self.setInterval();
} else self.moveText_lr(dir, true);
}
}
} else if(['top', 'bottom'].indexOf(this.options.from) > -1) {
this.intervalFunction = function(dir) {
if(self.moveText_tb(dir, self.options.append) == false) {
if(self.options.pp === true) {
clearInterval(self.i);
self.options.from = self.options.to;
self.options.to = dir;
self.setInterval();
} else self.moveText_tb(dir, true);
}
}
}
}

this.i = setInterval(function() { self.intervalFunction(self.options.from); }, this.options.speed);
},

moveText_lr: function(dir, p) {
if(p === true) {
this.ticker.style.left = ((dir == 'left') 
? this.element.getWidth() + 'px'
: (0 - this.ticker.getWidth()) + 'px'
);

return;
}

if(dir == 'left') { //text moves to right
var newLeft = parseInt(this.ticker.style.left) - p;
if((newLeft + p) < (0 - this.ticker.getWidth()))
return false;
} else { //if(dir == 'right')
var newLeft = parseInt(this.ticker.style.left) + p;
if(newLeft > (this.element.getWidth() + p))
return false;
}

this.ticker.style.left = newLeft + 'px';
if(TICKER_DEBUG) $('debug').update('left:' + newLeft + 'px');
},

moveText_tb: function(dir, p) {
if(p === true) {
this.ticker.style.top = ((dir == 'top') 
? (0 - this.ticker.getHeight()) + 'px'
: this.ticker.getHeight() + 'px'
);

return;
}

if(dir == 'top') { //text moves to bottom
var newTop = parseInt(this.ticker.style.top) + p;
if(newTop > this.ticker.getHeight())
return false;
} else { //if(dir == 'bottom')
var newTop = parseInt(this.ticker.style.top) - p;
if(newTop < (0 - this.ticker.getHeight()))
return false;
}

this.ticker.style.top = newTop + 'px';
if(TICKER_DEBUG) $('debug').update('top:' + newTop + 'px');
},

detachMouse: function(event) {
if(this.element.style.position == 'absolute') {
document.stopObserving('mousemove', this.eventBind);
this.element.style.top = '';
this.element.style.left = '';
this.element.style.position = '';
} else {
this.element.style.position = 'absolute';
this.mouseBinder(event);
document.observe('mousemove', this.eventBind);
}
},

mouseBinder: function(event) { 
this.element.style.top = (Event.pointerY(event) + 10) + 'px';
this.element.style.left = (Event.pointerX(event) + 15) + 'px';
},

initializeTextDrag: function() {
this.element.style.cursor = this.onDragCursor;
},

uninitializeTextDrag: function() {
this.mousePosition = null;
this.element.style.cursor = 'auto';
},

textDrag: function(event) {
if(['left', 'right'].indexOf(this.options.from ) > -1)
this.dragText_lr(event);
else if(['top', 'bottom'].indexOf(this.options.from) > -1)
this.dragText_tb(event);
else this.dragText_all(event);

this.saveMousePosition(event);
},

saveMousePosition: function(event) {
this.mousePosition = {
left: Event.pointerX(event),
top: Event.pointerY(event)
}

return false;
},

elementInternalForceGet: function() {
var returnVal = this.element;
$A(arguments).each(function(item) {
if(returnVal[item])
returnVal = returnVal[item];
});

return returnVal;
},

//see elementInternalForceGet: cache stuff
elementInternalGet: function() { 
var key = $A(arguments).toString();
if(typeof this.internal[key] != 'undefined')
return this.internal[key];

var returnVal = this.element;
$A(arguments).each(function(item) {
if(returnVal[item])
returnVal = returnVal[item];
});

this.internal[key] = returnVal;
return returnVal;
},

dragText_all: function(event) { 
this.dragText_lr(event);
this.dragText_tb(event);
},

dragText_tb: function(event) {
if(this.mousePosition == null) 
return this.saveMousePosition(event);

//drag
if(Event.pointerY(event) > this.mousePosition.top) { //pointer go's down
var newTop = parseInt(this.ticker.style.top) + (Event.pointerY(event) - this.mousePosition.top);
if(newTop > this.element.getHeight()) {
if(TICKER_DEBUG) $('debug').update('drag:down-failed');
return;
}

if(TICKER_DEBUG) $('debug').update('drag:down');
} else { //pointer go's up
var newTop = parseInt(this.ticker.style.top) - (this.mousePosition.top - Event.pointerY(event));
if(newTop < (0 - this.element.getHeight())) {
if(TICKER_DEBUG) $('debug').update('drag:up-failed');
return;
}

if(TICKER_DEBUG) $('debug').update('drag:up');
}

this.ticker.style.top = newTop + 'px';
},

dragText_lr: function(event) {
if(this.mousePosition == null)
return this.saveMousePosition(event);

//drag
if(Event.pointerX(event) > this.mousePosition.left) { //pointer go's to right
var newLeft = parseInt(this.ticker.style.left) + (Event.pointerX(event) - this.mousePosition.left);
if(newLeft > this.element.getWidth()) {
if(TICKER_DEBUG) $('debug').update('drag:right-failed');
return;
}

if(TICKER_DEBUG) $('debug').update('drag:right');
} else { //pointer go's to left
var newLeft = parseInt(this.ticker.style.left) - (this.mousePosition.left - Event.pointerX(event));
if(newLeft < (0 - this.ticker.getWidth())) {
if(TICKER_DEBUG) $('debug').update('drag:left-failed');
return;
}

if(TICKER_DEBUG) $('debug').update('drag:left');
}

this.ticker.style.left = newLeft + 'px';
}
});
