(function (_super) { var ns = 'hui_presentation'; /** * Vertical rows * @class * @augments hui.ui.Component * @param {Object} options */ hui.ui.Presentation = function(options) { _super.call(this, options); this.items = []; this.images = []; hui.cls.add(this.element,'hui-is-light'); this.nativeScroll = !!navigator.userAgent.match('iPhone|iPad|iPod|Safari') && !window.chrome && hui.browser.webkitVersion > 603; //this.nativeScroll = false; this._attach(); }; hui.ui.Presentation.create = function(options) { options = options || {}; var makeIcon = function(body, size) { return '<svg class="' + ns + '_icon" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + size + ' ' + size + '">' + body + '</svg>'; }; var close = makeIcon( '<line class="' + ns + '_line" x1="1" y1="1" x2="31" y2="31"/>' + '<line class="' + ns + '_line" x1="1" y1="31" x2="31" y2="1"/>' ); close = makeIcon('<path class="' + ns + '_line" d="M1,1l30,30 M1,31L31,1"/>', 32); close = makeIcon('<path class="' + ns + '_line" d="M1,1l20,20 M1,21L21,1"/>', 22); var right = makeIcon('<path class="' + ns + '_line" d="M8.5,31l15-15L8.5,1"/>', 32); var left = makeIcon('<path class="' + ns + '_line" d="M23.5,1l-15,15l15,15"/>', 32); options.element = hui.build('div', { 'class' : ns, html : '<div class="' + ns + '_viewer id-viewer"><div class="' + ns + '_items id-items"></div></div>' + '<div class="' + ns + '_thumbnails id-thumbs"></div>'+ '<div class="' + ns + '_close id-close">' + close + '</div>'+ '<div class="' + ns + '_arrow ' + ns + '_next id-next">' + right + '</div>'+ '<div class="' + ns + '_arrow ' + ns + '_previous id-previous">' + left + '</div>', parent: document.body }); if (!hui.browser.touch) { hui.cls.add(options.element,'hui-is-mouse'); } return new hui.ui.Presentation(options); }; hui.ui.Presentation.prototype = { position: 0, index : 0, width: 0, animating: false, nodes : { viewer : '.id-viewer', items : '.id-items', thumbs : '.id-thumbs', close : '.id-close', next : '.id-next', previous : '.id-previous' }, _attach : function() { hui.on(this.nodes.close,'tap',this.close, this); hui.on(this.nodes.next,'tap',this.next, this); hui.on(this.nodes.previous,'tap',this.previous, this); hui.on(this.nodes.thumbs,'tap',this._tapThumbs, this); if (this.nativeScroll) { hui.cls.add(this.element,'hui-is-native-scroll'); this._attachNative(); } else { this._attachDrag(); } }, close : function(e) { if (e) hui.event(e).stop(); hui.cls.remove(this.element,'hui-is-open'); this._lockScroll(false); }, _attachNative : function() { var x,y; var moved = false; hui.listen(this.element,'touchstart',function(e) { moved = false; }.bind(this)); hui.listen(this.element,'touchmove',function(e) { if (e.touches && e.touches.length == 2) { if (x===undefined) {x = e.pageX;} if (y===undefined) {y = e.pageY;} var img = this.images[this.index]; var newX = e.pageX - x + img.x; var newY = e.pageY - y + img.y; var scale = (e.scale) * (img.scale); img.newScale = scale; img.newX = newX; img.newY = newY; img.node.style.transform = 'scale(' + scale + ') translate(' + (newX)/scale + 'px,' + (newY)/scale + 'px)'; } if (e.touches && e.touches.length > 1) { e.preventDefault(); } moved = true; //console.log('Scale', e.scale); }.bind(this)); hui.listen(this.element,'touchend',function(e) { x = y = undefined; this.images.forEach(function(img) { if (img.newScale) { img.scale = img.newScale; img.newScale = undefined; } if (img.newX) { img.x = img.newX; img.newX = undefined; } if (img.newY) { img.y = img.newY; img.newY = undefined; } }); if (!moved && hui.dom.isDescendantOrSelf(e.target, this.nodes.viewer)) { var img = this.images[this.index]; if (img.scale != 1) { img.node.style.transition = 'transform .3s'; img.node.style.transform = 'scale(1) translate(0px,0px)'; setTimeout(function() { img.node.style.transition = ''; },350); img.scale = 1; img.x = img.y = 0; } else { this._toggleThumbs(); } } }.bind(this)); var timer; var scrollEnd = function() { var width = this.nodes.viewer.clientWidth; var scrl = this.nodes.viewer.scrollLeft; this.index = Math.round(scrl / width); }.bind(this); hui.listen(this.nodes.viewer,'scroll',function(e) { //console.log('Scroll', e); clearTimeout(timer); timer = setTimeout(scrollEnd,150); }); }, _originalScroll : 0, _lockScroll : function(lock) { if (lock) { this._originalScroll = document.body.scrollTop; } lock = lock ? 'hidden' : ''; document.body.parentNode.style.overflow = lock; document.body.style.overflow = lock; if (!lock) { document.body.scrollTop = this._originalScroll; } }, /** Go to the previous image * @param {Boolean} user If it is initiated by the user */ previous : function(e) { if (e) hui.stop(e); this.index--; var num = 1; if (this.index < 0) { this.index = this.items.length - 1; num = this.items.length; } this._goToImage(true,num,true); }, /** Go to the next image * @param {Boolean} user If it is initiated by the user */ next : function(e) { if (e) hui.stop(e); this.index++; var num = 1; if (this.index==this.items.length) { this.index = 0; num = this.items.length; } this._goToImage(true,num,true); }, show : function(params) { params = params || {}; if (params.source) { var pos = hui.position.get(params.source); hui.cls.add(this.element,'hui-is-minimized'); } hui.cls.add(this.element,'hui-is-open'); this._calculateSize(); if (params.items) { this.items = params.items; this._rebuild(); } if (hui.isNumber(params.index)) { this.index = params.index; this._goToImage(false, 0, false); } window.setTimeout(function() { this._lockScroll(true); }.bind(this),100) }, _tapThumbs : function(e) { e = hui.event(e); var thumb = e.findByClass(ns + '_thumbnail'); if (thumb) { var index = parseInt(thumb.getAttribute('data'),10); this._goTo(index); } }, _rebuild : function() { this.images = []; this.nodes.items.innerHTML = ''; this.nodes.thumbs.innerHTML = ''; for (var i = 0; i < this.items.length; i++) { var url = hui.ui.callDelegates(this,'getPreview',{item: this.items[i], index: i}); var item = hui.build('div',{parent : this.nodes.items, 'class' : ns+'_item'}); var image = hui.build('div',{parent : item, 'class' : ns+'_image'}); var content = hui.build('div',{parent : image, 'class' : ns+'_image_content'}); var thumb = hui.build('div',{parent : this.nodes.thumbs, 'class' : ns+'_thumbnail', data:i}); if (url) { content.style.backgroundImage = 'url(' + url + ')'; thumb.style.backgroundImage = 'url(' + url + ')'; } this.images.push({node:content,scale:1,x:0,y:0}); } hui.cls.set(this.element, 'hui-is-multiple', this.items.length > 1); this._updateImages(); }, _updateImages : function() { if (!this.items.length) { return; } var width = this.nodes.viewer.clientWidth, height = this.nodes.viewer.clientHeight, thumbs = hui.get.children(this.nodes.thumbs); var thumbSize = thumbs[0].clientWidth; var load = function(url,node) { var img = new Image(); img.onload = function() { node.style.backgroundImage = "url('" + url + "')"; }; img.src = url; }; var ratio = window.devicePixelRatio > 1 ? 2 : 1; for (var i = 0; i < this.items.length; i++) { var item = this.items[i]; var url = hui.ui.callDelegates(this,'getImage',{item: item, width: width * ratio, height: height * ratio}); load(url, this.images[i].node); //images[i].style.backgroundImage = "url('" + url + "')"; var thmbUrl = hui.ui.callDelegates(this,'getImage',{item: item, width: thumbSize * ratio, height: thumbSize * ratio}); load(thmbUrl, thumbs[i]); //thumbs[i].style.backgroundImage = "url('" + url + "')"; } }, _calculateSize : function() { this.width = this.nodes.viewer.clientWidth; }, $$layout : function() { this._calculateSize(); this._updateImages(); }, _draw : function() { this.nodes.items.style.transform = 'translate3d(' + this.position + 'px,0,0)'; }, _attachDrag : function() { var initial = 0; var left = 0; var scrl = 0; var viewer = this.nodes.viewer; var inner = this.nodes.items; var max = 0; var stmp; var currentSlide; var speed = 0; hui.drag.attach({ touch : true, element : viewer, $check : function() { return !this.animating; }.bind(this), $startMove : function(e) { initial = e.getLeft(); scrl = this.position; max = (this.items.length-1) * this.width * -1; stmp = e.event.timeStamp; speed = 0; }.bind(this), $move : function(e) { var latestLeft = left; left = e.getLeft(); var pos = (scrl - (initial - left)); if (pos > 0) { pos = (Math.exp(pos * -0.013) -1) * -80; } if (pos < max) { pos = (Math.exp((pos - max) * 0.013) -1) * 80 + max; } this.position = pos; var dur = (e.event.timeStamp - stmp); var curSpeed = dur > 0 ? (latestLeft - left) / dur : 0; speed = (speed + curSpeed) / 2; //console.log(speed); stmp = e.event.timeStamp; this._draw(); }.bind(this), $endMove : function(e) { var func = (initial - left) < 0 ? Math.floor : Math.ceil; this.index = func(this.position * -1 / this.width); var num = this.items.length - 1; if (this.index==this.items.length) { this.index = 0; this.index = this.items.length - 1; } else if (this.index < 0) { this.index = this.items.length - 1; this.index = 0; } else { num = 1; } this._goToImage(true,num,false,true, Math.abs(speed)); }.bind(this), $notMoved : this._toggleThumbs.bind(this) }); }, _toggleThumbs : function() { if (this.items.length > 1) { hui.cls.toggle(this.element,'hui-is-thumbnails'); } }, _goTo : function(index) { if (this.index == index) { return; } var diff = Math.abs(this.index - index); this.index = index; this._goToImage(true, diff, false); }, _goToImage : function(animate,num,user,drag,speed) { if (this.nativeScroll) { var viewer = this.nodes.viewer, scrl = viewer.clientWidth * this.index; if (animate) { hui.animate({ node: viewer, duration: 500, property: 'scrollLeft', value: scrl, ease: hui.ease.fastSlow }); } else { if (hui.browser.webkitVersion < 603) { setTimeout(function() { viewer.scrollTo(scrl,0); }); } else { this.nodes.viewer.scrollLeft = scrl; } } return; } speed = speed || 2; var initial = this.position; var target = this.position = this.index * (this.width) * -1; if (animate) { var duration, ease; if (drag) { duration = 300 / speed; ease = hui.ease.quadOut; duration = Math.min(800,Math.max(200, duration)); } else if (num > 1) { duration = Math.min(num * 500, 2000); ease = hui.ease.fastSlow; } else { var end = this.index === 0 || this.index === this.items.length - 1; ease = (end ? hui.ease.elastic : hui.ease.fastSlow); if (!user) { ease = hui.ease.fastSlow; } duration = (end ? 1000 : 1000 / speed); } this.animating = true; hui.animate({ node : this.nodes.items, //css : {marginLeft : target + 'px'}, duration : duration, ease : ease, $render : function(node,v) { this.position = initial + (target - initial) * v; this._draw(); }.bind(this), $complete : function() { this.animating = false; }.bind(this) }); } else { this._draw(); } } }; hui.extend(hui.ui.Presentation, _super); hui.define('hui.ui.Presentation', hui.ui.Presentation); })(hui.ui.Component);