/** * QSF Slide Application * @uses JQuery, YAHOO.widget.Paginator **/ var App_Slide = qs.createObject(); App_Slide.prototype = { __instances: [], _timer: null, _arrowTimer: null, _mouseTimer: null, _mouseOverStatus: null, _animated: true, _buttons: [{name: 'prev', title: 'Previous'}, {name: 'play', title: 'Play', arguments: [0]}, {name: 'pause', title: 'Pause'}, {name: 'next', title: 'Next'}], arrowsSize: [40, 80], // [width, height] _paginatorTemplatePlaceholders: ['{FirstPageLink}', '{PreviousPageLink}', '{PageLinks}', '{NextPageLink}', '{LastPageLink}'], paginator: null, container: null, itemContainer: null, buttonsContainer: null, index: null, slides: null, idItem: null, status: null, autostart: true, defaultDirection: 'right', direction: null, interval: 5000, effect: 'slide', effectDuration: 500, showArrows: true, enableButtons: true, enablePaginator: true, pageLinkWidth: 24, paginatorOptions: { firstPageLinkLabel: '«', previousPageLinkLabel: '‹', nextPageLinkLabel: '›', lastPageLinkLabel: '» ', rowsPerPage: 1 }, resizeTimeout: null, init: function (options) { if (typeof options.testImage != 'undefined' && '' != options.testImage) { var testImage = new Image(); testImage.onload = function () { if (testImage.width > 0) { new App_Slide(options); } else { var containerId = 'slides-container-' + qs.debug.vdie(); $('#' + containerId).hide(); } }; testImage.src = options.testImage; } else { new App_Slide(options); } }, initialize: function (options) { this.setOptions(options); if (!this.slides.length) { return false; } App_Slide.prototype.__instances[this.idItem] = this; var obj = this; if (this.slides.length <= 1) { this.showArrows = false; this.enableButtons = false; this.enablePaginator = false; this.autostart = false; } // prepare HTML this.container.onmouseover = function (event) { obj.itemOnMouseOver(event); }; this.container.onmouseout = function (event) { obj.itemOnMouseOut(event); }; this.itemContainer = document.createElement('div'); this.itemContainer.className = 'slide_items_container'; this.itemContainer.style.maxWidth = this.maxWidth + 'px'; this.itemContainer.style.maxHeight = this.maxHeight + 'px'; this.container.appendChild(this.itemContainer); if (this.enableButtons || this.enablePaginator) { this.toolbarContainer = document.getElementById('slides-toolbar-container-' + this.idItem); if (!this.toolbarContainer) { this.toolbarContainer = document.createElement('div'); this.toolbarContainer.id = 'slides-toolbar-container-' + this.idItem; if (this.container.nextSibling) { this.container.parentNode.insertBefore(this.toolbarContainer, this.container.nextSibling); } else { this.container.parentNode.appendChild(this.toolbarContainer); } } this.toolbarContainer.className = 'slide_toolbar_container'; this.paginatorContainer = document.createElement('div'); this.paginatorContainer.className = 'slide_paginator'; this.paginatorContainer.id = 'slide-toolbar-' + this.idItem; this.toolbarContainer.appendChild(this.paginatorContainer); } if (this.enableButtons) { this.buttonsContainer = document.createElement('div'); this.buttonsContainer.className = 'slide_player'; for (var i = this._buttons.length -1; i >=0 ; i--) { var button = this._buttons[i]; var a = document.createElement('a'); a.className = button.name; a.title = button.title; a.alt = button.title; a.href = '#'; a.onclick = (function (idItem, button) { return function () { var obj = App_Slide.prototype.getInstance(idItem); obj[button.name].apply( obj, (button.arguments && button.arguments.length) ? button.arguments : [] ); return false; }; })(this.idItem, button); this.buttonsContainer.appendChild(a); } this.toolbarContainer.appendChild(this.buttonsContainer); } if (this.toolbarContainer) { var clear = document.createElement('div'); clear.className = 'clear'; this.toolbarContainer.appendChild(clear); } // end of prepare HTML this.showToolbar(); $('#slide-container-mobile').addClass('hidden-desktop'); $(this.container).addClass('visible-desktop').removeClass('hidden'); $('.slide_preload', this.container).fadeOut(250); $('.slide_preload', this.container).remove(); for (var j = 0; j < this.slides.length; j++) { this.slides[j].showTime = false; this.slides[j]._animated = true; this.setVisible(false, j); } this.slides[0].showTime = new Date().getTime(); $(this.container).touchSwipeLeft(function () { obj.next(); }); $(this.container).touchSwipeRight(function () { obj.prev(); }); $(window).resize(function () { obj.onResize(); }); this._resize(); if (this.autostart) { this.play(0); } else { this.pause(); this.preload(0); } return true; }, onResize: function () { var obj = this; if (this.resizeTimeout) { clearTimeout(this.resizeTimeout); this.resizeTimeout = null; } this.resizeTimeout = setTimeout(function () { obj._resize(); }, 300); }, _resize: function () { if (this._animated) { this.width = $(this.container).width(); this.height = Math.round(this.maxHeight * this.width / this.maxWidth); $('.slide_items_container', this.container).css('width', this.width); $('.slide_items_container', this.container).css('height', this.height); $('.slide_item', this.container).css('width', this.width); $('.slide_item', this.container).css('height', this.height); if (this.showArrows) { this.displayArrows(); } this.initImageMap(); } }, displayArrows: function () { var obj = this; if (undefined == this.nextButton) { this.nextButton = document.createElement('div'); this.nextButton.className = 'slide_next_button'; // this.nextButton.style.display = 'none'; this.nextButton.onclick = function() { obj.next(); }; this.container.appendChild(this.nextButton); } this.nextButton.style.marginLeft = (this.width - this.arrowsSize[0]) + 'px'; // this.nextButton.style.marginTop = Math.ceil((this.height - this.arrowsSize[1])/2) + 'px'; if (undefined == this.prevButton) { this.prevButton = document.createElement('div'); this.prevButton.className = 'slide_prev_button'; // this.prevButton.style.display = 'none'; this.prevButton.onclick = function() { obj.prev(); }; this.container.appendChild(this.prevButton); } // this.prevButton.style.marginTop = Math.ceil((this.height - this.arrowsSize[1])/2) + 'px'; this.prevButton.style.marginLeft = '0px'; }, /** * передерто з https://github.com/stowball/jQuery-rwdImageMaps */ initImageMap: function () { var obj = this; $('div.slide_item img').each(function() { if (typeof($(this).attr('usemap')) == 'undefined') { return; } var w = obj.maxWidth, h = obj.maxHeight; var wPercent = $(this).width() / 100, hPercent = $(this).height() / 100, map = $(this).attr('usemap').replace('#', ''), c = 'coords'; $('map[name="' + map + '"]').find('area').each(function() { if (!$(this).data(c)) { $(this).data(c, $(this).attr(c)); } var coords = $(this).data(c).split(','), coordsPercent = new Array(coords.length); for (var i = 0; i < coordsPercent.length; ++i) { if (i % 2 === 0) { coordsPercent[i] = parseInt(((coords[i]/w)*100)*wPercent); } else { coordsPercent[i] = parseInt(((coords[i]/h)*100)*hPercent); } } $(this).attr(c, coordsPercent.toString()); }); }); }, setOptions: function (options) { if (typeof options == 'object') { for (var field in options) { var value = options[field]; if (typeof value == 'string' && !value.length) { continue; } switch (field) { case 'interval': this.setInterval(value); break; case 'idContainer': this.setContainer(value); break; case 'slides': if (typeof value == 'object') { this.setSlides(value) } break; case 'paginatorOptions': this.setPaginatorOptions(value); break; case 'idItem': this.setIdItem(value); break; case 'effectDuration': value = +value; // break intentionally omitted default: this[field] = value; } } } }, setPaginatorOption: function (name, value) { if (typeof value == 'string' && !value.length) { return false; } if (name == 'linkWidth' && +value) { this.pageLinkWidth = +value; return false; } this.paginatorOptions[name] = value; return true; }, setPaginatorOptions: function (options) { for (var i in options) { this.setPaginatorOption(i, options[i]); } }, isVisible: function (index) { if (typeof index == 'undefined') { index = this.index; } if (typeof this.slides[index] != 'undefined') { return this.slides[index].visible; } return false; }, setVisible: function (visible, index) { if (typeof index == 'undefined') { index = this.index; } if (typeof this.slides[index] != 'undefined') { this.slides[index].visible = visible; } return false; }, isPreloaded: function (index) { if (typeof index == 'undefined') { index = this.index; } if (typeof this.slides[index] != 'undefined' && typeof this.slides[index].containerObj != 'undefined') { return true; } return false; }, getInstance: function(id) { if (typeof App_Slide.prototype.__instances[id] != 'undefined') { return App_Slide.prototype.__instances[id]; } return false; }, setInterval: function (interval) { interval = parseFloat(interval); if (!isNaN(interval) && interval != 0) { this.interval = interval * 1000; return true; } alert('App_Slide: time interval is wrong!'); return false; }, setIdItem: function (id) { id = parseInt(id); if (!isNaN(id) && id != 0) { this.idItem = id; this.setContainer('slides-container-' + id); return true; } alert('App_Slide: idItem is wrong!'); return false; }, setContainer: function(id) { this.container = document.getElementById(id); if (this.container) { return true; } this.container = null; alert('App_Slide: slides container is wrong!'); return false; }, animationStarted: function (index) { if (typeof index == 'undefined') { index = this.index; } this._animated = false; this.slides[index]._animated = false; }, prev: function () { if (!this._animated) { return false; } this.stop(); this.direction = 'left'; this.animationStarted(this.getNextIndex()); this.initNextShowTime(0); this.preload(); return true; }, play: function (interval) { this._mouseOverStatus = null; this.log('play'); this.status = 'play'; this._mouseOverStatus = 'play'; if (typeof interval != 'undefined') { this.initNextShowTime(interval); } else { this.initNextShowTime(interval); } this.preload(); this.startTimer(); this.hideButton('play'); this.showButton('pause'); }, next: function () { if (!this._animated) { return false; } this.stop(); this.direction = 'right'; this.animationStarted(this.getNextIndex()); this.initNextShowTime(0); this.preload(); return true; }, pause: function () { this.stop(); this.showButton('play'); this.hideButton('pause'); }, hideButton: function (name) { $('a.' + name, this.buttonsContainer).hide(); }, showButton: function (name) { $('a.' + name, this.buttonsContainer).show(); }, setSlides: function(slides) { if (typeof slides == 'object') { this.slides = slides; return true; } alert('App_Slide: slides are not object!'); return false; }, startTimer: function () { if (this._timer != null) { clearTimeout(this._timer); this._timer = null; } this._timer = setTimeout('App_Slide.prototype.getInstance(\'' + this.idItem + '\').preload()', this.interval); return true; }, stopTimer: function () { if (this._timer != null) { clearTimeout(this._timer); } this._timer = null; if (null != this._mouseTimer) { clearTimeout(this._mouseTimer); this._mouseTimer = null; } }, stop: function () { this.status = 'stop'; this._mouseOverStatus = 'stop'; this.stopTimer(); return true; }, showBigArrows: function () { if (this.showArrows) { $(this.prevButton).show(); $(this.nextButton).show(); } this.showToolbar(); }, hideBigArrows: function () { if (this.showArrows) { // $(this.prevButton).hide(); // $(this.nextButton).hide(); } this.hideToolbar(); }, itemOnMouseOver: function (event) { if (null != this._arrowTimer) { clearTimeout(this._arrowTimer); this._arrowTimer = null; } this.showBigArrows(); if (null == this._mouseOverStatus) { this._mouseOverStatus = this.status; } if (null != this._mouseTimer) { clearTimeout(this._mouseTimer); this._mouseTimer = null; } this.stopTimer(); this.showButton('play'); this.hideButton('pause'); }, itemOnMouseOut: function (event) { this._arrowTimer = setTimeout('App_Slide.prototype.getInstance(\'' + this.idItem + '\').hideBigArrows();', 50); if (this._mouseOverStatus == 'play') { this._mouseTimer = setTimeout('App_Slide.prototype.getInstance(\'' + this.idItem + '\').play();', 50); } if ('play' == this._mouseOverStatus) { this.hideButton('play'); this.showButton('pause'); } }, show: function (index) { if (typeof index == 'undefined') { index = this.index; } if (this.slides[index] == null || this.slides[index] == 'undefined') { index = 0; } var slide = this.slides[index]; var direction = -1; if (this.getDirection() == 'right') { direction = 1; } this.direction = null; this.log('direction=' + direction); if (this.index != null) { if ('slide' == this.effect) { slide.containerObj.style.left = direction * this.width + 'px'; } else { this.slides[index].containerObj.style.display = 'none'; } } slide.containerObj.style.marginLeft = 0; slide.containerObj.style.width = this.width + 'px'; slide.containerObj.style.height = this.height + 'px'; $(this.itemContainer).append(slide.containerObj); this._animated = false; slide._animated = false; var obj = this; if (this.index != null) { if ('slide' == this.effect) { this.log('animation ' + (-1 * direction * this.width) + ' ' + this.effectDuration + ' ms'); $('.slide_item:first').animate( {marginLeft:-1 * direction * this.width}, {duration: this.effectDuration} ); $('.slide_item:last').animate( {marginLeft:-1 * direction * this.width}, { duration: this.effectDuration, complete: function () {obj.animationComplete(index, direction);} } ); } else { $(this.slides[this.index].containerObj).fadeOut(this.effectDuration); $(slide.containerObj).fadeIn( this.effectDuration, function () {obj.animationComplete(index, direction);} ); } } else { this.log('no animation'); obj.animationComplete(index, direction); } }, animationComplete: function (index, direction) { var slide = this.slides[index]; if ($('.slide_item', this.container).size() > 1) { if (direction) { $('.slide_item:last', this.container).css({left: 0, marginLeft: 0}); $('.slide_item:first', this.container).remove(); } else { $('.slide_item:first', this.container).css({left: 0, marginLeft: 0}); $('.slide_item:last', this.container).remove(); } } this._animated = true; slide.showTime = false; this.setVisible(false, this.index); // mark previous banner as invisible this.log('show ' + this.index + '->' + index); this.index = index; // set current index this.paginatorSetPage(index + 1); this.setVisible(true); // mark current banner as visible this.initImageMap(); if (this.status == 'play') { this.initNextShowTime(); this.preload(); this.startTimer(); } else { this.log('status = ' + this.status); } }, hideToolbar: function () { if (!this.enablePaginator && !this.enableButtons) { return false; } return false; }, showToolbar: function () { if (!this.enablePaginator && !this.enableButtons) { return false; } if (typeof this.toolbarContainer.positionFixed == 'undefined') { if (this.enablePaginator) { var paginatorWidth = this.width; if (this.enableButtons) { paginatorWidth -= this.buttonsContainer.offsetWidth; } this.paginatorOptions.containers = 'slide-toolbar-' + this.idItem; this.paginatorOptions.totalRecords = this.slides.length; this.paginatorOptions.totalRecords = this.slides.length; var additionalPages = 0; if (typeof this.paginatorOptions.pageLinks == 'undefined') { if (typeof this.paginatorOptions.template == 'string' && this.paginatorOptions.template.length) { for (var i = 0; i < this._paginatorTemplatePlaceholders.length; i++) { var placeholder = this._paginatorTemplatePlaceholders[i]; if (placeholder == '{pageLinks}') { continue; } if (-1 != this.paginatorOptions.template.indexOf(placeholder)) { additionalPages++; } } } else { additionalPages = 4; } this.paginatorOptions.pageLinks = Math.floor(paginatorWidth / this.pageLinkWidth) - additionalPages; } this.paginator = new YAHOO.widget.Paginator(this.paginatorOptions); this.paginator.render(); var obj = this; this.paginator.subscribe('changeRequest', function(state) {obj.paginatorChangeRequest(state)}); } this.toolbarContainer.positionFixed = true; } $(this.toolbarContainer).show(); return true; }, paginatorSetPage: function (page) { if (this.paginator) { this.paginator.setPage(page, true); } }, paginatorChangeRequest: function (state) { if (!this._animated) { return false; } var index = state.page - 1; if (index > this.index) { this.direction = 'right'; } else { this.direction = 'left'; } this.animationStarted(index); this.initShowTime(index, 0); this.preload(index); this.paginator.setState(state); return true; }, initShowTime: function (index, interval) { if (typeof interval == 'undefined') { interval = this.interval; } this.slides[index].showTime = new Date().getTime() + interval; }, initNextShowTime: function (interval) { this.initShowTime(this.getNextIndex(), interval); }, getDirection: function () { return this.direction || this.defaultDirection; }, getNextIndex: function () { var index; var direction = this.getDirection(); if (null == this.index) { return 0; } else if ('right' == direction) { index = (this.slides.length == this.index + 1) ? 0 : this.index + 1; } else if ('left' == direction) { index = (0 == this.index) ? this.slides.length - 1 : this.index - 1; } return index; }, onabort: function (image) { return false; }, onerror: function (image) { this.next(); }, extractHtmlImages: function (html) { var re, match, images = []; var trimQuotes = function trimQuotes(str) { return str.replace(/^["']+|["']+$/g, ''); }; // scr images re = /]+src\s*=\s*["']([^"']+)["'][^>]*>/ig; while (null !== (match = re.exec(html))) { images.push(match[1]); } // background images re = /background\s*:\s*url\(([^\)]+)\)/ig; while (null !== (match = re.exec(html))) { images.push(trimQuotes(match[1])); } return images; }, preloadHtmlImages: function (html, callback) { var obj = this, i, count, loadingCount, loadCallback, sources, _images = []; sources = this.extractHtmlImages(html); count = loadingCount = sources.length; if (count) { for (i = 0; i < count; i++) { _images[i] = new Image(); loadCallback = (function (index) { return function () { if (0 === --loadingCount) { callback.call(obj); } } })(i); _images[i].onabort = loadCallback; _images[i].onerror = loadCallback; _images[i].onload = loadCallback; _images[i].src = sources[i]; } } else { callback.call(obj); } return this; }, preload: function (index, onloadCallback) { if (typeof index == 'undefined') { index = this.getNextIndex(); } var obj = this; var slide = this.slides[index]; if (typeof slide.containerObj == 'undefined') { this.log('preload ' + index); slide.containerObj = document.createElement('div'); slide.containerObj.className = 'slide_item'; slide.containerObj.style.maxWidth = this.maxWidth + 'px'; slide.containerObj.style.maxHeight = this.maxHeight + 'px'; var htmlContainer = document.createElement('div'); htmlContainer.className = 'slide_html'; if ('image' == slide.type) { var imageObj = new Image(); imageObj.setAttribute('useMap', '#slide_map_' + slide.id); imageObj.setAttribute('alt', slide.title); imageObj.setAttribute('title', slide.title); imageObj.onabort = function () {obj.onabort(this)}; imageObj.onerror = function () {obj.onerror(this)}; imageObj.onload = function () { /*this.style.marginLeft = Math.ceil((obj.width - this.width)/2) + 'px'; this.style.marginTop = Math.ceil((obj.height - this.height)/2) + 'px';*/ obj.preloaded(index); }; imageObj.src = slide.image; if (slide.linkType != 'none' && slide.url != '') { var slideUrl = document.createElement('a'); slideUrl.setAttribute('class', 'slide-url'); slideUrl.setAttribute('href', slide.url); slideUrl.setAttribute('title', slide.title); if (slide.target) { slideUrl.setAttribute('target', '_blank'); } slideUrl.appendChild(imageObj); htmlContainer.appendChild(slideUrl); } else { htmlContainer.appendChild(imageObj); } var slideTitle = document.createElement('h2'); slideTitle.setAttribute('title', slide.title); if (undefined != slide.title) { $(slideTitle).text(qs.truncate(slide.title, slide.maxImageTitleLength)); } var titleContainer = document.createElement('div'); titleContainer.className = 'slide_text single_title tac'; titleContainer.appendChild(slideTitle); htmlContainer.appendChild(titleContainer); slide.containerObj.appendChild(htmlContainer); } else if ('html' == slide.type) { htmlContainer.style.maxWidth = this.maxWidth + 'px'; htmlContainer.style.maxHeight = this.maxHeight + 'px'; htmlContainer.innerHTML = slide.content; slide.containerObj.appendChild(htmlContainer); obj.preloadHtmlImages(slide.content, function () { obj.preloaded(index); }); } } else { obj.preloaded(index); } }, preloaded: function (index) { this.log('preloaded ' + index); var now = new Date(); var slide = this.slides[index]; if (false !== slide.showTime && Math.floor(now.getTime()/1000) >= Math.floor(slide.showTime/1000)) { this.show(index); } else { this.log(slide.showTime + '\n' + now.getTime()); } }, log: function (text) { if (!this.debug || typeof console == 'undefined') { return false; } var message = 'index=' + this.index + '. [' + text + '] '; console.info(message); return true; } };