diff options
Diffstat (limited to 'vendor/ContentFlow/contentflow_src.js')
| -rw-r--r-- | vendor/ContentFlow/contentflow_src.js | 2584 |
1 files changed, 2584 insertions, 0 deletions
diff --git a/vendor/ContentFlow/contentflow_src.js b/vendor/ContentFlow/contentflow_src.js new file mode 100644 index 0000000..b6a5968 --- /dev/null +++ b/vendor/ContentFlow/contentflow_src.js @@ -0,0 +1,2584 @@ +/* ContentFlow, version 1.0.2 + * (c) 2007 - 2010 Sebastian Kutsch + * <http://www.jacksasylum.eu/ContentFlow/> + * + * ContentFlow is distributed under the terms of the MIT license. + * (see http://www.jacksasylum.eu/ContentFlow/LICENSE) + * + *--------------------------------------------------------------------------*/ +/* + * ============================================================ + * Global configutaion and initilization object + * ============================================================ + */ +var ContentFlowGlobal = { + Flows: new Array, + AddOns: {}, + scriptName: 'contentflow.js', + scriptElement: null, + Browser: new (function () { + this.Opera = window.opera ? true : false; + this.IE = document.all && !this.Opera ? true : false; + this.IE6 = this.IE && typeof(window.XMLHttpRequest) == "undefined" ? true : false; + this.IE8 = this.IE && typeof(document.querySelectorAll) != "undefined" ? true : false; + this.IE7 = this.IE && ! this.IE6 && !this.IE8 ? true : false; + this.WebKit = /WebKit/i.test(navigator.userAgent) ? true : false, + this.iPhone = /iPhone|iPod/i.test(navigator.userAgent)? true : false; + this.Chrome = /Chrome/i.test(navigator.userAgent) ? true : false; + this.Safari = /Safari/i.test(navigator.userAgent) && !this.Chrome ? true : false; + this.Konqueror = navigator.vendor == "KDE" ? true : false; + this.Konqueror4 = this.Konqueror && /native code/.test(document.getElementsByClassName) ? true : false; + this.Gecko = !this.WebKit && navigator.product == "Gecko" ? true : false; + this.Gecko19 = this.Gecko && Array.reduce ? true : false; + })(), + + getAddOnConf: function(name) { + if(this.AddOns[name]) + return this.AddOns[name].conf; + else + return {}; + }, + + setAddOnConf: function (name, conf) { + this.AddOns[name].setConfig(conf); + }, + + getScriptElement:function (scriptName) { + var regex = new RegExp(scriptName); + var scripts = document.getElementsByTagName('script'); + for (var i=0; i<scripts.length; i++) { + if (scripts[i].src && regex.test(scripts[i].src)) + return scripts[i]; + } + return ''; + }, + + getScriptPath: function (scriptElement, scriptName) { + var regex = new RegExp(scriptName+".*"); + return scriptElement.src.replace(regex, ''); + }, + + addScript: function (path) { + if (this.Browser.IE || this.Browser.WebKit || this.Browser.Konqueror) { + document.write('<script type="text/javascript" src="'+path+'"><\/script>'); + } + else { + var script = document.createElement('script'); + script.src = path; + script.setAttribute('type', 'text/javascript'); + document.getElementsByTagName('head')[0].appendChild(script); + } + }, + + addScripts: function (basePath, filenames) { + for (var i=0; i<filename.length; i++) + this.addScript(basepath+filenames[i]); + }, + + addStylesheet: function (path) { + if (this.Browser.Gecko19) { + var link = document.createElement('link'); + link.setAttribute('rel', 'stylesheet'); + link.setAttribute('href', path); + link.setAttribute('type', 'text/css'); + link.setAttribute('media', 'screen'); + document.getElementsByTagName('head')[0].appendChild(link); + } + else { + document.write('<link rel="stylesheet" href="'+path+'" type="text/css" media="screen" />'); + } + + }, + + addStylesheets: function (basePath, filenames) { + for (var i=0; i<filename.length; i++) + this.addStylesheet(basepath+filenames[i]); + }, + + initPath: function () { + /* get / set basic values */ + this.scriptElement = this.getScriptElement(this.scriptName); + if (!this.scriptElement) { + this.scriptName = 'contentflow_src.js'; + this.scriptElement = this.getScriptElement(this.scriptName); + } + + this.BaseDir = this.getScriptPath(this.scriptElement, this.scriptName) ; + if (!this.AddOnBaseDir) this.AddOnBaseDir = this.BaseDir; + if (!this.CSSBaseDir) this.CSSBaseDir = this.BaseDir; + }, + + init: function () { + /* add default stylesheets */ + this.addStylesheet(this.CSSBaseDir+'contentflow.css'); + this.addStylesheet(this.CSSBaseDir+'mycontentflow.css'); // FF2: without adding a css-file FF2 hangs on a reload. + // I don't have the slidest idea why + // Could be timing problem + this.loadAddOns = new Array(); + /* add AddOns scripts */ + if (this.scriptElement.getAttribute('load')) { + var AddOns = this.loadAddOns = this.scriptElement.getAttribute('load').replace(/\ +/g,' ').split(' '); + for (var i=0; i<AddOns.length; i++) { + if (AddOns[i] == '') continue; + //if (AddOns[i] == 'myStyle') { + //this.addStylesheet(this.BaseDir+'mycontentflow.css'); + //continue; + //} + this.addScript(this.AddOnBaseDir+'ContentFlowAddOn_'+AddOns[i]+'.js'); + } + } + + /* ========== ContentFlow auto initialization on document load ========== + * thanks to Dean Edwards + * http://dean.edwards.name/weblog/2005/02/order-of-events/ + */ + var CFG = this; + + /* for Mozilla, Opera 9, Safari */ + if (document.addEventListener) { + /* for Safari */ + if (this.Browser.WebKit) { + var _timer = setInterval(function() { + if (/loaded|complete/.test(document.readyState)) { + clearInterval(_timer); + CFG.onloadInit(); // call the onload handler + } + }, 10); + } + else { + document.addEventListener("DOMContentLoaded", CFG.onloadInit, false); + } + } + else if (this.Browser.IE) { + document.write("<script id=__ie_cf_onload defer src=javascript:void(0)><\/script>"); + var script = document.getElementById("__ie_cf_onload"); + script.onreadystatechange = function() { + if (this.readyState == "complete") { + CFG.onloadInit(); // call the onload handler + } + }; + } + + /* for all other browsers */ + window.addEvent('load', CFG.onloadInit, false); + + /* ================================================================== */ + + }, + + onloadInit: function () { + // quit if this function has already been called + if (arguments.callee.done) return; + for (var i=0; i< ContentFlowGlobal.loadAddOns.length; i++) { + var a = ContentFlowGlobal.loadAddOns[i]; + if (!ContentFlowGlobal.AddOns[a]) { + var CFG = ContentFlowGlobal; + window.setTimeout( CFG.onloadInit, 10); + return; + } + } + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + + /* fix for mootools */ + if (window.Element && Element.implement && document.all && !window.opera) { + for (var prop in window.CFElement.prototype) { + if(!window.Element.prototype[prop]) { + var implement = {}; + implement[prop] = window.CFElement.prototype[prop]; + Element.implement(implement); + } + } + } + + /* init all manualy created flows */ + for (var i=0; i< ContentFlowGlobal.Flows.length; i++) { + ContentFlowGlobal.Flows[i].init(); + } + + /* init the rest */ + var divs = document.getElementsByTagName('div'); + DIVS: for (var i = 0; i < divs.length; i++) { + if (divs[i].className.match(/\bContentFlow\b/)) { + for (var j=0; j<ContentFlowGlobal.Flows.length; j++) { + if (divs[i] == ContentFlowGlobal.Flows[j].Container) continue DIVS; + } + var CF = new ContentFlow(divs[i],{}, false); + CF.init(); + } + } + } + +}; + +ContentFlowGlobal.initPath(); + + +/* + * ============================================================ + * ContentFlowAddOn + * ============================================================ + */ +var ContentFlowAddOn = function (name, methods, register) { + if (typeof register == "undefined" || register != false) + ContentFlowGlobal.AddOns[name] = this; + + this.name = name; + if (!methods) methods = {}; + this.methods = methods; + this.conf = {}; + if (this.methods.conf) { + this.setConfig(this.methods.conf); + delete this.methods.conf; + } + + + this.scriptpath = ContentFlowGlobal.AddOnBaseDir; + if (methods.init) { + var init = methods.init.bind(this); + init(this); + } +}; + +ContentFlowAddOn.prototype = { + Browser: ContentFlowGlobal.Browser, + + addScript: ContentFlowGlobal.addScript, + addScripts: ContentFlowGlobal.addScripts, + + addStylesheet: function (path) { + if (!path) + path = this.scriptpath+'ContentFlowAddOn_'+this.name+'.css'; + ContentFlowGlobal.addStylesheet(path); + }, + addStylesheets: ContentFlowGlobal.addStylesheets, + + setConfig: function (conf) { + for (var c in conf) { + this.conf[c] = conf[c]; + } + }, + + _init: function (flow) { + if (this.methods.ContentFlowConf) { + flow.setConfig(this.methods.ContentFlowConf); + } + } + + +}; + + + +/* + * ============================================================ + * ContentFlowGUIElement + * ============================================================ + */ + +var ContentFlowGUIElement = function (CFobj, element) { + element.setDimensions = function () { + this.dimensions = this.getDimensions(); + this.center = {x: this.dimensions.width/2, y:this.dimensions.height/2}; + this.position = this.findPos(); + }; + element.addObserver = function (eventName, method) { + var m = this.eventMethod = method.bind(CFobj); + this.observedEvent = eventName; + this.addEvent(eventName, m, false); + }; + + element.makeDraggable = function (onDrag, beforeDrag, afterDrag) { + + this.stopDrag = function(event) { + if (!event) var event = window.event; + if (this.Browser.iPhone) { + window.removeEvent('touchemove', onDrag, false); + if (!this.ontochmove) { + var t = event.target; + if (t.firstChild) t = t.firstChild; + var e = document.createEvent('MouseEvents'); + e.initEvent('click', true, true); + t.dispatchEvent(e); + } + } + else { + window.removeEvent('mousemove', onDrag, false); + } + afterDrag(event); + }.bind(this); + + this.initDrag = function (event) { + if (!event) var event = window.event; + var e = event; + if (event.touches) e = event.touches[0]; + + this.mouseX = e.clientX; + this.mouseY = e.clientY; + + beforeDrag(event); + + }.bind(this); + + this.startDrag = function (event) { + if (!event) var event = window.event; + + var stopDrag = this.stopDrag; + + if (this.Browser.iPhone) { + var s = this; + s.ontouchmove = false + window.addEvent('touchmove', function (e) { + s.ontouchmove = true; + onDrag(e); + }, false); + event.preventDefault(); + window.addEvent('touchend', stopDrag, false); + } + else { + window.addEvent('mousemove', onDrag, false); + window.addEvent('mouseup', stopDrag, false); + } + if(event.preventDefault) { event.preventDefault() } + + }.bind(this); + + var startDrag = this.startDrag; + if (this.Browser.iPhone) { + this.addEventListener('touchstart', startDrag, false); + } + else { + this.addEvent('mousedown', startDrag, false); + } + + }; + + element.Browser = ContentFlowGlobal.Browser; + $CF(element).setDimensions(); + return element; +}; + + +/* + * ============================================================ + * ContentFlowItem + * ============================================================ + */ +var ContentFlowItem = function (CFobj, element, index) { + this.CFobj = CFobj; + this._activeElement = CFobj.conf.activeElement; + this.pre = null; + this.next = null; + /* + * ==================== item click events ==================== + * handles the click event on an active and none active item + */ + + this.clickItem = function (event) { + if(!event) var event = window.event; + var el = event.target ? event.target : event.srcElement; + var index = el.itemIndex ? el.itemIndex : el.parentNode.itemIndex; + var item = this.items[index]; + if (this._activeItem == item) { + this.conf.onclickActiveItem(item); + } + else { + if (this.conf.onclickInactiveItem(item) != false ) this.moveToIndex(index); + } + }.bind(CFobj), + + this.setIndex = function (index) { + this.index = index; + this.element.itemIndex = index; + }; + this.getIndex = function () { + return this.index; + }; + + + /* generate deault HTML structure if item is an image */ + if ($CF(element).nodeName == "IMG") { + var el = document.createElement('div'); + el.className = "item"; + + var cont = element.parentNode.replaceChild( el, element); + cont.className = "content"; + el.appendChild(cont); + + if (element.title) { + var cap = document.createElement('div'); + cap.className = "caption"; + cap.innerHTML = element.title; + el.appendChild(cap); + } + element = el; + } + + /* create item object */ + this.element = $CF(element); + this.item = element; + if (typeof index != "undefined") this.setIndex(index); + this.content = this.element.getChildrenByClassName('content')[0]; + this.caption = this.element.getChildrenByClassName('caption')[0]; + this.label = this.element.getChildrenByClassName('label')[0]; + + /* if content is image set properties */ + if (this.content.nodeName == "IMG") { + CFobj._imagesToLoad++; + + var foobar = function () { + CFobj._imagesToLoad--; + this.image = this.content; + this.setImageFormat(this.image); + if ( CFobj.conf.reflectionHeight > 0) { + this.addReflection(); + } + this.initClick(); + CFobj._addItemCueProcess(true); + }.bind(this); + + if (this.content.complete && this.content.width > 0) + window.setTimeout(foobar, 100); + else if (this.Browser.IE && !this.content.onload) { + var self = this; + var t = window.setInterval( function () { + if (self.content.complete && self.content.width > 0) { + window.clearInterval(t); + foobar(); + } + }, 10); + } + else + this.content.onload = window.setTimeout(foobar, 100); + } + else { + this.initClick(); + CFobj._addItemCueProcess(true); + } + +}; + +ContentFlowItem.prototype = { + + Browser: ContentFlowGlobal.Browser, + + makeActive: function () { + this.element.addClassName('active'); + this.CFobj.conf.onMakeActive(this); + }, + + makeInactive: function () { + this.element.removeClassName('active'); + this.CFobj.conf.onMakeInactive(this); + }, + + initClick: function () { + var cItem = this.clickItem; + this[this._activeElement].addEvent('click', cItem, false); + }, + + setImageFormat: function (img) { + if (this.Browser.IE6 || this.Browser.IE7) img.style.width = "auto"; + img.origProportion = img.width / img.height; + img.setAttribute('origProportion', img.width / img.height); + if (this.Browser.IE6 || this.Browser.IE7) img.style.width = ""; + //img.origWidth = img.width; + //img.origHeight = img.height; + if (img.origProportion <= 1) + img.addClassName('portray'); + else + img.addClassName('landscape'); + }, + + /* + * add reflection to item + */ + addReflection: function() { + var CFobj = this.CFobj; + var reflection; + var image = this.content; + + + if (this.Browser.IE) { + var filterString = 'progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)'; + if (CFobj._reflectionColorRGB) { + // transparent gradient + if (CFobj.conf.reflectionColor == "transparent") { + var RefImg = reflection = this.reflection = document.createElement('img'); + reflection.src = image.src; + } + // color gradient + else { + reflection = this.reflection = document.createElement('div'); + var RefImg = document.createElement('img'); + RefImg.src = image.src; + reflection.width = RefImg.width; + reflection.height = RefImg.height; + RefImg.style.width = '100%'; + RefImg.style.height = '100%'; + var color = CFobj._reflectionColorRGB; + reflection.style.backgroundColor = '#'+color.hR+color.hG+color.hB; + reflection.appendChild(RefImg); + } + filterString += ' progid:DXImageTransform.Microsoft.Alpha(opacity=0, finishOpacity=50, style=1, finishX=0, startY='+CFobj.conf.reflectionHeight*100+' finishY=0)'; + } else { + var RefImg = reflection = this.reflection = document.createElement('img'); + reflection.src = image.src; + } + // crop image (streches and crops (clip on default dimensions), original proportions will be restored through CSS) + filterString += ' progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22='+1/CFobj.conf.reflectionHeight+')'; + + if (ContentFlowGlobal.Browser.IE6) { + if (image.src.match(/\.png$/) ) { + image.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image.src+"', sizingMethod=scale )"; + image.filterString = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image.src+"', sizingMethod=scale )"; + filterString += " progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+image.src+"', sizingMethod=scale )"; + image.origSrc = image.src; + image.src='img/blank.gif'; + RefImg.src="img/blank.gif"; + } + } + + reflection.filterString = filterString; + RefImg.style.filter = filterString; + + } else { + if (CFobj._reflectionWithinImage) + var canvas = this.canvas = $CF(document.createElement('canvas')); + else + var canvas = reflection = this.reflection = document.createElement('canvas'); + + if (canvas.getContext) { + if (CFobj._reflectionWithinImage) { + for (var i=0; i <image.attributes.length; i++) { + canvas.setAttributeNode(image.attributes[i].cloneNode(true)); + } + } + + var context = canvas.getContext("2d"); + + /* calc image size */ + var max = CFobj.maxHeight; + var size = CFobj._scaleImageSize(this, {width: max, height: max }, max) + var width = size.width; + var height = size.height; + + // overwrite default height and width + if (CFobj._reflectionWithinImage) { + canvas.width = width; + canvas.height = height; + this.setImageFormat(canvas); + canvas.height = height * (1 + CFobj.conf.reflectionHeight + CFobj.conf.reflectionGap); + + } + else { + canvas.width = width; + canvas.height = height * CFobj.conf.reflectionHeight; + } + + context.save(); /* save default context */ + + /* draw image into canvas */ + if (CFobj._reflectionWithinImage) { + context.drawImage(image, 0, 0, width, height); + } + + /* mirror image by transformation of context and image drawing */ + if (CFobj._reflectionWithinImage) { + var contextHeight = height * ( 1 + CFobj.conf.reflectionGap/2) * 2; + } + else { + var contextHeight = image.height; + } + // -1 for FF 1.5 + contextHeight -= 1; + + context.translate(0, contextHeight); + context.scale(1, -1); + /* draw reflection image into canvas */ + context.drawImage(image, 0, 0, width, height); + + /* restore default context for simpler further canvas manupulation */ + context.restore(); + + if (CFobj._reflectionColorRGB) { + var gradient = context.createLinearGradient(0, 0, 0, canvas.height); + + var alpha = [0, 0.5, 1]; + if (CFobj._reflectionColor == "transparent") { + context.globalCompositeOperation = "destination-in"; + alpha = [1, 0.5, 0]; + } + + var red = CFobj._reflectionColorRGB.iR; + var green = CFobj._reflectionColorRGB.iG; + var blue = CFobj._reflectionColorRGB.iB; + if (CFobj._reflectionWithinImage) { + gradient.addColorStop(0, 'rgba('+red+','+green+','+blue+','+alpha[0]+')'); + gradient.addColorStop(height/canvas.height, 'rgba('+red+','+green+','+blue+','+alpha[0]+')'); + gradient.addColorStop(height/canvas.height, 'rgba('+red+','+green+','+blue+','+alpha[1]+')'); + } + else { + gradient.addColorStop(0, 'rgba('+red+','+green+','+blue+','+alpha[1]+')'); + } + gradient.addColorStop(1, 'rgba('+red+','+green+','+blue+','+alpha[2]+')'); + + context.fillStyle = gradient; + context.fillRect(0, 0, canvas.width, canvas.height); + + } + + if (CFobj._reflectionWithinImage) { + image.parentNode.replaceChild(canvas, image); + this.content = canvas; + this.origContent = canvas; + delete this.image;// = true; + + } + + } else { + CFobj._reflectionWithinImage = false; + delete this.reflection; + } + + } + if (reflection) { + reflection.className = "reflection"; + this.element.appendChild(reflection); + + /* be shure that caption is last child */ + if (this.caption) this.element.appendChild(this.caption); + } + + } + + + }; + +/* + * ============================================================ + * ContentFlow + * ============================================================ + */ +var ContentFlow = function (container, config) { + + if (container) { + ContentFlowGlobal.Flows.push(this); + this.Container = container; + this._userConf = config?config:{}; + this.conf = {}; + this._loadedAddOns = new Array(); + } else { + throw ('ContentFlow ERROR: No flow container node or id given'); + } + +}; + +ContentFlow.prototype = { + _imagesToLoad: 0, + _activeItem: 0, + _currentPosition: 0, + _targetPosition: 0, + _stepLock: false, + _millisecondsPerStep: 40, + _reflectionWithinImage: true, + Browser: ContentFlowGlobal.Browser, + + _defaultConf: { + /* pre conf */ + useAddOns: 'all', // all, none, [AddOn1, ... , AddOnN] + + biggestItemPos: 0, + loadingTimeout: 30000, //milliseconds + activeElement: 'content', // item or content + + maxItemHeight: 0, + scaleFactor: 1, + scaleFactorLandscape: 1.33, + scaleFactorPortrait: 1.0, + fixItemSize: false, + relativeItemPosition: "top center", // align top/above, bottom/below, left, right, center of position coordinate + + circularFlow: true, + verticalFlow: false, + visibleItems: -1, + endOpacity: 1, + startItem: "center", + scrollInFrom: "pre", + + flowSpeedFactor: 1.0, + flowDragFriction: 1.0, + scrollWheelSpeed: 1.0, + keys: { + 13: function () { this.conf.onclickActiveItem(this._activeItem) }, + 37: function () { this.moveTo('pre') }, + 38: function () { this.moveTo('visibleNext') }, + 39: function () { this.moveTo('next') }, + 40: function () { this.moveTo('visiblePre') } + }, + + reflectionColor: "transparent", // none, transparent or hex RGB CSS style #RRGGBB + reflectionHeight: 0.5, // float (relative to original image height) + reflectionGap: 0.0, + + /* ==================== actions ==================== */ + + onInit: function () {}, + + onclickInactiveItem: function (item) {}, + + onclickActiveItem: function (item) { + var url, target; + + if (url = item.content.getAttribute('href')) { + target = item.content.getAttribute('target'); + } + else if (url = item.element.getAttribute('href')) { + target = item.element.getAttribute('target'); + } + else if (url = item.content.getAttribute('src')) { + target = item.content.getAttribute('target'); + } + + if (url) { + if (target) + window.open(url, target).focus(); + else + window.location.href = url; + } + }, + + onMakeInactive: function (item) {}, + + onMakeActive: function (item) {}, + + onReachTarget: function(item) {}, + + onMoveTo: function(item) {}, + + //onDrawItem: function(item, relativePosition, relativePositionNormed, side, size) {}, + onDrawItem: function(item) {}, + + onclickPreButton: function (event) { + this.moveToIndex('pre'); + return Event.stop(event); + }, + + onclickNextButton: function (event) { + this.moveToIndex('next'); + return Event.stop(event); + }, + + /* ==================== calculations ==================== */ + + calcStepWidth: function(diff) { + var vI = this.conf.visibleItems; + var items = this.items.length; + items = items == 0 ? 1 : items; + if (Math.abs(diff) > vI) { + if (diff > 0) { + var stepwidth = diff - vI; + } else { + var stepwidth = diff + vI; + } + } else if (vI >= this.items.length) { + var stepwidth = diff / items; + } else { + var stepwidth = diff * ( vI / items); + //var stepwidth = diff/absDiff * Math.max(diff * diff,Math.min(absDiff,0.3)) * ( vI / this.items.length); + //var stepwidth = this.flowSpeedFactor * diff / this.visibleItems; + //var stepwidth = this.flowSpeedFactor * diff * ( this.visibleItems / this.items.length) + //var stepwidth = this.flowSpeedFactor * diff / this._millisecondsPerStep * 2; // const. speed + } + return stepwidth; + }, + + calcSize: function (item) { + var rP = item.relativePosition; + //var rPN = relativePositionNormed; + //var vI = this.conf.visibleItems; + + var h = 1/(Math.abs(rP)+1); + var w = h; + return {width: w, height: h}; + }, + + calcCoordinates: function (item) { + var rP = item.relativePosition; + //var rPN = item.relativePositionNormed; + var vI = this.conf.visibleItems; + + var f = 1 - 1/Math.exp( Math.abs(rP)*0.75); + var x = item.side * vI/(vI+1)* f; + var y = 1; + + return {x: x, y: y}; + }, + + /* + calcRelativeItemPosition: function (item) { + var x = 0; + var y = -1; + return {x: x, y: y}; + }, + */ + + calcZIndex: function (item) { + return -Math.abs(item.relativePositionNormed); + }, + + calcFontSize: function (item) { + return item.size.height; + }, + + calcOpacity: function (item) { + return Math.max(1 - ((1 - this.conf.endOpacity ) * Math.sqrt(Math.abs(item.relativePositionNormed))), this.conf.endOpacity); + } + }, + + /* ---------- end of defaultConf ---------- */ + + + /* + * ==================== index helper methods ==================== + */ + + /* + * checks if index is within the index range of the this.items array + * returns a value that is within this range + */ + _checkIndex: function (index) { + index = Math.max(index, 0); + index = Math.min(index, this.itemsLastIndex); + return index; + }, + + /* + * sets the object property itemsLastIndex + */ + _setLastIndex: function () { + this.itemsLastIndex = this.items.length - 1; + }, + + /* +*/ + _getItemByIndex: function (index) { + return this.items[this._checkIndex(index)]; + }, + + _getItemByPosition: function (position) { + return this._getItemByIndex(this._getIndexByPosition(position)); + }, + + /* returns the position of an item-index relative to current position */ + _getPositionByIndex: function(index) { + if (!this.conf.circularFlow) return this._checkIndex(index); + var cI = this._getIndexByPosition(this._currentPosition); + var dI = index - cI; + if (Math.abs(dI) > dI+this.items.length) + dI += this.items.length; + else if (Math.abs(dI) > (Math.abs(dI-this.items.length))) + dI -= this.items.length; + + return this._currentPosition + dI; + + }, + + /* returns the index an item at position p would have */ + _getIndexByPosition: function (position) { + if (position < 0) var mod = 0; + else var mod = 1; + + var I = (Math.round(position) + mod) % this.items.length; + if (I>0) I -= mod; + else if(I<0) I += this.items.length - mod; + else if(position<0) I = 0; + else I = this.items.length - 1; + + return I; + }, + + _getIndexByKeyWord: function (keyword, relativeTo, check) { + if (relativeTo) + var index = relativeTo; + else if (this._activeItem) + var index = this._activeItem.index; + else + var index = 0; + + if (isNaN(keyword)) { + switch (keyword) { + case "first": + case "start": + index = 0; + break; + case "last": + case "end": + index = this.itemsLastIndex; + break; + case "middle": + case "center": + index = Math.round(this.itemsLastIndex/2); + break; + case "right": + case "next": + index += 1; + break; + case "left": + case "pre": + case "previous": + index -= 1; + break; + case 'visible': + case 'visiblePre': + case 'visibleLeft': + index -= this.conf.visibleItems; + break; + case 'visibleNext': + case 'visibleRight': + index += this.conf.visibleItems; + break; + default: + index = index; + } + } + else { + index = keyword; + } + if (check != false) + index = this._checkIndex(index); + + return index; + }, + + + _setCaptionLabel: function (index) { + if(this.Position && !this.Slider.locked) + this.Position.setLabel(index); + this._setGlobalCaption(); + }, + + + /* + * ==================== public methods ==================== + */ + getAddOnConf: function(name) { + return ContentFlowGlobal.getAddOnConf(name); + }, + + setAddOnConf: function(name, conf) { + ContentFlowGlobal.setAddOnConf(name, conf); + }, + + + /* + * calls _init() if ContentFlow has not been initialized before + * needed if ContentFlow is not automatically initialized on window.load + */ + init: function () { + if(this.isInit) return; + this._init(); + }, + + /* + * parses configuration object and initializes configuration values + */ + setConfig: function(config) { + if (!config) return; + var dC = this._defaultConf; + for (var option in config) { + if (dC[option] == "undefined" ) continue; + switch (option) { + case "scrollInFrom": + case "startItem": + if (typeof(config[option]) == "number" || typeof(config[option]) == "string") { + //this["_"+option] = config[option]; + this.conf[option] = config[option]; + } + break; + default: + if (typeof(dC[option] == config[option])) { + //this["_"+option] = config[option]; + if (typeof config[option] == "function") { + this.conf[option] = config[option].bind(this); + } + else { + this.conf[option] = config[option]; + } + } + } + } + switch (this.conf.reflectionColor) { + case this.conf.reflectionColor.search(/#[0-9a-fA-F]{6}/)>= 0?this.conf.reflectionColor:this.conf.reflectionColor+"x": + this._reflectionColorRGB = { + hR: this.conf.reflectionColor.slice(1,3), + hG: this.conf.reflectionColor.slice(3,5), + hB: this.conf.reflectionColor.slice(5,7), + iR: parseInt(this.conf.reflectionColor.slice(1,3), 16), + iG: parseInt(this.conf.reflectionColor.slice(3,5), 16), + iB: parseInt(this.conf.reflectionColor.slice(5,7), 16) + }; + break; + case "none": + case "transparent": + default: + this._reflectionColor = "transparent"; + this._reflectionColorRGB = { + hR: 0, hG: 0, hB:0, + iR: 0, iG: 0, iB:0 + }; + break; + } + if (this.items) { + if (this.conf.visibleItems < 0) + this.conf.visibleItems = Math.round(Math.sqrt(this.items.length)); + this.conf.visibleItems = Math.min(this.conf.visibleItems, this.items.length - 1); + } + + if (this.conf.relativeItemPosition) { + var calcRP = { + x: { + left: function(size) { return -1 }, + center: function(size) { return 0 }, + right: function(size) { return 1 } + }, + y: { + top: function(size) { return -1 }, + center: function(size) { return 0 }, + bottom: function(size) { return 1 } + } + }; + + var iP = this.conf.relativeItemPosition; + iP = iP.replace(/above/,"top").replace(/below/,"bottom"); + var x, y = null; + x = iP.match(/left|right/); + y = iP.match(/top|bottom/); + c = iP.match(/center/); + if (!x) { + if (c) x = "center"; + else x = "center"; + } + if (!y) { + if (c) y = "center"; + else y = "top"; + } + var calcX = calcRP.x[x]; + var calcY = calcRP.y[y]; + this.conf.calcRelativeItemPosition = function (item) { + var x = calcX(item.size); + var y = calcY(item.size); + return {x: x, y: y}; + }; + this.conf.relativeItemPosition = null; + } + + if (this._reflectionType && this._reflectionType != "clientside") { + this.conf.reflectionHeight = 0; + } + + }, + + getItem: function (index) { + return this.items[this._checkIndex(Math.round(index))]; + }, + + /* + * returns the index number of the active item + */ + getActiveItem: function() { + return this._activeItem; + }, + + /* + * returns the number of items the flow contains + */ + getNumberOfItems: function () { + return this.items.length; + }, + + /* + * reinitializes sizes. + * called on window.resize + */ + resize: function () { + this._initSizes(); + this._initStep(); + }, + + /* + * scrolls flow to item i + */ + moveToPosition: function (p, holdPos) { + if (!this.conf.circularFlow) p = this._checkIndex(p); + this._targetPosition = p; + this.conf.onMoveTo(this._getItemByPosition(p)); + this._initStep(false, holdPos); + }, + moveToIndex: function (index) { + this._targetPosition = Math.round(this._getPositionByIndex(this._getIndexByKeyWord(index, this._activeItem.index, !this.conf.circularFlow))); + this.conf.onMoveTo(this._getItemByPosition(this._targetPosition)); + this._initStep(); + }, + moveToItem: function (item) { + var i; + if (item.itemIndex) i = item.itemIndex; + else i = item.index; + this.moveToIndex(i); + }, + moveTo: function (i) { + if (typeof i == "object") this.moveToItem(i); + else if (isNaN(i) || (i == Math.floor(i) && i < this.items.length) ) this.moveToIndex(i); + else this.moveToPosition(i); + }, + + /* + * initializes item and adds it at index position + */ + _addItemCue: [], + _addItemCueProcess: function (deleteFirst) { + var c = this._addItemCue; + if (deleteFirst == true) + c.shift(); + if (c.length > 0 && ! c[0].p) { + c[0].p = true; + var self = this; + var t = c.length > 5 ? 1 : 40; + window.setTimeout(function () { self._addItem(c[0].el, c[0].i)}, t) ; + } + }, + addItem: function(el, index) { + this._addItemCue.push({ el: el, i: index, p: false}); + if (this._addItemCue.length == 1) + this._addItemCueProcess(); + }, + + _addItem: function(el, index) { + if (typeof index == "string") { + switch (index) { + case "first": + case "start": + index = 0; + break; + case "last": + case "end": + index = isNaN(this.itemsLastIndex) ? 0 : this.itemsLastIndex; + index += 1; + break; + default: + index = this._getIndexByKeyWord(index); + } + } + + index = Math.max(index, 0); + index = Math.min(index, this.itemsLastIndex + 1); + index = isNaN(index) ? 0 : index; + + this.Flow.appendChild(el); + + /* init item after insertion. that way it's part of the document and all styles are applied */ + var item = new ContentFlowItem(this, el, index); + if (this.items.length == 0 ) { + this.resize(); + if (this.conf.circularFlow) { + item.pre = item; + item.next = item; + } + } + else { + if (index == this.itemsLastIndex + 1) { + item.pre = this.items[this.itemsLastIndex]; + item.next = item.pre.next; + } + else { + item.next = this.items[index]; + item.pre = item.next.pre; + } + if (item.pre) item.pre.next = item; + if (item.next) item.next.pre = item; + } + this.items.splice(index,0, item); + + /* adjust item indices */ + for (var i = index; i < this.items.length; i++) { + this.items[i].setIndex(i); + } + this._setLastIndex(); + + if (this.conf.origVisibleItems < 0) { + this.conf.visibleItems = Math.round(Math.sqrt(this.items.length)); + } + this.conf.visibleItems = Math.min(this.conf.visibleItems, this.items.length - 1); + + /* adjust targetItem, currentPos so that current view does not change*/ + if (Math.round(this._getPositionByIndex(index)) <= Math.round(this._targetPosition)) { + this._targetPosition++; + if (!this.conf.circularFlow) + this._targetPosition = Math.min(this._targetPosition, this.itemsLastIndex); + } + if (this._getPositionByIndex(index) <= this._currentPosition) { + this._currentPosition++; + if (!this.conf.circularFlow) + this._currentPosition = Math.min(this._currentPosition, this.itemsLastIndex); + } + + // avoid display errors (wrong sizing) + var CF = this; + window.setTimeout(function () { + if(CF.items.length == 1 ) { + CF._currentPosition = -0.01; + CF._targetPosition = 0; + CF.resize(); + } + else { + CF._initStep(); + } + }, 100); + + return index; + + }, + + /* + * removes item at index position, cleans it up and returns it + */ + rmItem: function(index) { + if (index == "undefined") index = this._activeItem.index; + index = this._getIndexByKeyWord(index); + if (!this.items[index]) return null; + + var item = this.items[index]; + + if (item.pre) item.pre.next = item.next; + if (item.next) item.next.pre = item.pre; + this.items.splice(index,1); + + /* adjust item indices */ + for (var i = index ; i < this.items.length; i++) { + this.items[i].setIndex(i); + } + this._setLastIndex(); + + /* adjust targetItem, currentPos and activeItem so that current view does not change*/ + if (Math.round(this._getPositionByIndex(index)) < Math.round(this._targetPosition)) { + this._targetPosition--; + if (!this.conf.circularFlow) + this._targetPosition = this._checkIndex(this._targetPosition); + } + if (this._getPositionByIndex(index) < this._currentPosition) { + this._currentPosition--; + if (!this.conf.circularFlow) + this._currentPosition = this._checkIndex(this._currentPosition); + } + this._activeItem = this._getItemByPosition(this._currentPosition); + + /* remove item from DOM tree, take the next step and return removed item */ + var removedItem = item.element.parentNode.removeChild(item.element); + // avoid display errors (wrong sizing) + var CF = this; + window.setTimeout(function () { CF._initStep() }, 10); + return removedItem; + + }, + + + /* + * ==================== initialization ==================== + */ + + + /* -------------------- main init -------------------- */ + _init: function () { + + if (typeof(this.Container) == 'string') { // no node + var container = document.getElementById(this.Container); + if (container) { + this.Container = container; + } else { + throw ('ContentFlow ERROR: No element with id \''+this.Container+'\' found!'); + return; + } + } + + /* ---------- reserve CSS namespace */ + + $CF(this.Container).addClassName('ContentFlow'); + + /* ---------- detect GUI elements */ + var flow = $CF(this.Container).getChildrenByClassName('flow')[0]; + if (!flow) { + throw ('ContentFlow ERROR: No element with class\'flow\' found!'); + return; + } + this.Flow = new ContentFlowGUIElement(this, flow); + + var scrollbar = this.Container.getChildrenByClassName('scrollbar')[0]; + if (scrollbar) { + this.Scrollbar = new ContentFlowGUIElement(this, scrollbar); + var slider = this.Scrollbar.getChildrenByClassName('slider')[0]; + if (slider) { + this.Slider = new ContentFlowGUIElement(this, slider); + var position = this.Slider.getChildrenByClassName('position')[0]; + if (position) { + this.Position = new ContentFlowGUIElement(this, position); + } + } + + } + + /* ---------- init configuration */ + this.setConfig(this._defaultConf); + this._initAddOns(); /* init AddOns */ + this.setConfig(this._userConf); + + this._initSizes(); // ...... + + + /* ---------- init item lists ---------- */ + var items = this.Flow.getChildrenByClassName('item'); + + this.items = new Array(); + for (var i=0; i<items.length; i++) { + var item = this.items[i] = new ContentFlowItem(this, items[i], i); + if (i > 0) { + item.pre = this.items[i-1]; + item.pre.next = item; + } + } + this._setLastIndex(); + if (this.conf.circularFlow && this.items.length > 0) { + var s = this.items[0]; + s.pre = this.items[this.items.length-1]; + s.pre.next = s; + } + + /* ---------- init GUI */ + this._initGUI(); + + /* ---------- init start parameters ---------- */ + if (this._activeElement != "content") + this._activeElement = "element"; + + this.conf.origVisibleItems = this.conf.visibleItems; + if (this.conf.visibleItems < 0) { + this.conf.visibleItems = Math.round(Math.sqrt(this.items.length)); + } + this.conf.visibleItems = Math.min(this.conf.visibleItems, this.items.length - 1); + + this._targetPosition = this._getIndexByKeyWord(this.conf.startItem, 0); + + var index = this._getIndexByKeyWord(this.conf.scrollInFrom, this._targetPosition); + switch (this.conf.scrollInFrom) { + case "next": + case "right": + index -= 0.5; + break; + case "pre": + case "previous": + case "left": + index += 0.5; + break; + } + this._currentPosition = index; + + + /* ---------- wait till all images are loaded or + * grace time is up to show all and take the first step + */ + var now = new Date(); + var cf = this; + var timer = window.setInterval ( + function() { + if ( cf._imagesToLoad == 0 || new Date() - now > cf._loadingTimeout ) { + clearInterval(timer); + + cf._activeItem = cf.getItem(cf._currentPosition); + if (cf._activeItem) { + cf._activeItem.makeActive(); + cf._setCaptionLabel(cf._activeItem.index); + } + + cf.Flow.style.visibility = "visible"; // show flow after images are loaded + if (cf.loadIndicator) cf.loadIndicator.style.display = "none"; + if (cf.Scrollbar) cf.Scrollbar.style.visibility = "visible"; + + cf.resize(); + for (var i=0; i < cf._loadedAddOns.length; i++) { + var a = ContentFlowGlobal.AddOns[cf._loadedAddOns[i]]; + if (a.methods.afterContentFlowInit) + a.methods.afterContentFlowInit(cf); + } + cf.conf.onInit(); + } + }, 10 + ); + + this.isInit = true; + + }, + + /* ---------- init AddOns ---------- */ + _initAddOns: function () { + + // get an array of names of all AddOns that should be used + var loadAddOns = []; + if (this._userConf.useAddOns) { + if (typeof this._userConf.useAddOns == "string") { + loadAddOns = this._userConf.useAddOns.split(" "); + } + else if (typeof this._userConf.useAddOns == "array") { + loadAddOns = this._userConf.useAddOns; + } + } + else if (this.Container.getAttribute("useAddOns")) { + loadAddOns = this.Container.getAttribute("useAddOns").split(" "); + } + else { + loadAddOns = this.conf.useAddOns.split(' '); + } + + + // check the names for keywords + for (var i=0; i<loadAddOns.length; i++) { + if (loadAddOns[i] == "none") { + loadAddOns = new Array(); + break; + } + else if (loadAddOns[i] == "all") { + loadAddOns = new Array(); + for (var AddOn in ContentFlowGlobal.AddOns) + loadAddOns.push(AddOn); + break; + } + } + + // init all AddOns that should be used and exist + for (var i=0; i<loadAddOns.length; i++) { + var AddOn = ContentFlowGlobal.AddOns[loadAddOns[i]]; + if (AddOn) { + this._loadedAddOns.push(loadAddOns[i]); + AddOn._init(this); + this.Container.addClassName('ContentFlowAddOn_'+AddOn.name); + if (AddOn.methods.onloadInit) + AddOn.methods.onloadInit(this); + } + } + + }, + + + _initGUI: function () { + + // resize + //if (!this.Browser.iPhone) { + var resize = this.resize.bind(this); + window.addEvent('resize', resize, false); + //} + //else { + //var g = this; + //window.addEvent('resize', function () { + //g._initSizes(); + //g._initStep(); + //} , false); + //} + + // pre and next buttons + var divs = this.Container.getElementsByTagName('div'); + for (var i = 0; i < divs.length; i++) { + if ($CF(divs[i]).hasClassName('preButton')) { + var pre = divs[i]; + var mt = this.conf.onclickPreButton; + pre.addEvent('click', mt, false); + } + else if (divs[i].hasClassName('nextButton')) { + var next = divs[i]; + var mt = this.conf.onclickNextButton; + next.addEvent('click', mt, false); + } + } + + // Container object + // mousewheel + if (this.conf.scrollWheelSpeed != 0) { + var wheel = this._wheel.bind(this); + if(window.addEventListener) this.Container.addEventListener('DOMMouseScroll', wheel, false); + this.Container.onmousewheel = wheel; + } + + // key strokes + var key = this._keyStroke.bind(this); + if (this.conf.keys && !this.Browser.iPhone) { + if (document.addEventListener) { + if (!this.Browser.Opera) { + var mouseoverCheck = document.createElement('div'); + mouseoverCheck.addClassName('mouseoverCheckElement'); + this.Container.appendChild(mouseoverCheck); + + if (this.Browser.WebKit) { + document.body.addEvent('keydown', function (event) { + if (mouseoverCheck.offsetLeft > 0) key(event) ; + }); + } else { + window.addEvent('keydown', function (event) { + if (mouseoverCheck.offsetLeft > 0) key(event) ; + }); + } + } + else { + this.Container.addEvent('keydown', key); + } + } + else { + this.Container.onkeydown = key; + } + } + + + // Flow object + if (this.conf.flowDragFriction > 0) { + var onDrag = function (event) { + var e = event; + if (event.touches) e = event.touches[0]; + var mouseX = e.clientX; + var mouseY = e.clientY; + + if (this.conf.verticalFlow) { + var dist = mouseY - this.Flow.mouseY; // px / or px per sec because _dragFlow wil be called in shorter intervalls if draged fast + var dim = this.Flow.dimensions.height; + } + else { + var dist = mouseX - this.Flow.mouseX; // px / or px per sec because _dragFlow wil be called in shorter intervalls if draged fast + var dim = this.Flow.dimensions.width; + } + var itemDist = (dist / dim )* (2*this.conf.visibleItems +1); // items + var target = this._currentPosition - itemDist * 2*this.conf.visibleItems / this.conf.flowDragFriction ; + + this.Flow.mouseX = mouseX; + this.Flow.mouseY = mouseY; + + this.moveToPosition(target, true); + }.bind(this); + + var beforeDrag = function () {}; + + var afterDrag = function (event) { + var t = Math.round(this._targetPosition); + if (Math.abs( t - this._currentPosition) > 0.001 ) + this.moveToPosition(t); + }.bind(this); + + + this.Flow.makeDraggable(onDrag, beforeDrag, afterDrag); + } + + // Scrollbar Object + if (this.Scrollbar) { + var click = function(event) { + if (!event) var event = window.event; + + if (!this.Scrollbar.clickLocked) { + var mouseX = event.clientX; + var positionOnScrollbar = mouseX - this.Scrollbar.position.left; + var targetIndex = Math.round(positionOnScrollbar/this.Scrollbar.dimensions.width * this.itemsLastIndex); + this.moveToIndex(targetIndex); + } + else + this.Scrollbar.clickLocked = false; + }.bind(this); + this.Scrollbar.addObserver('click', click); + } + + // Slider Object + if (this.Slider) { + + if (this.Browser.IE6) { + var virtualSlider = document.createElement('div'); + virtualSlider.className = 'virtualSlider'; + this.Slider.appendChild(virtualSlider); + } + + // position slider on scrollbar + this.Slider.setPosition = function (relPos) { + relPos = relPos - Math.floor(relPos) + this._getIndexByPosition(Math.floor(relPos)); + if (Math.round(relPos) < 0) + relPos = this.itemsLastIndex; + else if (relPos <= 0) + relPos = 0; + else if (Math.round(relPos) > this.itemsLastIndex) + relPos = 0; + else if (relPos >= this.itemsLastIndex) + relPos = this.itemsLastIndex; + + + if (this.items.length > 1) { + var sPos = (relPos / this.itemsLastIndex)* this.Scrollbar.dimensions.width; + } else { + var sPos = 0.5 * this.Scrollbar.dimensions.width; + } + this.Slider.style.left = sPos - this.Slider.center.x+ "px"; + this.Slider.style.top = this.Scrollbar.center.y - this.Slider.center.y +"px"; + + }.bind(this); + + // make slider draggable + var beforeDrag = function (event) { + this.Scrollbar.clickLocked = true; + }.bind(this); + + var onDrag = function (event) { + var e = event; + if (event.touches) e = event.touches[0]; + var selectedIndex = this._checkIndex((e.clientX - this.Scrollbar.position.left) / this.Scrollbar.dimensions.width * this.itemsLastIndex); + this._targetPosition = this._getPositionByIndex(selectedIndex); + this.Slider.setPosition(selectedIndex); + if (this.Position) this.Position.setLabel(selectedIndex); + this._initStep(true, true); + }.bind(this); + + var afterDrag = function (event) { + this._targetPosition = Math.round(this._targetPosition); + this.conf.onMoveTo(this._getItemByPosition(this._targetPosition)); + this._initStep(true); + }.bind(this); + + this.Slider.makeDraggable(onDrag, beforeDrag, afterDrag); + } + + + // Position object + if (this.Position) { + this.Position.setLabel = function (index) { + index = this._checkIndex(Math.round(index)); + if (this.items && this.items[index].label) + this.Position.innerHTML = this.items[index].label.innerHTML; + else + this.Position.innerHTML = index + 1; + }.bind(this); + } + + + this.globalCaption = this.Container.getChildrenByClassName('globalCaption')[0]; + this.loadIndicator = this.Container.getChildrenByClassName('loadIndicator')[0]; + }, + + /* ---------- init element sizes ---------- */ + _initSizes: function (x) { + //if (this.Browser.Konqueror4 && x != true) { + //var t = this; + //window.setTimeout( function () { t._initSizes(true) }, 0); + //return; + //} + + // sets this.maxHeight + this._initMaxHeight(); + + var scrollbarHeight = this._initScrollbarSize(); + + // reduce maxHeit if container has a fixed height + if (!this.conf.verticalFlow && this.Container.style.height && this.Container.style.height != "auto") + this.maxHeight -= scrollbarHeight; + + if (!this._activeItem) return; + + var mFS = this._findBiggestItem(); + + var pF = this.Flow.findPos(); + + /* set height / width of flow */ + if (this.conf.verticalFlow) { + this.Flow.style.width = mFS.width.width+"px"; + this.Flow.style.height =3* mFS.width.width * (1 + this.conf.reflectionHeight + this.conf.reflectionGap) + "px"; + } else { + this.Flow.style.height = mFS.height.height +(mFS.height.top - pF.top)+"px"; + } + + /* remove gap */ + var s = this.conf.verticalFlow ? mFS.width.width : mFS.height.height; + var cH = s /(1 + this.conf.reflectionHeight + this.conf.reflectionGap); + this.Flow.style.marginBottom = - (s - cH)+ "px"; + + this.Flow.dimensions = this.Flow.getDimensions(); + + if (!this.Browser.IE6) { + if (this.conf.verticalFlow && this.Container.clientWidth < this.Flow.dimensions.width) { + //this.Container.style.width = this.Flow.dimensions.width+"px"; + } + else if (this.Container.clientHeight < this.Flow.dimensions.height) { + this.Container.style.height = this.Flow.dimensions.height+"px"; + } + } + + if (this.conf.verticalFlow) { + this.Flow.center = {x: this.Flow.dimensions.height/2, y:mFS.width.width/2}; + } else { + this.Flow.center = {x: this.Flow.dimensions.width/2, y:mFS.height.height/2}; + } + + }, + + /* -------------------------------------------------------------------------------- */ + + _initScrollbarSize: function () { + var SB; + var SL; + var PO; + if (SB = this.Scrollbar) { + SB.setDimensions(); + var scrollbarHeight = SB.dimensions.height; + + if (SL = this.Slider) { + SL.setDimensions(); + scrollbarHeight += SL.dimensions.height; + + if (PO = this.Position) { + + var oldLabel = PO.innerHTML; + var maxH = maxW = 0; + PO.style.width = "auto"; + + if (this.items) { + for (var i=0; i < this.items.length; i++) { + var item = this.items[i]; + if (item.label) { + PO.innerHTML = item.label.innerHTML; + } + else { + PO.innerHTML = item.index; + } + var h = PO.clientHeight; + var w = PO.clientWidth; + if ( h > maxH) maxH = h; + if ( w > maxW) maxW = w; + } + } + else { + PO.innerHTML = " "; + maxH = PO.clientHeight; + maxW = PO.clientWidth; + } + + PO.innerHTML = oldLabel; + + PO.setDimensions(); + + PO.style.width = maxW +"px"; + PO.style.left = (SL.dimensions.width - maxW)/2 + "px"; + + var extraSpace = PO.position.top - SL.position.top; + if (extraSpace > 0) { + extraSpace += -SB.dimensions.height + maxH; + SB.style.marginBottom = extraSpace + "px"; + } + else { + extraSpace *= -1; + SB.style.marginTop = extraSpace + "px"; + } + scrollbarHeight += extraSpace; + } + } + } + else { + scrollbarHeight = 0; + } + + return scrollbarHeight; + + }, + + /* -------------------------------------------------------------------------------- */ + + _initMaxHeight: function () { + + if (this.conf.verticalFlow) { + var proportion = screen.width/screen.height; + var Csd = this.Container.style.width; + var Cdim = this.Container.clientWidth; + var Fsd = this.Flow.style.width; + var Fdim = this.Flow.clientWidth; + var Fdim_o = this.Flow.clientHeight; + } else { + var proportion = screen.height/screen.width; + var Csd = this.Container.style.height; + var Cdim = this.Container.clientHeight; + var Fsd = this.Flow.style.height; + var Fdim = this.Flow.clientHeight; + var Fdim_o = this.Flow.clientWidth; + } + + // set height of container and flow + if (this.ContainerOldDim) + Csd = this.ContainerOldDim; + if (this.FlowOldDim) + Fsd = this.FlowOldDim; + + this.ContainerOldDim = "auto"; + this.FlowOldDim = "auto"; + + + /* calc maxHeight */ + if (this.conf.maxItemHeight <= 0) { + + this.maxHeight = Fdim_o / 3 * proportion/1 * this.conf.scaleFactor; // divided by 3 because of left/center/right, yes it's a magic number + + if (this.conf.verticalFlow && (this.maxHeight == 0 || this.maxHeight > Fdim)) { + this.maxHeight = Fdim; + } + + if (Csd && Csd != "auto") { + var gap = this.conf.verticalFlow ? 0 : this.conf.reflectionGap; + var rH = this.conf.verticalFlow ? 0 : this.conf.reflectionHeight; + this.maxHeight = Cdim/ (this.conf.scaleFactor* (1 + rH + gap)); + this.ContainerOldDim = Csd; + } + else if (Fsd && Fsd != "auto") { + var gap = this.conf.verticalFlow ? 0 : this.conf.reflectionGap; + this.maxHeight = Fdim / (this.conf.scaleFactor* (1 + this.conf.reflectionHeight + gap)); + this.FlowOldDim = Fsd; + } + } + else { + this.maxHeight = this.conf.maxItemHeight; + } + }, + + /* -------------------------------------------------------------------------------- */ + + _findBiggestItem: function () { + + var currentItem = this._activeItem; + + var itemP = currentItem.pre; + var itemN = currentItem.next; + var mFS = maxFlowSize = { + width: { width: 0, left: 0, height:0, top: 0, item: null, rI: 0 }, + height: { width: 0, left: 0, height:0, top: 0, item: null, rI: 0 } + } + + + var checkMax = function (item, rI) { + var el = item.element; + el.style.display = "block"; + var p = el.findPos(); + var h = el.clientHeight; + var w = el.clientWidth; + if (h + p.top >= mFS.height.height + mFS.height.top) { + mFS.height.height = h; + mFS.height.top = p.top; + mFS.height.item = item; + mFS.height.rI = rI; + } + if (w + p.left >= mFS.width.width + mFS.width.left) { + mFS.width.width = w; + mFS.width.left = p.left; + mFS.width.item = item; + mFS.width.rI = rI; + } + el.style.display = "none"; + } + + var ocp = this._currentPosition; + this._currentPosition = this.conf.visibleItems+1; + + // find the position with highest y-value + for (var i=-this.conf.visibleItems; i <= this.conf.visibleItems; i++) { + currentItem.element.style.display = "none"; + this._positionItem(currentItem, i); + checkMax(currentItem, i); + } + + // find the biggest item + var index = mFS.height.rI; + for (var i=0; i < this.items.length; i++) { + var item = this.items[i]; + item.element.style.display = "none"; + this._positionItem(item, index); + checkMax(item, index); + } + + this._currentPosition = ocp; + + return mFS + }, + + + + /* + * ==================== Key strok ==================== + */ + + /* + * handles keystroke events + */ + _keyStroke: function(event) { + if(!event) var event = window.event; + + if (event.which) { + var keyCode = event.which; + } else if (event.keyCode) { + var keyCode = event.keyCode; + } + + if (this.conf.keys[keyCode]) { + this.conf.keys[keyCode].bind(this)(); + return Event.stop(event); + } + else { + return true; + } + }, + + /* + * ==================== mouse wheel ==================== + * Event handler for mouse wheel event + * http://adomas.org/javascript-mouse-wheel/ + */ + + _wheel: function (event) { + if (!event) var event = window.event; // MS + + var delta = 0; + if (event.wheelDelta) { + delta = event.wheelDelta/120; + } else if (event.detail) { + delta = -event.detail/3; + } + + if (delta) { + var target = this._targetPosition ; + if (delta < 0 ) { + target += (1 * this.conf.scrollWheelSpeed); + } else { + target -= (1 * this.conf.scrollWheelSpeed); + } + this.moveToPosition(Math.round(target)); + } + + return Event.stop(event); + }, + + + /* + * ==================== set global Caption ==================== + */ + _setGlobalCaption: function () { + if (this.globalCaption) { + this.globalCaption.innerHTML = ''; + if(this._activeItem && this._activeItem.caption) + this.globalCaption.appendChild(this._activeItem.caption.cloneNode(true)); + } + }, + + /* + * ==================== move items ==================== + */ + + /* + * intend to make a step + */ + _initStep: function (holdSlider, holdPos) { + if (this.Slider) { + if(holdSlider) { + this.Slider.locked = true; + } else { + this.Slider.locked = false; + } + } + this._holdPos = holdPos == true ? true : false; + if (!this._stepLock) { + this._stepLock = true; + this._step(); + } + }, + + /* + * make a step + */ + _step: function () { + + var diff = this._targetPosition - this._currentPosition; + var absDiff = Math.abs(diff); + if ( absDiff > 0.001) { // till activeItem is nearly at position 0 + + this._currentPosition += this.conf.flowSpeedFactor * this.conf.calcStepWidth(diff, absDiff, this.items.length, this.conf.visibleItems); + + var AI = this.items[(this._getIndexByPosition(this._currentPosition))]; + + if (AI && AI != this._activeItem) { + if (this._activeItem) this._activeItem.makeInactive(); + this._activeItem = AI; + this._activeItem.makeActive(); + this._setCaptionLabel(this._activeItem.index); + if (Math.abs(this._targetPosition - this._currentPosition) <= 0.5 ) this.conf.onReachTarget(this._activeItem); + } + + this._positionItems(); + + var st = this._step.bind(this); + window.setTimeout(st,this._millisecondsPerStep); + + } else if (!this._holdPos) { + if (this.Slider) this.Slider.locked = false; + this._currentPosition = Math.round(this._currentPosition); + if(this.Position && !this.Slider.locked && this._activeItem) { + this._setCaptionLabel(this._activeItem.index); + } + this._positionItems(); + this._stepLock = false; + } else { + this._stepLock = false; + } + + if (this.Slider && !this.Slider.locked) { + this.Slider.setPosition(this._currentPosition); + } + }, + + + +/* ------------------------------------------------------------------------------------------------------ */ + + /* + * position items + */ + _positionItems: function () { + + if (this._lastStart) { + var item = this._lastStart; + while (item) { + item.element.style.display="none"; + item = item.next; + if (item == this._lastStart) break; + if (item && item.pre == this._lastEnd) break; + } + } + else { + this._lastStart = this._activeItem; + } + + if (!this._activeItem) return; + var currentItem = this._activeItem; + var itemP = currentItem.pre; + var itemN = currentItem.next; + + this._positionItem(currentItem, 0); + for (var i=1; i <= this.conf.visibleItems && 2*i < this.items.length ; i++) { + if (itemP) { + this._positionItem(itemP, -i); + this._lastStart = itemP; + itemP = itemP.pre; + } + if (itemN) { + this._positionItem(itemN, i); + this._lastEnd = itemN; + itemN = itemN.next; + } + } + + }, + + _positionItem: function (item, relativeIndex) { + + var conf = this.conf; + var vF = conf.verticalFlow; + + var els = item.element.style; + //els.display =" none"; + //if (els.display != "none") return; + + /* Index and position relative to activeItem */ + var p = item.position = this._currentPosition + relativeIndex; + var relativePosition = item.relativePosition = Math.round(p) - this._currentPosition; + var relativePositionNormed = item.relativePositionNormed = conf.visibleItems > 0 ? relativePosition/conf.visibleItems : 0; + var side = relativePosition < 0 ? -1 : 1; + side *= relativePosition == 0 ? 0 : 1; + item.side = side; + + var size = conf.calcSize(item); + size.height = Math.max(size.height, 0); + size.width = Math.max(size.width, 0); + if (item.content.origProportion) size = this._scaleImageSize(item, size); + item.size = size; + + var coords = item.coordinates = conf.calcCoordinates (item); + var relItemPos = item.relativeItemPosition = conf.calcRelativeItemPosition(item); + var zIndex = item.zIndex = conf.calcZIndex (item); + var fontSize = item.fontSize = conf.calcFontSize (item); + var opacity = item.opacity = conf.calcOpacity(item); + + size.height *= this.maxHeight; + size.width *= this.maxHeight; + + /* set position */ + var sA = vF ? size.height : size.width; + var sB = vF ? size.width : size.height; + var pX = this.Flow.center.x * ( 1 + coords.x ) + (relItemPos.x - 1) * sA/2; + var pY = this.maxHeight/2 * ( 1 + coords.y ) + (relItemPos.y - 1 )* sB/2; + els.left = (vF ? pY : pX)+"px"; + els.top = (vF ? pX : pY)+"px"; + + this._setItemSize(item, size); + + /* set opacity */ + if (conf.endOpacity != 1) { + this._setItemOpacity(item); + } + + /* set font size */ + if (!this.Browser.IE) els.fontSize = (fontSize * 100) +"%"; + + /* set z-index */ + els.zIndex = 32768 + Math.round(zIndex * this.items.length); // just for FF + + conf.onDrawItem(item); + + els.visibility = "visible"; + els.display = "block"; + }, + + _scaleImageSize: function (item, size, max) { + var sFL = this.conf.scaleFactorLandscape; + var sFP = this.conf.scaleFactorPortrait; + var vF = this.conf.verticalFlow; + var prop = item.content.origProportion; + var width = size.width; + var height = size.height; + var c = item.content; + + if (vF) { + if (prop <= 1) { + if (sFL != "max" && sFL != 1) { + height *= sFL; + width = Math.min(height * prop, max ? max : 1 ); + } + height = width / prop; + } + else if (prop > 1) { + if (sFP == "max") { + height = max ? max : 1; + } + else if (sFP != 1) { + width *= sFP; + height = Math.min(width/prop, max ? max : 1) + } + else { + height = width / prop; + } + width = height * prop; + } + } + else { + if (prop > 1) { + if (sFL != "max" && sFL != 1) { + width *= sFL; + height = Math.min(width / prop, max ? max : 1); + } + width = height * prop; + } + else if (prop <= 1) { + if (sFP == "max") { + width = max ? max : 1; + } + else if (sFP != 1) { + height *= sFP; + width = Math.min(height*prop, max ? max : 1); + } + else { + width = height * prop; + } + height = width / prop; + } + } + + height = isNaN(height) ? 0 : height; + width = isNaN(width) ? 0 : width; + + if (!max && this.conf.fixItemSize) { + + var propS = size.width / size.height; + + var max = Math.max(size.width, size.height); + var s = this._scaleImageSize(item, {width: max, height: max}, max); + + if (propS < 1) { + height = s.height/size.height; + width = height * prop / propS; + } + else { + width = s.width/size.width; + height = width / prop * propS; + } + + var h = height * 100; + var w = width * 100; + var mL= (1 - width)/2 * 100; + var mT= ( 1 - height ) / propS * 100 * (vF ? 0.5 : 1 ); + c.style.height = h+"%"; + if (item.reflection) item.reflection.style.height = h*this.conf.reflectionHeight+"%"; + c.style.width = w+"%"; + if (item.reflection) item.reflection.style.width = w+"%"; + c.style.marginLeft = mL+"%"; + if (item.reflection) item.reflection.style.marginLeft = mL+"%"; + c.style.marginTop = mT+"%"; + + item.element.style.overflow = "hidden"; + + return size; + } + else { + return {width: width, height: height}; + } + + }, + + _setItemSize: (function () { + if (ContentFlowGlobal.Browser.IE) { + var _setItemSize = function (item, size) { + if (!this.conf.fixItemSize) { + item.content.style.height = size.height+"px"; + } + else if (ContentFlowGlobal.Browser.IE6) { + var h = parseInt(item.content.style.height)/100; + item.content.style.height = size.height*h+"px"; + var mT = parseInt(item.content.style.marginTop)/100; + item.content.style.marginTop = size.height*mT+"px"; + } + if (item.reflection) { + var h = parseInt(item.content.style.height); + item.reflection.style.height = h*this.conf.reflectionHeight+"px"; + item.reflection.style.marginTop = h * this.conf.reflectionGap + "px"; + } + item.element.style.width = size.width +"px"; + item.element.style.height = size.height*(1+this.conf.reflectionHeight+this.conf.reflectionGap)+"px"; + } + } + else { + var _setItemSize = function (item, size) { + if (item.reflection) { + item.element.style.height = size.height*(1+this.conf.reflectionHeight + this.conf.reflectionGap) +"px"; + item.reflection.style.marginTop = size.height * this.conf.reflectionGap + "px"; + } + else if (this._reflectionWithinImage) { + item.element.style.height = size.height*(1+this.conf.reflectionHeight + this.conf.reflectionGap) +"px"; + } + else { + item.element.style.height = size.height +"px"; + } + item.element.style.width = size.width +"px"; + } + } + return _setItemSize; + + })(), + + _setItemOpacity: (function () { + if (ContentFlowGlobal.Browser.IE6) { + var _setItemOpacity = function (item) { + if (item.content.origSrc && item.content.origSrc.match(/\.png$/) ) { + var s = item.content.src; + item.content.src = item.content.origSrc; + item.content.style.filter = item.content.filterString+" progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")"; + item.content.src = s; + } + else { + item.content.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")"; + } + if (item.reflection) item.reflection.style.filter = item.reflection.filterString+"progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")"; + } + } + else if (ContentFlowGlobal.Browser.IE) { + var _setItemOpacity = function (item) { item.element.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(opacity="+item.opacity+")"; } + } + else { + var _setItemOpacity = function (item) { item.element.style.opacity = item.opacity; } + } + return _setItemOpacity; + })() + + +}; + + +/* ==================== extendig javascript/DOM objects ==================== */ + +/* + * adds bind method to Function class + * http://www.digital-web.com/articles/scope_in_javascript/ + */ + +if (!Function.bind) { + Function.prototype.bind = function(obj) { + var method = this; + return function () { + return method.apply(obj, arguments); + }; + }; +} + + +/* + * extending Math object + */ +if (!Math.erf2) { + // error function (http://en.wikipedia.org/wiki/Error_function), implemented as erf(x)^2 + Math.erf2 = function (x) { + var a = - (8*(Math.PI -3)/(3*Math.PI*(Math.PI -4))); + var x2 = x*x; + var f = 1 - Math.pow(Math.E, -x2 * (4/Math.PI + a*x2)/(1+a*x2)); + return f; + }; +} + +if (!Math._2PI05) { + Math._2PI05 = Math.sqrt(2*Math.PI); +} + +if (!Math.normDist) { + // normal distribution + Math.normDist = function (x, sig, mu) { + if (!sig) var sig = 1; + if (!mu) var mu = 0; + if (!x) var x = - mu; + return 1/(sig * Math._2PI05) * Math.pow(Math.E, - (x-mu)*(x-mu)/(2*sig*sig) ); + }; +} + +if (!Math.normedNormDist) { + Math.normedNormDist = function (x, sig, mu) { + return this.normDist(x, sig, mu)/this.normDist(mu, sig, mu); + }; +} + +if (!Math.exp) { + Math.exp = function(x) { + return Math.pow(Math.E, x); + }; +} + +if (!Math.ln) { + Math.ln = Math.log; +} + +if (!Math.log2) { + Math.log2 = function (x) { + return Math.log(x)/Math.LN2; + }; +} + +if (!Math.log10) { + Math.log10 = function (x) { + return Math.log(x)/Math.LN10; + }; +} + +if (!Math.logerithm) { + Math.logerithm = function (x, b) { + if (!b || b == Math.E) + return Math.log(x); + else if (b == 2) + return Math.log2(x); + else if (b == 10) + return Math.log10(x); + else + return Math.log(x)/Math.log(b); + }; +} + + +/* + * extending Event object + */ +if (!Event) var Event = {}; + +if (!Event.stop) { + Event.stop = function (event) { + event.cancelBubble = true; + if (event.preventDefault) event.preventDefault(); + if (event.stopPropagation) event.stopPropagation(); + return false; + }; +} + +/* + * extending Element object + */ +if (document.all && !window.opera) { + window.$CF = function (el) { + if (typeof el == "string") { + return window.$CF(document.getElementById(el)); + } + else { + if (CFElement.prototype.extend && el && !el.extend) CFElement.prototype.extend(el); + } + return el; + }; +} else { + window.$CF = function (el) { + return el; + }; +} + +if (!window.HTMLElement) { + CFElement = {}; + CFElement.prototype = {}; + CFElement.prototype.extend = function (el) { + for (var method in this) { + if (!el[method]) el[method] = this[method]; + } + }; +} +else { + CFElement = window.HTMLElement; +} + + +/* + * Thanks to Peter-Paul Koch + * http://www.quirksmode.org/js/findpos.html + */ +if (!CFElement.findPos) { + CFElement.prototype.findPos = function() { + var obj = this; + var curleft = curtop = 0; + try { + if (obj.offsetParent) { + curleft = obj.offsetLeft; + curtop = obj.offsetTop; + while (obj = obj.offsetParent) { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } + } + } + catch (ex) {} + return {left:curleft, top:curtop}; + }; +} + +if (!CFElement.getDimensions) { + CFElement.prototype.getDimensions = function() { + return {width: this.clientWidth, height: this.clientHeight}; + }; +} + +/* + * checks if an element has the class className + */ +if (!CFElement.hasClassName) { + CFElement.prototype.hasClassName = function(className) { + return (new RegExp('\\b'+className+'\\b').test(this.className)); + }; +} + +/* + * adds the class className to the element + */ +if (!CFElement.addClassName) { + CFElement.prototype.addClassName = function(className) { + if(!this.hasClassName(className)) { + this.className += (this.className ? ' ':'') + className ; + } + }; +} + +/* + * removes the class className from the element el + */ +if (!CFElement.removeClassName) { + CFElement.prototype.removeClassName = function(className) { + this.className = this.className.replace(new RegExp('\\b'+className+'\\b'), '').replace(/\s\s/g,' '); + }; +} + +/* + * removes or adds the class className from/to the element el + * depending if the element has the class className or not. + */ +if (!CFElement.toggleClassName) { + CFElement.prototype.toggleClassName = function(className) { + if(this.hasClassName(className)) { + this.removeClassName(className); + } else { + this.addClassName(className); + } + }; +} + +/* + * returns all children of element el, which have the class className + */ +if (!CFElement.getChildrenByClassName) { + CFElement.prototype.getChildrenByClassName = function(className) { + var children = new Array(); + for (var i=0; i < this.childNodes.length; i++) { + var c = this.childNodes[i]; + if (c.nodeType == 1 && $CF(c).hasClassName(className)) { + children.push(c); + } + } + return children; + }; +} + +/* + * Browser independent event handling method. + * adds the eventListener eventName to element el and attaches the function method to it. + */ +if (!CFElement.addEvent) { + CFElement.prototype.addEvent = function(eventName, method, capture) { + if (this.addEventListener) + this.addEventListener(eventName, method, capture); + else + this.attachEvent('on'+eventName, method); + }; +} + +/* + * Browser independent event handling method. + * removes the eventListener eventName with the attached function method from element el. + */ +if (!CFElement.removeEvent) { + CFElement.prototype.removeEvent = function(eventName, method, capture) { + if (this.removeEventListener) + this.removeEventListener(eventName, method, capture); + else + this.detachEvent('on'+eventName, method); + }; +} + +/* + * Browser independent event handling method. + * adds the eventListener eventName to element el and attaches the function method to it. + */ +if (!window.addEvent) { + window.addEvent = function(eventName, method, capture) { + if (this.addEventListener) { + this.addEventListener(eventName, method, capture); + } else { + if (eventName != 'load' && eventName != 'resize') + document.attachEvent('on'+eventName, method); + else + this.attachEvent('on'+eventName, method); + } + }; +} + +/* + * Browser independent event handling method. + * removes the eventListener eventName with the attached function method from element el. + */ +if (!window.removeEvent) { + window.removeEvent = function(eventName, method, capture) { + if (this.removeEventListener) { + this.removeEventListener(eventName, method, capture); + } else { + if (eventName != 'load' && eventName != 'resize') + document.detachEvent('on'+eventName, method); + else + this.detachEvent('on'+eventName, method); + } + }; +} + +/* ==================== start it all up ==================== */ +ContentFlowGlobal.init(); + |
