/** * @module Ink.UI.Gallery_1 * @author inkdev AT sapo.pt * @version 1 */ Ink.createModule('Ink.UI.Gallery', '1', ['Ink.UI.Aux_1','Ink.Dom.Event_1','Ink.Dom.Css_1','Ink.Dom.Element_1','Ink.Dom.Selector_1','Ink.Util.Array_1','Ink.Util.Swipe_1'], function(Aux, Event, Css, Element, Selector, InkArray, Swipe ) { 'use strict'; /** * Function to calculate the size based on a given max. size and image size. * * @function maximizeBox * @param {Number} maxSz * @param {Number} imageSz * @param {Boolean} forceMaximize * @return {Number} * @private */ var maximizeBox = function(maxSz, imageSz, forceMaximize) { var w = imageSz[0]; var h = imageSz[1]; if (forceMaximize || (w > maxSz[0] || h > maxSz[1]) ) { var arImg = w / h; var arMax = maxSz[0] / maxSz[1]; var s = (arImg > arMax) ? maxSz[0] / w : maxSz[1] / h; return [parseInt(w * s + 0.5, 10), parseInt(h * s + 0.5, 10)]; } return imageSz; }; /** * @function maximizeBox * @param {Object} o * @param {Function} cb Callback function to run on each image loaded. * @private */ var getDimsAsync = function(o, cb) { cb = Ink.bind(cb,o); var dims = [o.img.offsetWidth, o.img.offsetHeight]; if (dims[0] && dims[1]) { cb(dims); } o.img.onload = Ink.bindEvent(function() { cb([this.img.offsetWidth, this.img.offsetHeight]); },o); }; /** * @class Ink.UI.Gallery * @constructor * @version 1 * @uses Ink.UI.Aux * @uses Ink.Dom.Event * @uses Ink.Dom.Css * @uses Ink.Dom.Element * @uses Ink.Dom.Selector * @uses Ink.Util.Array * @uses Ink.Util.Swipe * @param {String|DOMElement} selector * @param {Object} [options] Options for the gallery * @param {Number} [options.fullImageMaxWidth] Default value is 400. * @param {Number} [options.thumbnailMaxWidth] Max. width of the thumbnail. Default value is 106. * @param {Number} [options.layout] This determines what layout the gallery will have. Numeric value between 0 and 3. * @param {Boolean} [options.circular] Determines if the gallery behaves in a circular never ending cycle. * @param {Boolean} [options.fixImageSizes] Specifies if the images should be forced to have the gallery size. * @example *
* */ var Gallery = function(selector, options) { this._element = Aux.elOrSelector(selector, '1st argument'); this._options = Ink.extendObj({ fullImageMaxWidth: 600, fullImageMaxHeight: 400, thumbnailMaxWidth: 106, layout: 0, circular: false, fixImageSizes: false }, Element.data(this._element)); this._options = Ink.extendObj(this._options, options || {}); this._handlers = { navClick: Ink.bindEvent(this._onNavClick,this), paginationClick: Ink.bindEvent(this._onPaginationClick,this), thumbsClick: Ink.bindEvent(this._onThumbsClick,this), focusBlur: Ink.bindEvent(this._onFocusBlur,this), keyDown: Ink.bindEvent(this._onKeyDown,this) }; this._isFocused = false; this._model = []; if (this._options.model instanceof Array) { this._model = this._options.model; this._createdFrom = 'JSON'; } else if (this._element.nodeName.toLowerCase() === 'ul') { this._createdFrom = 'DOM'; } else { throw new TypeError('You must pass a selector expression/DOM element as 1st option or provide a model on 2nd argument!'); } this._index = 0; this._thumbIndex = 0; if( !isNaN(this._options.layout) ){ this._options.layout = parseInt(this._options.layout,10); if (this._options.layout === 0) { this._showThumbs = false; this._showDescription = false; this._paginationHasPrevNext = false; } else if (this._options.layout === 1 || this._options.layout === 2 || this._options.layout === 3) { this._showThumbs = true; this._showDescription = true; this._paginationHasPrevNext = true; } else { throw new TypeError('supported layouts are 0-3!'); } } if (this._element.getAttribute('data-fix-image-sizes') !== null) { this._options.fixImageSizes = true; } this._init(); }; Gallery.prototype = { /** * Init function called from the constructor. * * @method _init * @private */ _init: function() { // extract model if (this._createdFrom === 'DOM') { this._extractModelFromDOM(); } // generate and apply DOM var el = this._generateMarkup(); var parentEl = this._element.parentNode; if (!this._notFirstInit) { Aux.storeIdAndClasses(this._element, this); this._notFirstInit = true; } parentEl.insertBefore(el, this._element); parentEl.removeChild(this._element); this._element = el; Aux.restoreIdAndClasses(this._element, this); // subscribe events Event.observe(this._paginationEl, 'click', this._handlers.paginationClick); Event.observe(this._navEl, 'click', this._handlers.navClick); if (this._showThumbs) { Event.observe(this._thumbsUlEl, 'click', this._handlers.thumbsClick); } Event.observe(this._element, 'mouseover', this._handlers.focusBlur); Event.observe(this._element, 'mouseout', this._handlers.focusBlur); Event.observe(document, 'keydown', this._handlers.keyDown); Aux.registerInstance(this, this._element, 'gallery'); }, /** * Updates the model from the UL representation * * @method _extractModelFromDOM * @private */ _extractModelFromDOM: function() { /*global console:false */ var m = []; var dims; var liEls = Selector.select('> li', this._element); InkArray.each(liEls,function(liEl) { try { var d = { image_full: '', image_thumb: '', title_text: '', title_link: '', description: '', content_overlay: document.createDocumentFragment() }; var enclosureAEl = Selector.select('> a[rel=enclosure]', liEl)[0]; var thumbImgEl = Selector.select('> img', enclosureAEl)[0]; var bookmarkAEl = Selector.select('> a[class=bookmark]', liEl)[0]; var titleSpanEl = Selector.select('span[class=entry-title]', liEl)[0]; var entryContentSpanEl = Selector.select('> span[class=entry-content]', liEl)[0]; var contentOverlayEl = Selector.select('> .content-overlay', liEl)[0]; dims = enclosureAEl.getAttribute('data-dims'); if (dims !== null) { dims = dims.split(','); dims[0] = parseInt(dims[0], 10); dims[1] = parseInt(dims[1], 10); } if (dims && !isNaN(dims[0]) && !isNaN(dims[1])) { d.dims = dims; } d.image_full = enclosureAEl.getAttribute('href'); d.image_thumb = thumbImgEl.getAttribute('src'); if (bookmarkAEl) { d.title_link = bookmarkAEl.getAttribute('href'); } d.title_text = titleSpanEl.innerHTML; if (entryContentSpanEl) { d.description = entryContentSpanEl.innerHTML; } if(contentOverlayEl){ d.content_overlay.appendChild(contentOverlayEl); } m.push(d); } catch(ex) { console.error('problematic element:'); console.error(liEl); console.error(ex); throw new Error('Problem parsing gallery data from DOM!'); } }); this._model = m; }, /** * Returns the top element for the gallery DOM representation * * @method _generateMarkup * @private * @return {DOMElement} Returns the Gallery element totally rendered. */ _generateMarkup: function() { /*jshint maxstatements:80 */ var el = document.createElement('div'); el.className = 'ink-gallery'; var stageEl = document.createElement('div'); stageEl.className = 'stage'; // nav var navEl = document.createElement('nav'); navEl.innerHTML = [ '' ].join(''); this._navEl = navEl; // slider var sliderEl = document.createElement('div'); sliderEl.className = 'slider'; var ulEl = document.createElement('ul'); this._sliderUlEl = ulEl; var that = this; var W = this._options.fullImageMaxWidth; var H = this._options.fullImageMaxHeight; InkArray.each(this._model,function(d, i) { var liEl = document.createElement('li'); var imgEl = document.createElement('img'); imgEl.setAttribute('name', 'image ' + (i + 1)); imgEl.setAttribute('src', d.image_full); imgEl.setAttribute('alt', d.title_text); //imgEl.style.maxWidth = that._options.fullImageMaxWidth + 'px'; //imgEl.setAttribute('width', that._options.fullImageMaxWidth); // TODO? liEl.appendChild(imgEl); if(d.content_overlay){ if(d.content_overlay.nodeType === 1 || d.content_overlay.nodeType === 11){ d.content_overlay = liEl.appendChild(d.content_overlay); } else if(typeof d.content_overlay === 'string'){ var contentOverlayEl = document.createElement('div'); contentOverlayEl.className = 'content-overlay'; contentOverlayEl.innerHTML = d.content_overlay; d.content_overlay = liEl.appendChild(contentOverlayEl); } } ulEl.appendChild(liEl); if (that._options.fixImageSizes) { var dimsCb = function(dims) { //console.log(this, dims); var imgEl = this.img; var data = this.data; if (!data.dims) { data.dims = dims; } var dims2 = maximizeBox([W, H], dims); var w = dims2[0]; var h = dims2[1]; var dw = Math.floor( (W - w)/2 ); var dh = Math.floor( (H - h)/2 ); if (w !== W || h !== H) { imgEl.setAttribute('width', w); imgEl.setAttribute('height', h); var s = imgEl.style; if (dw > 0) { s.paddingLeft = dw + 'px'; } if (dh > 0) { s.paddingBottom = dh + 'px'; } } }; if (d.dims) { dimsCb.call( {img:imgEl, data:d}, d.dims); } else { getDimsAsync({img:imgEl, data:d}, dimsCb); } } }); sliderEl.appendChild(ulEl); this._sliderEl = sliderEl; // description var articleTextDivEl; if (this._showDescription) { var d = this._model[this._index]; articleTextDivEl = document.createElement('div'); articleTextDivEl.className = ['article_text', 'example' + (this._options.layout === 3 ? 2 : this._options.layout)].join(' '); if (d.title_link) { articleTextDivEl.innerHTML = ['