/* ----------------------------------------------------------------- Script: MooFlow.js v.0.2dev 2008-04-12 Copyright: Copyright (c) 2007 Tobias Wetzel (ToBSn), License: MIT-style license ChangeLog: Added { Reflection via JS Load Images via JSON Load Images form HTML-Soure with Filter onClickView Callback - returns a object obj{'coordinates', 'src','alt','...'} all image attributes and parent a href, rel and target } Changed { Class Initialization Improved Speed-Up } Fixed { Slider inside click blocked key input set fullscreen / useWindowResize } Probs: Safari 1/2 canvas must be added to body before can paint the reflection :( Tested: Safari 3 / Safari 2(no reflection) Firefox Opera 9 IE 6 ----------------------------------------------------------------- */ var SliderEx = new Class({ Extends: Slider, set: function(step){ this.step = step.limit(0, this.options.steps); this.fireEvent('onTick', this.toPosition(this.step)); return this; }, clickedElement: function(event){ var dir = this.range < 0 ? -1 : 1; var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half; position = position.limit(-this.options.offset, this.full -this.options.offset); this.step = Math.round(this.min + dir * this.toStep(position)); this.checkStep(); this.fireEvent('onTick', position); } }); Fx.TweenEx = new Class({ Extends: Fx.Tween, render: function(element, property, value){ this.fireEvent('onMotionChange', value[0].value); element.setStyle(property, this.serve(value, this.options.unit)); } }); Element.implement({ reflect: function(arg){ var i = new Element('img').setProperty('src', arg.src); if (Browser.Engine.trident) { i.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity=30, style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+arg.height*0.3+')'; i.setStyles({'width':'100%', 'height':'100%'}); return new Element('div').adopt(i); } else { var can = new Element('canvas').setProperties({'width':arg.width, 'height':arg.height}); if (can.getContext && !Browser.Engine.webkit419 ) { var ctx = can.getContext("2d"); ctx.save(); ctx.translate(0,arg.height-1); ctx.scale(1,-1); ctx.drawImage(i, 0, 0, arg.width, arg.height); ctx.restore(); ctx.globalCompositeOperation = "destination-out"; ctx.fillStyle = '#000'; ctx.fillRect(0, arg.height*0.5, arg.width, arg.height); var gra = ctx.createLinearGradient(0, 0, 0, arg.height*0.5); gra.addColorStop(1, "rgba(255, 255, 255, 1.0)"); gra.addColorStop(0, "rgba(255, 255, 255, "+(1-0.3)+")"); ctx.fillStyle = gra; ctx.fillRect(0, 0, arg.width, arg.height); } return can; } } }); var MooFlow = new Class({ Implements: [Events, Options], options: { onStart: Class.empty, onComplete: Class.empty, onCancel: Class.empty, onClickView: Class.empty, onAutoPlay: Class.empty, onAutoStop: Class.empty, reflection: 0.5, heightRatio: 0.6, startIndex: 0, interval: 3000, factor: 115, bgColor: '#000', stylePath: 'MooFlow.css', useCaption: false, useResize: false, useSlider: false, useWindowResize: false, useMouseWheel: false, useKeyInput: false, useViewer: false }, initialize: function(element, options){ this.MooFlow = element; this.setOptions(options); this.foc = 150; this.index = this.options.startIndex; this.factor = this.options.factor; this.isFull = false; this.isAutoPlay = false; this.isLoading = false; this.MooFlow.addClass('mf').setStyles({ 'overflow':'hidden', 'background-color':this.options.bgColor, 'visibility':'hidden', 'position':'relative' }); if(!$chk($('mfCSS'))){new Asset.css(this.options.stylePath,{id:'mfCSS'});} if(this.options.useWindowResize){window.addEvent('resize', this.update.bind(this, true));} if(this.options.useMouseWheel){this.MooFlow.addEvent('mousewheel', this.wheelTo.bind(this));} if(this.options.useKeyInput){document.addEvent('keydown', this.keyTo.bind(this));} this.getElements(this.MooFlow); }, getElements: function(el){ this.master = {'images':[]}; var els = el.getChildren(); if(els.length<=0) return; $$(els).each(function(e){ var hash = $H(e.getElement('img').getProperties('src','title','alt','longdesc')); if(e.get('tag') == 'a'){hash.merge(e.getProperties('href','rel','target'));} hash = hash.getClean(); this.master['images'].push(hash); }, this); this.clearMain(); }, loadJSON: function(url){ if(!url || this.isLoading) return; this.isLoading = true; new Request.JSON({ onComplete: function(data){ if($chk(data)){ this.master = data; this.index = this.options.startIndex; this.clearMain(); } }.bind(this), onFailure: function(){ this.isLoading = false; this.fireEvent('onChancel', 'Can not load JSON-Data!'); }.bind(this) }, this).get(url); }, loadHTML: function(url, filter){ if(!url || !filter || this.isLoading) return; this.isLoading = true; new Request.HTML({ onSuccess: function(tree, els, htm){ this.getElements(new Element('div', {html: htm}).getChildren(filter)); this.index = this.options.startIndex; }.bind(this), onFailure: function(){ this.isLoading = false; this.fireEvent('onChancel', 'Can not load Remote Images!'); }.bind(this) }, this).get(url); }, clearMain: function(){ if(this.nav){ new Fx.Tween(this.nav, 'bottom', { onComplete: function(){ this.nav.dispose(); if(this.cap) this.cap.dispose(); this.MooFlow.empty(); this.createAniObj(); }.bind(this) }).start(-50); } if(this.cap){this.cap.fade(0);} if(!this.nav && !this.cap){ this.MooFlow.empty(); this.createAniObj(); } }, getMooFlowElements: function(key){ var els = []; this.master.images.each(function(el){ els.push(el[key]); }); return els; }, createAniObj: function(){ this.aniObj = new Element('div').inject(this.MooFlow); this.aniFx = new Fx.TweenEx(this.aniObj, 'left', { transition: Fx.Transitions.Expo.easeOut, link: 'cancel', duration: 750, onMotionChange: this.process.bind(this), onStart: this.flowStart.bind(this), onComplete: this.flowComplete.bind(this) }); this.addLoader(); }, addLoader: function(){ this.MooFlow.store('height', this.MooFlow.getSize().x*this.options.heightRatio); this.MooFlow.addClass('load').setStyle('visibility', 'visible'); new Fx.Tween(this.MooFlow, 'height', { duration: 800, onComplete: this.preloadImg.bind(this) }).start(this.MooFlow.retrieve('height')); }, preloadImg: function(){ this.loader = new Element('div').addClass('loader').inject(this.MooFlow); var imgs = this.getMooFlowElements('src'); this.loadedImages = new Asset.images(imgs, { onComplete: this.loaded.bind(this), onProgress: this.createMooFlowElement.bind(this) }); }, createMooFlowElement: function(counter, index){ var object = this.getCurrent(index); object['width'] = this.loadedImages[index].width; object['height'] = this.loadedImages[index].height; var div = new Element('div').setStyles({ 'position':'absolute', 'display':'none', 'height': this.MooFlow.getSize().y }); var con = new Element('div').inject(div); var img = new Element('img', { 'src': object.src, 'styles':{ 'vertical-align':'bottom', 'width':'100%', 'height':'50%' } }).inject(con); var ref = new Element('img').reflect({ 'src': object.src, 'ref': this.options.reflection, 'height': object.height, 'width': object.width }).inject(con).setStyles({'width':'100%','height':'50%','background-color': this.options.bgColor}); div.inject(this.MooFlow); img.addEvent('click', this.clickTo.bind(this, index)); if(!this.options.useViewer) img.addEvent('dblclick', this.viewCallBack.bind(this, index)); object['div'] = div; object['img'] = img; object['con'] = con; this.loader.set('html', (counter+1) + ' / ' + this.loadedImages.length); }, loaded: function(){ this.iL = this.master.images.length-1; new Fx.Tween(this.loader, 'opacity', { duration : 1000, onComplete: this.createUI.bind(this) }).start(0); }, createUI: function(){ this.MooFlow.removeClass('load'); this.loader.dispose(); if(this.options.useCaption){ this.cap = new Element('div').addClass('caption').set('opacity',0); this.MooFlow.adopt(this.cap); } this.nav = new Element('div').addClass('MooFlowNav').setStyle('bottom','-50px'); var autoPlayCon = new Element('div').addClass('autoPlayCon'); var sliderCon = new Element('div').addClass('sliderCon'); var resizeCon = new Element('div').addClass('resizeCon'); if(this.options.useAutoPlay){ var play = new Element('a').addClass('play').addEvent('click', this.play.bind(this)); var stop = new Element('a').addClass('stop').addEvent('click', this.stop.bind(this)); autoPlayCon.adopt(stop, play); } if(this.options.useSlider){ this.sliPrev = new Element('a').addClass('sliderNext'); this.sliNext = new Element('a').addClass('sliderPrev'); this.slider = new Element('div').addClass('slider'); this.knob = new Element('div').addClass('knob'); this.knob.adopt(new Element('div').addClass('knobleft')); this.slider.adopt(this.knob); sliderCon.adopt(this.sliPrev,this.slider,this.sliNext); this.slider.store('parentWidth', sliderCon.getSize().x-this.sliPrev.getSize().x-this.sliNext.getSize().x); } if(this.options.useResize){ var resize = new Element('a').addClass('resize'); resize.addEvent('click', this.setScreen.bind(this)); resizeCon.adopt(resize); } this.nav.adopt(autoPlayCon,sliderCon,resizeCon); this.MooFlow.adopt(this.nav); this.showUI(); }, showUI: function(){ if(this.cap) this.cap.fade(1); this.nav.tween('bottom', 20); this.fireEvent('onStart'); this.update(); }, update: function(e){ if(e) return; this.oW = this.MooFlow.getSize().x; this.sz = this.oW * 0.5; if(this.options.useSlider){ this.slider.setStyle('width',this.slider.getParent().getSize().x-this.sliPrev.getSize().x-this.sliNext.getSize().x-1); this.knob.setStyle('width',(this.slider.getSize().x/this.iL)); this.sli = new SliderEx(this.slider, this.knob, {steps: this.iL}).set(this.index); this.sli.addEvent('onChange', this.glideTo.bind(this)); this.sliNext.addEvent('click', this.next.bind(this)); this.sliPrev.addEvent('click', this.prev.bind(this)); } this.glideTo(this.index); this.isLoading = false; }, setScreen: function(){ this.isFull = !this.isFull; if(this.isFull){ this.holder = new Element('div').inject(this.MooFlow,'after'); this.MooFlow.wraps(new Element('div').inject(document.body)); this.MooFlow.setStyles({'position':'absolute','z-index':'100','top':'0','left':'0','width':window.getSize().x,'height':window.getSize().y}); if(this.options.useWindowResize){ this._initResize = this.initResize.bind(this); window.addEvent('resize', this._initResize); } } else { this.MooFlow.wraps(this.holder); delete this.holder; window.removeEvent('resize', this._initResize); this.MooFlow.setStyles({'position':'relative','z-index':'','top':'','left':'','width':'','height':this.MooFlow.retrieve('height')}); this.slider.setStyle('width',this.slider.retrieve('parentWidth')); } this.update(); }, initResize: function(){ this.MooFlow.setStyles({'width':window.getSize().x,'height':window.getSize().y}); this.update(); }, getCurrent: function(index){ return this.master.images[$chk(index) ? index : this.index]; }, flowStart: $empty, flowComplete: $empty, viewCallBack: function(index){ if(this.index != index) return; var el = $H(this.getCurrent()); var callBackObject = {}; callBackObject['coords'] = el.img.getCoordinates(); el.each(function(v, k){ if($type(v) == 'number' || $type(v) == 'string') callBackObject[k] = v; }, this); this.fireEvent('onClickView', callBackObject); }, prev: function(){ if(this.index > 0) this.clickTo(this.index-1); }, stop: function(){ $clear(this.autoPlay); this.isAutoPlay = false; this.fireEvent('onAutoStop'); }, play: function(){ this.autoPlay = this.auto.periodical(this.options.interval, this); this.isAutoPlay = true; this.fireEvent('onAutoPlay'); }, auto: function(){ if(this.index < this.iL) this.next(); else if(this.index == this.iL) this.clickTo(0); }, next: function(){ if(this.index < this.iL) this.clickTo(this.index+1); }, keyTo: function(e){ e = new Event(e); switch (e.code){ case 37: e.stop(); this.prev(); break; case 39: e.stop(); this.next(); } }, wheelTo: function(e){ e = new Event(e).stop(); var d = e.wheel; if(e.preventDefault) e.preventDefault(); if(d > 0) this.prev(); if(d < 0) this.next(); }, clickTo: function(index){ if(this.index == index) return; this.aniFx.cancel(); if(this.sli) this.sli.set(index); this.glideTo(index); }, glideTo: function(index){ this.index = index; if(this.cap) this.cap.set('html', this.getCurrent().title); this.aniFx.start(index*-this.foc); }, process: function(x){ var zI=this.iL,z,W,H,foc=this.foc,f=this.factor,sz=this.sz,oW=this.oW,div; with (Math) { this.master.images.each(function(el){ div = el.div; if(x>-foc*6 && x= el.width * 0.5) W = round(f / z * sz); el.con.setStyle('height', H*2 + 'px'); div.setStyle('width', W + 'px'); div.setStyle('left', round(((x / z * sz) + sz) - (f * 0.5) / z * sz) + 'px'); div.setStyle('top', round(oW * 0.4 - H) + 'px'); div.setStyle('z-index', x < 0 ? zI++ : zI--); div.setStyle('display', 'block'); } else { div.setStyle('display', 'none'); } x += foc; }); } } }); window.addEvent('domready', function(){ $$('.MooFlowieze').each(function(mooflow){ new MooFlow(mooflow); }); });