Cookies en esta web

Esta página web utiliza cookies de terceros para el análisis de visitas y comportamiento de usuarios. Puedes aceptar o rechazar las cookies de tu navegador con las siguientes opciones:

PLANTA DE QUÍMICA FINA

UNIVERSIDAD ALCALÁ DE HENARES

1993

BIBLIOTECA PÚBLICA DEL ESTADO

MINISTERIO DE CULTURA

NITIDUS ARQUITECTOS

2011

EDIFICIO FOMENTO DEL TRABAJO

CAIXA CATALUNYA

DAMIÁN RIBAS ARQUITECTO

2009

EDIFICIO JUDICIAL DE GERONA

GENERALITAT DE CATALUNYA

BOSCH TARRÚS ARQUITECTOS

2009

MERCADO MUNICIPAL "FONDO"

MAIRIE DE SANTA COLOMA DE GRAMANET

PICH AGUILERA ARCHITECTS

2008

CAMPOS DE FÚTBOL F.C. DAMM

CLUB DE FÚTBOL DAMM

ALONSO & BALAGUER

2002

ESTADIO OLÍMPICO, TÚNEZ

FERROVIAL - AGROMAN

A.A ARQUITECTES

1998

VIVIENDAS, CENTRO CIVICO Y APARCAMIENTO

PATRONATO MUNICIPAL DE LA VIVIENDA DE BARCELONA

NOGUÉ ONZAIN LÓPEZ ARQUITECTOS

2007

VIVIENDAS FIRA 2000

FIRA 2000

NOGUÉ ONZAIN LÓPEZ ARQUITECTOS

2007

VIVIENDAS BARRIO LA MINA

INCASOL

BAMMP ARQUITECTOS Y ASOCIADOS

2007

VIVIENDAS SOCIALES SANT ANDREU

INCASOL

LÓPEZ RIVERA ARQUITECTOS

2003

HOTEL WESTIN PALACE MADRID

MARRIOT

RUIZ - LARREA & ASOCIADOS

2022

PLANTA LOGÍSTICA MOUNTPARK - GSE

MOUNTPARK-GSE

PGI TORRELLA

NAVE LOGÍSTICA EES2 AMAZON

DRAGADOS

OFICINAS SOLVIA

080 ARQUITECTURA

NAVE LOGÍSTICA FEDEFARMA

FEDERACIÓ FARMACÈUTICA S.C.C.L

PGI TORRELLA

2018

CONCESIONARIO MAZDA

ZAPATA

2015

D'FACTORY 4.0

CONSORCI DE LA ZONA FRANCA

PGI TORRELLA

OFICINAS THÉA PHARMA

2020

TSH COWORKING HOTEL

NUEVA PLANTA LOGÍSTICA VGP PARKS ESPAÑA

VGP PARKS ESPAÑA

PGI TORRELLA

NAVE LOGÍSTICA VGP PARKS ESPAÑA

VGP PARKS ESPAÑA

PGI TORRELLA

NUEVA PLANTA LOGÍSTICA SEGRO

SEGRO

PGI TORRELLA

CENTRO LOGÍSTICO & ALMACÉN ROBOTIZADO MASSIMO DUTTI

INDITEX

PGI TORRELLA

NUEVO SILO MASSIMO DUTTI

PGI TORRELLA

LAVANDERÍA INDUSTRIAL ELIS MANOMATIC

PGI TORRELLA

PLANTA PROCESAMIENTO PERLITA IMERYS

IMERYS ELIS

PGI TORRELLA

PERNILS BUFALVENT

PERNILS BUFALVENT S.L.

PGI TORRELLA

CENTRO LOGÍSTICO DESIGUAL

DESIGUAL

PGI TORRELLA

RECINTO INDUSTRIAL ABELLÓ LINDE

ABELLÓ LINDE S.A.

PGI TORRELLA

Filtrar proyectos
nction( elem, selector ) { while ( elem.parentNode && elem != document.body ) { elem = elem.parentNode; if ( matchesSelector( elem, selector ) ) { return elem; } } }; // ----- getQueryElement ----- // // use element as selector string utils.getQueryElement = function( elem ) { if ( typeof elem == 'string' ) { return document.querySelector( elem ); } return elem; }; // ----- handleEvent ----- // // enable .ontype to trigger from .addEventListener( elem, 'type' ) utils.handleEvent = function( event ) { var method = 'on' + event.type; if ( this[ method ] ) { this[ method ]( event ); } }; // ----- filterFindElements ----- // utils.filterFindElements = function( elems, selector ) { // make array of elems elems = utils.makeArray( elems ); var ffElems = []; elems.forEach( function( elem ) { // check that elem is an actual element if ( !( elem instanceof HTMLElement ) ) { return; } // add elem if no selector if ( !selector ) { ffElems.push( elem ); return; } // filter & find items if we have a selector // filter if ( matchesSelector( elem, selector ) ) { ffElems.push( elem ); } // find children var childElems = elem.querySelectorAll( selector ); // concat childElems to filterFound array for ( var i=0; i < childElems.length; i++ ) { ffElems.push( childElems[i] ); } }); return ffElems; }; // ----- debounceMethod ----- // utils.debounceMethod = function( _class, methodName, threshold ) { threshold = threshold || 100; // original method var method = _class.prototype[ methodName ]; var timeoutName = methodName + 'Timeout'; _class.prototype[ methodName ] = function() { var timeout = this[ timeoutName ]; clearTimeout( timeout ); var args = arguments; var _this = this; this[ timeoutName ] = setTimeout( function() { method.apply( _this, args ); delete _this[ timeoutName ]; }, threshold ); }; }; // ----- docReady ----- // utils.docReady = function( callback ) { var readyState = document.readyState; if ( readyState == 'complete' || readyState == 'interactive' ) { // do async to allow for other scripts to run. metafizzy/flickity#441 setTimeout( callback ); } else { document.addEventListener( 'DOMContentLoaded', callback ); } }; // ----- htmlInit ----- // // http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ utils.toDashed = function( str ) { return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { return $1 + '-' + $2; }).toLowerCase(); }; var console = window.console; /** * allow user to initialize classes via [data-namespace] or .js-namespace class * htmlInit( Widget, 'widgetName' ) * options are parsed from data-namespace-options */ utils.htmlInit = function( WidgetClass, namespace ) { utils.docReady( function() { var dashedNamespace = utils.toDashed( namespace ); var dataAttr = 'data-' + dashedNamespace; var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); var elems = utils.makeArray( dataAttrElems ) .concat( utils.makeArray( jsDashElems ) ); var dataOptionsAttr = dataAttr + '-options'; var jQuery = window.jQuery; elems.forEach( function( elem ) { var attr = elem.getAttribute( dataAttr ) || elem.getAttribute( dataOptionsAttr ); var options; try { options = attr && JSON.parse( attr ); } catch ( error ) { // log error, do not initialize if ( console ) { console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + ': ' + error ); } return; } // initialize var instance = new WidgetClass( elem, options ); // make available via $().data('namespace') if ( jQuery ) { jQuery.data( elem, namespace, instance ); } }); }); }; // ----- ----- // return utils; })); /** * Outlayer Item */ ( function( window, factory ) { // universal module definition /* jshint strict: false */ /* globals define, module, require */ if ( typeof define == 'function' && define.amd ) { // AMD - RequireJS define( 'outlayer/item',[ 'ev-emitter/ev-emitter', 'get-size/get-size' ], factory ); } else if ( typeof module == 'object' && module.exports ) { // CommonJS - Browserify, Webpack module.exports = factory( require('ev-emitter'), require('get-size') ); } else { // browser global window.Outlayer = {}; window.Outlayer.Item = factory( window.EvEmitter, window.getSize ); } }( window, function factory( EvEmitter, getSize ) { 'use strict'; // ----- helpers ----- // function isEmptyObj( obj ) { for ( var prop in obj ) { return false; } prop = null; return true; } // -------------------------- CSS3 support -------------------------- // var docElemStyle = document.documentElement.style; var transitionProperty = typeof docElemStyle.transition == 'string' ? 'transition' : 'WebkitTransition'; var transformProperty = typeof docElemStyle.transform == 'string' ? 'transform' : 'WebkitTransform'; var transitionEndEvent = { WebkitTransition: 'webkitTransitionEnd', transition: 'transitionend' }[ transitionProperty ]; // cache all vendor properties that could have vendor prefix var vendorProperties = { transform: transformProperty, transition: transitionProperty, transitionDuration: transitionProperty + 'Duration', transitionProperty: transitionProperty + 'Property', transitionDelay: transitionProperty + 'Delay' }; // -------------------------- Item -------------------------- // function Item( element, layout ) { if ( !element ) { return; } this.element = element; // parent layout class, i.e. Masonry, Isotope, or Packery this.layout = layout; this.position = { x: 0, y: 0 }; this._create(); } // inherit EvEmitter var proto = Item.prototype = Object.create( EvEmitter.prototype ); proto.constructor = Item; proto._create = function() { // transition objects this._transn = { ingProperties: {}, clean: {}, onEnd: {} }; this.css({ position: 'absolute' }); }; // trigger specified handler for event type proto.handleEvent = function( event ) { var method = 'on' + event.type; if ( this[ method ] ) { this[ method ]( event ); } }; proto.getSize = function() { this.size = getSize( this.element ); }; /** * apply CSS styles to element * @param {Object} style */ proto.css = function( style ) { var elemStyle = this.element.style; for ( var prop in style ) { // use vendor property if available var supportedProp = vendorProperties[ prop ] || prop; elemStyle[ supportedProp ] = style[ prop ]; } }; // measure position, and sets it proto.getPosition = function() { var style = getComputedStyle( this.element ); var isOriginLeft = this.layout._getOption('originLeft'); var isOriginTop = this.layout._getOption('originTop'); var xValue = style[ isOriginLeft ? 'left' : 'right' ]; var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; var x = parseFloat( xValue ); var y = parseFloat( yValue ); // convert percent to pixels var layoutSize = this.layout.size; if ( xValue.indexOf('%') != -1 ) { x = ( x / 100 ) * layoutSize.width; } if ( yValue.indexOf('%') != -1 ) { y = ( y / 100 ) * layoutSize.height; } // clean up 'auto' or other non-integer values x = isNaN( x ) ? 0 : x; y = isNaN( y ) ? 0 : y; // remove padding from measurement x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; this.position.x = x; this.position.y = y; }; // set settled position, apply padding proto.layoutPosition = function() { var layoutSize = this.layout.size; var style = {}; var isOriginLeft = this.layout._getOption('originLeft'); var isOriginTop = this.layout._getOption('originTop'); // x var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; var xProperty = isOriginLeft ? 'left' : 'right'; var xResetProperty = isOriginLeft ? 'right' : 'left'; var x = this.position.x + layoutSize[ xPadding ]; // set in percentage or pixels style[ xProperty ] = this.getXValue( x ); // reset other property style[ xResetProperty ] = ''; // y var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; var yProperty = isOriginTop ? 'top' : 'bottom'; var yResetProperty = isOriginTop ? 'bottom' : 'top'; var y = this.position.y + layoutSize[ yPadding ]; // set in percentage or pixels style[ yProperty ] = this.getYValue( y ); // reset other property style[ yResetProperty ] = ''; this.css( style ); this.emitEvent( 'layout', [ this ] ); }; proto.getXValue = function( x ) { var isHorizontal = this.layout._getOption('horizontal'); return this.layout.options.percentPosition && !isHorizontal ? ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; }; proto.getYValue = function( y ) { var isHorizontal = this.layout._getOption('horizontal'); return this.layout.options.percentPosition && isHorizontal ? ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; }; proto._transitionTo = function( x, y ) { this.getPosition(); // get current x & y from top/left var curX = this.position.x; var curY = this.position.y; var didNotMove = x == this.position.x && y == this.position.y; // save end position this.setPosition( x, y ); // if did not move and not transitioning, just go to layout if ( didNotMove && !this.isTransitioning ) { this.layoutPosition(); return; } var transX = x - curX; var transY = y - curY; var transitionStyle = {}; transitionStyle.transform = this.getTranslate( transX, transY ); this.transition({ to: transitionStyle, onTransitionEnd: { transform: this.layoutPosition }, isCleaning: true }); }; proto.getTranslate = function( x, y ) { // flip cooridinates if origin on right or bottom var isOriginLeft = this.layout._getOption('originLeft'); var isOriginTop = this.layout._getOption('originTop'); x = isOriginLeft ? x : -x; y = isOriginTop ? y : -y; return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; }; // non transition + transform support proto.goTo = function( x, y ) { this.setPosition( x, y ); this.layoutPosition(); }; proto.moveTo = proto._transitionTo; proto.setPosition = function( x, y ) { this.position.x = parseFloat( x ); this.position.y = parseFloat( y ); }; // ----- transition ----- // /** * @param {Object} style - CSS * @param {Function} onTransitionEnd */ // non transition, just trigger callback proto._nonTransition = function( args ) { this.css( args.to ); if ( args.isCleaning ) { this._removeStyles( args.to ); } for ( var prop in args.onTransitionEnd ) { args.onTransitionEnd[ prop ].call( this ); } }; /** * proper transition * @param {Object} args - arguments * @param {Object} to - style to transition to * @param {Object} from - style to start transition from * @param {Boolean} isCleaning - removes transition styles after transition * @param {Function} onTransitionEnd - callback */ proto.transition = function( args ) { // redirect to nonTransition if no transition duration if ( !parseFloat( this.layout.options.transitionDuration ) ) { this._nonTransition( args ); return; } var _transition = this._transn; // keep track of onTransitionEnd callback by css property for ( var prop in args.onTransitionEnd ) { _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; } // keep track of properties that are transitioning for ( prop in args.to ) { _transition.ingProperties[ prop ] = true; // keep track of properties to clean up when transition is done if ( args.isCleaning ) { _transition.clean[ prop ] = true; } } // set from styles if ( args.from ) { this.css( args.from ); // force redraw. http://blog.alexmaccaw.com/css-transitions var h = this.element.offsetHeight; // hack for JSHint to hush about unused var h = null; } // enable transition this.enableTransition( args.to ); // set styles that are transitioning this.css( args.to ); this.isTransitioning = true; }; // dash before all cap letters, including first for // WebkitTransform => -webkit-transform function toDashedAll( str ) { return str.replace( /([A-Z])/g, function( $1 ) { return '-' + $1.toLowerCase(); }); } var transitionProps = 'opacity,' + toDashedAll( transformProperty ); proto.enableTransition = function(/* style */) { // HACK changing transitionProperty during a transition // will cause transition to jump if ( this.isTransitioning ) { return; } // make `transition: foo, bar, baz` from style object // HACK un-comment this when enableTransition can work // while a transition is happening // var transitionValues = []; // for ( var prop in style ) { // // dash-ify camelCased properties like WebkitTransition // prop = vendorProperties[ prop ] || prop; // transitionValues.push( toDashedAll( prop ) ); // } // munge number to millisecond, to match stagger var duration = this.layout.options.transitionDuration; duration = typeof duration == 'number' ? duration + 'ms' : duration; // enable transition styles this.css({ transitionProperty: transitionProps, transitionDuration: duration, transitionDelay: this.staggerDelay || 0 }); // listen for transition end event this.element.addEventListener( transitionEndEvent, this, false ); }; // ----- events ----- // proto.onwebkitTransitionEnd = function( event ) { this.ontransitionend( event ); }; proto.onotransitionend = function( event ) { this.ontransitionend( event ); }; // properties that I munge to make my life easier var dashedVendorProperties = { '-webkit-transform': 'transform' }; proto.ontransitionend = function( event ) { // disregard bubbled events from children if ( event.target !== this.element ) { return; } var _transition = this._transn; // get property name of transitioned property, convert to prefix-free var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; // remove property that has completed transitioning delete _transition.ingProperties[ propertyName ]; // check if any properties are still transitioning if ( isEmptyObj( _transition.ingProperties ) ) { // all properties have completed transitioning this.disableTransition(); } // clean style if ( propertyName in _transition.clean ) { // clean up style this.element.style[ event.propertyName ] = ''; delete _transition.clean[ propertyName ]; } // trigger onTransitionEnd callback if ( propertyName in _transition.onEnd ) { var onTransitionEnd = _transition.onEnd[ propertyName ]; onTransitionEnd.call( this ); delete _transition.onEnd[ propertyName ]; } this.emitEvent( 'transitionEnd', [ this ] ); }; proto.disableTransition = function() { this.removeTransitionStyles(); this.element.removeEventListener( transitionEndEvent, this, false ); this.isTransitioning = false; }; /** * removes style property from element * @param {Object} style **/ proto._removeStyles = function( style ) { // clean up transition styles var cleanStyle = {}; for ( var prop in style ) { cleanStyle[ prop ] = ''; } this.css( cleanStyle ); }; var cleanTransitionStyle = { transitionProperty: '', transitionDuration: '', transitionDelay: '' }; proto.removeTransitionStyles = function() { // remove transition this.css( cleanTransitionStyle ); }; // ----- stagger ----- // proto.stagger = function( delay ) { delay = isNaN( delay ) ? 0 : delay; this.staggerDelay = delay + 'ms'; }; // ----- show/hide/remove ----- // // remove element from DOM proto.removeElem = function() { this.element.parentNode.removeChild( this.element ); // remove display: none this.css({ display: '' }); this.emitEvent( 'remove', [ this ] ); }; proto.remove = function() { // just remove element if no transition support or no transition if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { this.removeElem(); return; } // start transition this.once( 'transitionEnd', function() { this.removeElem(); }); this.hide(); }; proto.reveal = function() { delete this.isHidden; // remove display: none this.css({ display: '' }); var options = this.layout.options; var onTransitionEnd = {}; var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; this.transition({ from: options.hiddenStyle, to: options.visibleStyle, isCleaning: true, onTransitionEnd: onTransitionEnd }); }; proto.onRevealTransitionEnd = function() { // check if still visible // during transition, item may have been hidden if ( !this.isHidden ) { this.emitEvent('reveal'); } }; /** * get style property use for hide/reveal transition end * @param {String} styleProperty - hiddenStyle/visibleStyle * @returns {String} */ proto.getHideRevealTransitionEndProperty = function( styleProperty ) { var optionStyle = this.layout.options[ styleProperty ]; // use opacity if ( optionStyle.opacity ) { return 'opacity'; } // get first property for ( var prop in optionStyle ) { return prop; } }; proto.hide = function() { // set flag this.isHidden = true; // remove display: none this.css({ display: '' }); var options = this.layout.options; var onTransitionEnd = {}; var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; this.transition({ from: options.visibleStyle, to: options.hiddenStyle, // keep hidden stuff hidden isCleaning: true, onTransitionEnd: onTransitionEnd }); }; proto.onHideTransitionEnd = function() { // check if still hidden // during transition, item may have been un-hidden if ( this.isHidden ) { this.css({ display: 'none' }); this.emitEvent('hide'); } }; proto.destroy = function() { this.css({ position: '', left: '', right: '', top: '', bottom: '', transition: '', transform: '' }); }; return Item; })); /*! * Outlayer v2.1.1 * the brains and guts of a layout library * MIT license */ ( function( window, factory ) { 'use strict'; // universal module definition /* jshint strict: false */ /* globals define, module, require */ if ( typeof define == 'function' && define.amd ) { // AMD - RequireJS define( 'outlayer/outlayer',[ 'ev-emitter/ev-emitter', 'get-size/get-size', 'fizzy-ui-utils/utils', './item' ], function( EvEmitter, getSize, utils, Item ) { return factory( window, EvEmitter, getSize, utils, Item); } ); } else if ( typeof module == 'object' && module.exports ) { // CommonJS - Browserify, Webpack module.exports = factory( window, require('ev-emitter'), require('get-size'), require('fizzy-ui-utils'), require('./item') ); } else { // browser global window.Outlayer = factory( window, window.EvEmitter, window.getSize, window.fizzyUIUtils, window.Outlayer.Item ); } }( window, function factory( window, EvEmitter, getSize, utils, Item ) { 'use strict'; // ----- vars ----- // var console = window.console; var jQuery = window.jQuery; var noop = function() {}; // -------------------------- Outlayer -------------------------- // // globally unique identifiers var GUID = 0; // internal store of all Outlayer intances var instances = {}; /** * @param {Element, String} element * @param {Object} options * @constructor */ function Outlayer( element, options ) { var queryElement = utils.getQueryElement( element ); if ( !queryElement ) { if ( console ) { console.error( 'Bad element for ' + this.constructor.namespace + ': ' + ( queryElement || element ) ); } return; } this.element = queryElement; // add jQuery if ( jQuery ) { this.$element = jQuery( this.element ); } // options this.options = utils.extend( {}, this.constructor.defaults ); this.option( options ); // add id for Outlayer.getFromElement var id = ++GUID; this.element.outlayerGUID = id; // expando instances[ id ] = this; // associate via id // kick it off this._create(); var isInitLayout = this._getOption('initLayout'); if ( isInitLayout ) { this.layout(); } } // settings are for internal use only Outlayer.namespace = 'outlayer'; Outlayer.Item = Item; // default options Outlayer.defaults = { containerStyle: { position: 'relative' }, initLayout: true, originLeft: true, originTop: true, resize: true, resizeContainer: true, // item options transitionDuration: '0.4s', hiddenStyle: { opacity: 0, transform: 'scale(0.001)' }, visibleStyle: { opacity: 1, transform: 'scale(1)' } }; var proto = Outlayer.prototype; // inherit EvEmitter utils.extend( proto, EvEmitter.prototype ); /** * set options * @param {Object} opts */ proto.option = function( opts ) { utils.extend( this.options, opts ); }; /** * get backwards compatible option value, check old name */ proto._getOption = function( option ) { var oldOption = this.constructor.compatOptions[ option ]; return oldOption && this.options[ oldOption ] !== undefined ? this.options[ oldOption ] : this.options[ option ]; }; Outlayer.compatOptions = { // currentName: oldName initLayout: 'isInitLayout', horizontal: 'isHorizontal', layoutInstant: 'isLayoutInstant', originLeft: 'isOriginLeft', originTop: 'isOriginTop', resize: 'isResizeBound', resizeContainer: 'isResizingContainer' }; proto._create = function() { // get items from children this.reloadItems(); // elements that affect layout, but are not laid out this.stamps = []; this.stamp( this.options.stamp ); // set container style utils.extend( this.element.style, this.options.containerStyle ); // bind resize method var canBindResize = this._getOption('resize'); if ( canBindResize ) { this.bindResize(); } }; // goes through all children again and gets bricks in proper order proto.reloadItems = function() { // collection of item elements this.items = this._itemize( this.element.children ); }; /** * turn elements into Outlayer.Items to be used in layout * @param {Array or NodeList or HTMLElement} elems * @returns {Array} items - collection of new Outlayer Items */ proto._itemize = function( elems ) { var itemElems = this._filterFindItemElements( elems ); var Item = this.constructor.Item; // create new Outlayer Items for collection var items = []; for ( var i=0; i < itemElems.length; i++ ) { var elem = itemElems[i]; var item = new Item( elem, this ); items.push( item ); } return items; }; /** * get item elements to be used in layout * @param {Array or NodeList or HTMLElement} elems * @returns {Array} items - item elements */ proto._filterFindItemElements = function( elems ) { return utils.filterFindElements( elems, this.options.itemSelector ); }; /** * getter method for getting item elements * @returns {Array} elems - collection of item elements */ proto.getItemElements = function() { return this.items.map( function( item ) { return item.element; }); }; // ----- init & layout ----- // /** * lays out all items */ proto.layout = function() { this._resetLayout(); this._manageStamps(); // don't animate first layout var layoutInstant = this._getOption('layoutInstant'); var isInstant = layoutInstant !== undefined ? layoutInstant : !this._isLayoutInited; this.layoutItems( this.items, isInstant ); // flag for initalized this._isLayoutInited = true; }; // _init is alias for layout proto._init = proto.layout; /** * logic before any new layout */ proto._resetLayout = function() { this.getSize(); }; proto.getSize = function() { this.size = getSize( this.element ); }; /** * get measurement from option, for columnWidth, rowHeight, gutter * if option is String -> get element from selector string, & get size of element * if option is Element -> get size of element * else use option as a number * * @param {String} measurement * @param {String} size - width or height * @private */ proto._getMeasurement = function( measurement, size ) { var option = this.options[ measurement ]; var elem; if ( !option ) { // default to 0 this[ measurement ] = 0; } else { // use option as an element if ( typeof option == 'string' ) { elem = this.element.querySelector( option ); } else if ( option instanceof HTMLElement ) { elem = option; } // use size of element, if element this[ measurement ] = elem ? getSize( elem )[ size ] : option; } }; /** * layout a collection of item elements * @api public */ proto.layoutItems = function( items, isInstant ) { items = this._getItemsForLayout( items ); this._layoutItems( items, isInstant ); this._postLayout(); }; /** * get the items to be laid out * you may want to skip over some items * @param {Array} items * @returns {Array} items */ proto._getItemsForLayout = function( items ) { return items.filter( function( item ) { return !item.isIgnored; }); }; /** * layout items * @param {Array} items * @param {Boolean} isInstant */ proto._layoutItems = function( items, isInstant ) { this._emitCompleteOnItems( 'layout', items ); if ( !items || !items.length ) { // no items, emit event with empty array return; } var queue = []; items.forEach( function( item ) { // get x/y object from method var position = this._getItemLayoutPosition( item ); // enqueue position.item = item; position.isInstant = isInstant || item.isLayoutInstant; queue.push( position ); }, this ); this._processLayoutQueue( queue ); }; /** * get item layout position * @param {Outlayer.Item} item * @returns {Object} x and y position */ proto._getItemLayoutPosition = function( /* item */ ) { return { x: 0, y: 0 }; }; /** * iterate over array and position each item * Reason being - separating this logic prevents 'layout invalidation' * thx @paul_irish * @param {Array} queue */ proto._processLayoutQueue = function( queue ) { this.updateStagger(); queue.forEach( function( obj, i ) { this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); }, this ); }; // set stagger from option in milliseconds number proto.updateStagger = function() { var stagger = this.options.stagger; if ( stagger === null || stagger === undefined ) { this.stagger = 0; return; } this.stagger = getMilliseconds( stagger ); return this.stagger; }; /** * Sets position of item in DOM * @param {Outlayer.Item} item * @param {Number} x - horizontal position * @param {Number} y - vertical position * @param {Boolean} isInstant - disables transitions */ proto._positionItem = function( item, x, y, isInstant, i ) { if ( isInstant ) { // if not transition, just set CSS item.goTo( x, y ); } else { item.stagger( i * this.stagger ); item.moveTo( x, y ); } }; /** * Any logic you want to do after each layout, * i.e. size the container */ proto._postLayout = function() { this.resizeContainer(); }; proto.resizeContainer = function() { var isResizingContainer = this._getOption('resizeContainer'); if ( !isResizingContainer ) { return; } var size = this._getContainerSize(); if ( size ) { this._setContainerMeasure( size.width, true ); this._setContainerMeasure( size.height, false ); } }; /** * Sets width or height of container if returned * @returns {Object} size * @param {Number} width * @param {Number} height */ proto._getContainerSize = noop; /** * @param {Number} measure - size of width or height * @param {Boolean} isWidth */ proto._setContainerMeasure = function( measure, isWidth ) { if ( measure === undefined ) { return; } var elemSize = this.size; // add padding and border width if border box if ( elemSize.isBorderBox ) { measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + elemSize.borderLeftWidth + elemSize.borderRightWidth : elemSize.paddingBottom + elemSize.paddingTop + elemSize.borderTopWidth + elemSize.borderBottomWidth; } measure = Math.max( measure, 0 ); this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; }; /** * emit eventComplete on a collection of items events * @param {String} eventName * @param {Array} items - Outlayer.Items */ proto._emitCompleteOnItems = function( eventName, items ) { var _this = this; function onComplete() { _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); } var count = items.length; if ( !items || !count ) { onComplete(); return; } var doneCount = 0; function tick() { doneCount++; if ( doneCount == count ) { onComplete(); } } // bind callback items.forEach( function( item ) { item.once( eventName, tick ); }); }; /** * emits events via EvEmitter and jQuery events * @param {String} type - name of event * @param {Event} event - original event * @param {Array} args - extra arguments */ proto.dispatchEvent = function( type, event, args ) { // add original event to arguments var emitArgs = event ? [ event ].concat( args ) : args; this.emitEvent( type, emitArgs ); if ( jQuery ) { // set this.$element this.$element = this.$element || jQuery( this.element ); if ( event ) { // create jQuery event var $event = jQuery.Event( event ); $event.type = type; this.$element.trigger( $event, args ); } else { // just trigger with type if no event available this.$element.trigger( type, args ); } } }; // -------------------------- ignore & stamps -------------------------- // /** * keep item in collection, but do not lay it out * ignored items do not get skipped in layout * @param {Element} elem */ proto.ignore = function( elem ) { var item = this.getItem( elem ); if ( item ) { item.isIgnored = true; } }; /** * return item to layout collection * @param {Element} elem */ proto.unignore = function( elem ) { var item = this.getItem( elem ); if ( item ) { delete item.isIgnored; } }; /** * adds elements to stamps * @param {NodeList, Array, Element, or String} elems */ proto.stamp = function( elems ) { elems = this._find( elems ); if ( !elems ) { return; } this.stamps = this.stamps.concat( elems ); // ignore elems.forEach( this.ignore, this ); }; /** * removes elements to stamps * @param {NodeList, Array, or Element} elems */ proto.unstamp = function( elems ) { elems = this._find( elems ); if ( !elems ){ return; } elems.forEach( function( elem ) { // filter out removed stamp elements utils.removeFrom( this.stamps, elem ); this.unignore( elem ); }, this ); }; /** * finds child elements * @param {NodeList, Array, Element, or String} elems * @returns {Array} elems */ proto._find = function( elems ) { if ( !elems ) { return; } // if string, use argument as selector string if ( typeof elems == 'string' ) { elems = this.element.querySelectorAll( elems ); } elems = utils.makeArray( elems ); return elems; }; proto._manageStamps = function() { if ( !this.stamps || !this.stamps.length ) { return; } this._getBoundingRect(); this.stamps.forEach( this._manageStamp, this ); }; // update boundingLeft / Top proto._getBoundingRect = function() { // get bounding rect for container element var boundingRect = this.element.getBoundingClientRect(); var size = this.size; this._boundingRect = { left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, top: boundingRect.top + size.paddingTop + size.borderTopWidth, right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) }; }; /** * @param {Element} stamp **/ proto._manageStamp = noop; /** * get x/y position of element relative to container element * @param {Element} elem * @returns {Object} offset - has left, top, right, bottom */ proto._getElementOffset = function( elem ) { var boundingRect = elem.getBoundingClientRect(); var thisRect = this._boundingRect; var size = getSize( elem ); var offset = { left: boundingRect.left - thisRect.left - size.marginLeft, top: boundingRect.top - thisRect.top - size.marginTop, right: thisRect.right - boundingRect.right - size.marginRight, bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom }; return offset; }; // -------------------------- resize -------------------------- // // enable event handlers for listeners // i.e. resize -> onresize proto.handleEvent = utils.handleEvent; /** * Bind layout to window resizing */ proto.bindResize = function() { window.addEventListener( 'resize', this ); this.isResizeBound = true; }; /** * Unbind layout to window resizing */ proto.unbindResize = function() { window.removeEventListener( 'resize', this ); this.isResizeBound = false; }; proto.onresize = function() { this.resize(); }; utils.debounceMethod( Outlayer, 'onresize', 100 ); proto.resize = function() { // don't trigger if size did not change // or if resize was unbound. See #9 if ( !this.isResizeBound || !this.needsResizeLayout() ) { return; } this.layout(); }; /** * check if layout is needed post layout * @returns Boolean */ proto.needsResizeLayout = function() { var size = getSize( this.element ); // check that this.size and size are there // IE8 triggers resize on body size change, so they might not be var hasSizes = this.size && size; return hasSizes && size.innerWidth !== this.size.innerWidth; }; // -------------------------- methods -------------------------- // /** * add items to Outlayer instance * @param {Array or NodeList or Element} elems * @returns {Array} items - Outlayer.Items **/ proto.addItems = function( elems ) { var items = this._itemize( elems ); // add items to collection if ( items.length ) { this.items = this.items.concat( items ); } return items; }; /** * Layout newly-appended item elements * @param {Array or NodeList or Element} elems */ proto.appended = function( elems ) { var items = this.addItems( elems ); if ( !items.length ) { return; } // layout and reveal just the new items this.layoutItems( items, true ); this.reveal( items ); }; /** * Layout prepended elements * @param {Array or NodeList or Element} elems */ proto.prepended = function( elems ) { var items = this._itemize( elems ); if ( !items.length ) { return; } // add items to beginning of collection var previousItems = this.items.slice(0); this.items = items.concat( previousItems ); // start new layout this._resetLayout(); this._manageStamps(); // layout new stuff without transition this.layoutItems( items, true ); this.reveal( items ); // layout previous items this.layoutItems( previousItems ); }; /** * reveal a collection of items * @param {Array of Outlayer.Items} items */ proto.reveal = function( items ) { this._emitCompleteOnItems( 'reveal', items ); if ( !items || !items.length ) { return; } var stagger = this.updateStagger(); items.forEach( function( item, i ) { item.stagger( i * stagger ); item.reveal(); }); }; /** * hide a collection of items * @param {Array of Outlayer.Items} items */ proto.hide = function( items ) { this._emitCompleteOnItems( 'hide', items ); if ( !items || !items.length ) { return; } var stagger = this.updateStagger(); items.forEach( function( item, i ) { item.stagger( i * stagger ); item.hide(); }); }; /** * reveal item elements * @param {Array}, {Element}, {NodeList} items */ proto.revealItemElements = function( elems ) { var items = this.getItems( elems ); this.reveal( items ); }; /** * hide item elements * @param {Array}, {Element}, {NodeList} items */ proto.hideItemElements = function( elems ) { var items = this.getItems( elems ); this.hide( items ); }; /** * get Outlayer.Item, given an Element * @param {Element} elem * @param {Function} callback * @returns {Outlayer.Item} item */ proto.getItem = function( elem ) { // loop through items to get the one that matches for ( var i=0; i < this.items.length; i++ ) { var item = this.items[i]; if ( item.element == elem ) { // return item return item; } } }; /** * get collection of Outlayer.Items, given Elements * @param {Array} elems * @returns {Array} items - Outlayer.Items */ proto.getItems = function( elems ) { elems = utils.makeArray( elems ); var items = []; elems.forEach( function( elem ) { var item = this.getItem( elem ); if ( item ) { items.push( item ); } }, this ); return items; }; /** * remove element(s) from instance and DOM * @param {Array or NodeList or Element} elems */ proto.remove = function( elems ) { var removeItems = this.getItems( elems ); this._emitCompleteOnItems( 'remove', removeItems ); // bail if no items to remove if ( !removeItems || !removeItems.length ) { return; } removeItems.forEach( function( item ) { item.remove(); // remove item from collection utils.removeFrom( this.items, item ); }, this ); }; // ----- destroy ----- // // remove and disable Outlayer instance proto.destroy = function() { // clean up dynamic styles var style = this.element.style; style.height = ''; style.position = ''; style.width = ''; // destroy items this.items.forEach( function( item ) { item.destroy(); }); this.unbindResize(); var id = this.element.outlayerGUID; delete instances[ id ]; // remove reference to instance by id delete this.element.outlayerGUID; // remove data for jQuery if ( jQuery ) { jQuery.removeData( this.element, this.constructor.namespace ); } }; // -------------------------- data -------------------------- // /** * get Outlayer instance from element * @param {Element} elem * @returns {Outlayer} */ Outlayer.data = function( elem ) { elem = utils.getQueryElement( elem ); var id = elem && elem.outlayerGUID; return id && instances[ id ]; }; // -------------------------- create Outlayer class -------------------------- // /** * create a layout class * @param {String} namespace */ Outlayer.create = function( namespace, options ) { // sub-class Outlayer var Layout = subclass( Outlayer ); // apply new options and compatOptions Layout.defaults = utils.extend( {}, Outlayer.defaults ); utils.extend( Layout.defaults, options ); Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); Layout.namespace = namespace; Layout.data = Outlayer.data; // sub-class Item Layout.Item = subclass( Item ); // -------------------------- declarative -------------------------- // utils.htmlInit( Layout, namespace ); // -------------------------- jQuery bridge -------------------------- // // make into jQuery plugin if ( jQuery && jQuery.bridget ) { jQuery.bridget( namespace, Layout ); } return Layout; }; function subclass( Parent ) { function SubClass() { Parent.apply( this, arguments ); } SubClass.prototype = Object.create( Parent.prototype ); SubClass.prototype.constructor = SubClass; return SubClass; } // ----- helpers ----- // // how many milliseconds are in each unit var msUnits = { ms: 1, s: 1000 }; // munge time-like parameter into millisecond number // '0.4s' -> 40 function getMilliseconds( time ) { if ( typeof time == 'number' ) { return time; } var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); var num = matches && matches[1]; var unit = matches && matches[2]; if ( !num.length ) { return 0; } num = parseFloat( num ); var mult = msUnits[ unit ] || 1; return num * mult; } // ----- fin ----- // // back in global Outlayer.Item = Item; return Outlayer; })); /*! * Masonry v4.2.2 * Cascading grid layout library * https://masonry.desandro.com * MIT License * by David DeSandro */ ( function( window, factory ) { // universal module definition /* jshint strict: false */ /*globals define, module, require */ if ( typeof define == 'function' && define.amd ) { // AMD define( [ 'outlayer/outlayer', 'get-size/get-size' ], factory ); } else if ( typeof module == 'object' && module.exports ) { // CommonJS module.exports = factory( require('outlayer'), require('get-size') ); } else { // browser global window.Masonry = factory( window.Outlayer, window.getSize ); } }( window, function factory( Outlayer, getSize ) { // -------------------------- masonryDefinition -------------------------- // // create an Outlayer layout class var Masonry = Outlayer.create('masonry'); // isFitWidth -> fitWidth Masonry.compatOptions.fitWidth = 'isFitWidth'; var proto = Masonry.prototype; proto._resetLayout = function() { this.getSize(); this._getMeasurement( 'columnWidth', 'outerWidth' ); this._getMeasurement( 'gutter', 'outerWidth' ); this.measureColumns(); // reset column Y this.colYs = []; for ( var i=0; i < this.cols; i++ ) { this.colYs.push( 0 ); } this.maxY = 0; this.horizontalColIndex = 0; }; proto.measureColumns = function() { this.getContainerWidth(); // if columnWidth is 0, default to outerWidth of first item if ( !this.columnWidth ) { var firstItem = this.items[0]; var firstItemElem = firstItem && firstItem.element; // columnWidth fall back to item of first element this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || // if first elem has no width, default to size of container this.containerWidth; } var columnWidth = this.columnWidth += this.gutter; // calculate columns var containerWidth = this.containerWidth + this.gutter; var cols = containerWidth / columnWidth; // fix rounding errors, typically with gutters var excess = columnWidth - containerWidth % columnWidth; // if overshoot is less than a pixel, round up, otherwise floor it var mathMethod = excess && excess < 1 ? 'round' : 'floor'; cols = Math[ mathMethod ]( cols ); this.cols = Math.max( cols, 1 ); }; proto.getContainerWidth = function() { // container is parent if fit width var isFitWidth = this._getOption('fitWidth'); var container = isFitWidth ? this.element.parentNode : this.element; // check that this.size and size are there // IE8 triggers resize on body size change, so they might not be var size = getSize( container ); this.containerWidth = size && size.innerWidth; }; proto._getItemLayoutPosition = function( item ) { item.getSize(); // how many columns does this brick span var remainder = item.size.outerWidth % this.columnWidth; var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; // round if off by 1 pixel, otherwise use ceil var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); colSpan = Math.min( colSpan, this.cols ); // use horizontal or top column position var colPosMethod = this.options.horizontalOrder ? '_getHorizontalColPosition' : '_getTopColPosition'; var colPosition = this[ colPosMethod ]( colSpan, item ); // position the brick var position = { x: this.columnWidth * colPosition.col, y: colPosition.y }; // apply setHeight to necessary columns var setHeight = colPosition.y + item.size.outerHeight; var setMax = colSpan + colPosition.col; for ( var i = colPosition.col; i < setMax; i++ ) { this.colYs[i] = setHeight; } return position; }; proto._getTopColPosition = function( colSpan ) { var colGroup = this._getTopColGroup( colSpan ); // get the minimum Y value from the columns var minimumY = Math.min.apply( Math, colGroup ); return { col: colGroup.indexOf( minimumY ), y: minimumY, }; }; /** * @param {Number} colSpan - number of columns the element spans * @returns {Array} colGroup */ proto._getTopColGroup = function( colSpan ) { if ( colSpan < 2 ) { // if brick spans only one column, use all the column Ys return this.colYs; } var colGroup = []; // how many different places could this brick fit horizontally var groupCount = this.cols + 1 - colSpan; // for each group potential horizontal position for ( var i = 0; i < groupCount; i++ ) { colGroup[i] = this._getColGroupY( i, colSpan ); } return colGroup; }; proto._getColGroupY = function( col, colSpan ) { if ( colSpan < 2 ) { return this.colYs[ col ]; } // make an array of colY values for that one group var groupColYs = this.colYs.slice( col, col + colSpan ); // and get the max value of the array return Math.max.apply( Math, groupColYs ); }; // get column position based on horizontal index. #873 proto._getHorizontalColPosition = function( colSpan, item ) { var col = this.horizontalColIndex % this.cols; var isOver = colSpan > 1 && col + colSpan > this.cols; // shift to next row if item can't fit on current row col = isOver ? 0 : col; // don't let zero-size items take up space var hasSize = item.size.outerWidth && item.size.outerHeight; this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; return { col: col, y: this._getColGroupY( col, colSpan ), }; }; proto._manageStamp = function( stamp ) { var stampSize = getSize( stamp ); var offset = this._getElementOffset( stamp ); // get the columns that this stamp affects var isOriginLeft = this._getOption('originLeft'); var firstX = isOriginLeft ? offset.left : offset.right; var lastX = firstX + stampSize.outerWidth; var firstCol = Math.floor( firstX / this.columnWidth ); firstCol = Math.max( 0, firstCol ); var lastCol = Math.floor( lastX / this.columnWidth ); // lastCol should not go over if multiple of columnWidth #425 lastCol -= lastX % this.columnWidth ? 0 : 1; lastCol = Math.min( this.cols - 1, lastCol ); // set colYs to bottom of the stamp var isOriginTop = this._getOption('originTop'); var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + stampSize.outerHeight; for ( var i = firstCol; i <= lastCol; i++ ) { this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); } }; proto._getContainerSize = function() { this.maxY = Math.max.apply( Math, this.colYs ); var size = { height: this.maxY }; if ( this._getOption('fitWidth') ) { size.width = this._getContainerFitWidth(); } return size; }; proto._getContainerFitWidth = function() { var unusedCols = 0; // count unused columns var i = this.cols; while ( --i ) { if ( this.colYs[i] !== 0 ) { break; } unusedCols++; } // fit container to columns that have been used return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; }; proto.needsResizeLayout = function() { var previousWidth = this.containerWidth; this.getContainerWidth(); return previousWidth != this.containerWidth; }; return Masonry; })); /*! * imagesLoaded PACKAGED v4.1.4 * JavaScript is all like "You images are done yet or what?" * MIT License */ /** * EvEmitter v1.1.0 * Lil' event emitter * MIT License */ /* jshint unused: true, undef: true, strict: true */ ( function( global, factory ) { // universal module definition /* jshint strict: false */ /* globals define, module, window */ if ( typeof define == 'function' && define.amd ) { // AMD - RequireJS define( 'ev-emitter/ev-emitter',factory ); } else if ( typeof module == 'object' && module.exports ) { // CommonJS - Browserify, Webpack module.exports = factory(); } else { // Browser globals global.EvEmitter = factory(); } }( typeof window != 'undefined' ? window : this, function() { function EvEmitter() {} var proto = EvEmitter.prototype; proto.on = function( eventName, listener ) { if ( !eventName || !listener ) { return; } // set events hash var events = this._events = this._events || {}; // set listeners array var listeners = events[ eventName ] = events[ eventName ] || []; // only add once if ( listeners.indexOf( listener ) == -1 ) { listeners.push( listener ); } return this; }; proto.once = function( eventName, listener ) { if ( !eventName || !listener ) { return; } // add event this.on( eventName, listener ); // set once flag // set onceEvents hash var onceEvents = this._onceEvents = this._onceEvents || {}; // set onceListeners object var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; // set flag onceListeners[ listener ] = true; return this; }; proto.off = function( eventName, listener ) { var listeners = this._events && this._events[ eventName ]; if ( !listeners || !listeners.length ) { return; } var index = listeners.indexOf( listener ); if ( index != -1 ) { listeners.splice( index, 1 ); } return this; }; proto.emitEvent = function( eventName, args ) { var listeners = this._events && this._events[ eventName ]; if ( !listeners || !listeners.length ) { return; } // copy over to avoid interference if .off() in listener listeners = listeners.slice(0); args = args || []; // once stuff var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; for ( var i=0; i < listeners.length; i++ ) { var listener = listeners[i] var isOnce = onceListeners && onceListeners[ listener ]; if ( isOnce ) { // remove listener // remove before trigger to prevent recursion this.off( eventName, listener ); // unset once flag delete onceListeners[ listener ]; } // trigger listener listener.apply( this, args ); } return this; }; proto.allOff = function() { delete this._events; delete this._onceEvents; }; return EvEmitter; })); /*! * imagesLoaded v4.1.4 * JavaScript is all like "You images are done yet or what?" * MIT License */ ( function( window, factory ) { 'use strict'; // universal module definition /*global define: false, module: false, require: false */ if ( typeof define == 'function' && define.amd ) { // AMD define( [ 'ev-emitter/ev-emitter' ], function( EvEmitter ) { return factory( window, EvEmitter ); }); } else if ( typeof module == 'object' && module.exports ) { // CommonJS module.exports = factory( window, require('ev-emitter') ); } else { // browser global window.imagesLoaded = factory( window, window.EvEmitter ); } })( typeof window !== 'undefined' ? window : this, // -------------------------- factory -------------------------- // function factory( window, EvEmitter ) { var $ = window.jQuery; var console = window.console; // -------------------------- helpers -------------------------- // // extend objects function extend( a, b ) { for ( var prop in b ) { a[ prop ] = b[ prop ]; } return a; } var arraySlice = Array.prototype.slice; // turn element or nodeList into an array function makeArray( obj ) { if ( Array.isArray( obj ) ) { // use object if already an array return obj; } var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; if ( isArrayLike ) { // convert nodeList to array return arraySlice.call( obj ); } // array of single index return [ obj ]; } // -------------------------- imagesLoaded -------------------------- // /** * @param {Array, Element, NodeList, String} elem * @param {Object or Function} options - if function, use as callback * @param {Function} onAlways - callback function */ function ImagesLoaded( elem, options, onAlways ) { // coerce ImagesLoaded() without new, to be new ImagesLoaded() if ( !( this instanceof ImagesLoaded ) ) { return new ImagesLoaded( elem, options, onAlways ); } // use elem as selector string var queryElem = elem; if ( typeof elem == 'string' ) { queryElem = document.querySelectorAll( elem ); } // bail if bad element if ( !queryElem ) { console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) ); return; } this.elements = makeArray( queryElem ); this.options = extend( {}, this.options ); // shift arguments if no options set if ( typeof options == 'function' ) { onAlways = options; } else { extend( this.options, options ); } if ( onAlways ) { this.on( 'always', onAlways ); } this.getImages(); if ( $ ) { // add jQuery Deferred object this.jqDeferred = new $.Deferred(); } // HACK check async to allow time to bind listeners setTimeout( this.check.bind( this ) ); } ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); ImagesLoaded.prototype.options = {}; ImagesLoaded.prototype.getImages = function() { this.images = []; // filter & find items if we have an item selector this.elements.forEach( this.addElementImages, this ); }; /** * @param {Node} element */ ImagesLoaded.prototype.addElementImages = function( elem ) { // filter siblings if ( elem.nodeName == 'IMG' ) { this.addImage( elem ); } // get background image on element if ( this.options.background === true ) { this.addElementBackgroundImages( elem ); } // find children // no non-element nodes, #143 var nodeType = elem.nodeType; if ( !nodeType || !elementNodeTypes[ nodeType ] ) { return; } var childImgs = elem.querySelectorAll('img'); // concat childElems to filterFound array for ( var i=0; i < childImgs.length; i++ ) { var img = childImgs[i]; this.addImage( img ); } // get child background images if ( typeof this.options.background == 'string' ) { var children = elem.querySelectorAll( this.options.background ); for ( i=0; i < children.length; i++ ) { var child = children[i]; this.addElementBackgroundImages( child ); } } }; var elementNodeTypes = { 1: true, 9: true, 11: true }; ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { var style = getComputedStyle( elem ); if ( !style ) { // Firefox returns null if in a hidden iframe https://bugzil.la/548397 return; } // get url inside url("...") var reURL = /url\((['"])?(.*?)\1\)/gi; var matches = reURL.exec( style.backgroundImage ); while ( matches !== null ) { var url = matches && matches[2]; if ( url ) { this.addBackground( url, elem ); } matches = reURL.exec( style.backgroundImage ); } }; /** * @param {Image} img */ ImagesLoaded.prototype.addImage = function( img ) { var loadingImage = new LoadingImage( img ); this.images.push( loadingImage ); }; ImagesLoaded.prototype.addBackground = function( url, elem ) { var background = new Background( url, elem ); this.images.push( background ); }; ImagesLoaded.prototype.check = function() { var _this = this; this.progressedCount = 0; this.hasAnyBroken = false; // complete if no images if ( !this.images.length ) { this.complete(); return; } function onProgress( image, elem, message ) { // HACK - Chrome triggers event before object properties have changed. #83 setTimeout( function() { _this.progress( image, elem, message ); }); } this.images.forEach( function( loadingImage ) { loadingImage.once( 'progress', onProgress ); loadingImage.check(); }); }; ImagesLoaded.prototype.progress = function( image, elem, message ) { this.progressedCount++; this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; // progress event this.emitEvent( 'progress', [ this, image, elem ] ); if ( this.jqDeferred && this.jqDeferred.notify ) { this.jqDeferred.notify( this, image ); } // check if completed if ( this.progressedCount == this.images.length ) { this.complete(); } if ( this.options.debug && console ) { console.log( 'progress: ' + message, image, elem ); } }; ImagesLoaded.prototype.complete = function() { var eventName = this.hasAnyBroken ? 'fail' : 'done'; this.isComplete = true; this.emitEvent( eventName, [ this ] ); this.emitEvent( 'always', [ this ] ); if ( this.jqDeferred ) { var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve'; this.jqDeferred[ jqMethod ]( this ); } }; // -------------------------- -------------------------- // function LoadingImage( img ) { this.img = img; } LoadingImage.prototype = Object.create( EvEmitter.prototype ); LoadingImage.prototype.check = function() { // If complete is true and browser supports natural sizes, // try to check for image status manually. var isComplete = this.getIsImageComplete(); if ( isComplete ) { // report based on naturalWidth this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); return; } // If none of the checks above matched, simulate loading on detached element. this.proxyImage = new Image(); this.proxyImage.addEventListener( 'load', this ); this.proxyImage.addEventListener( 'error', this ); // bind to image as well for Firefox. #191 this.img.addEventListener( 'load', this ); this.img.addEventListener( 'error', this ); this.proxyImage.src = this.img.src; }; LoadingImage.prototype.getIsImageComplete = function() { // check for non-zero, non-undefined naturalWidth // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671 return this.img.complete && this.img.naturalWidth; }; LoadingImage.prototype.confirm = function( isLoaded, message ) { this.isLoaded = isLoaded; this.emitEvent( 'progress', [ this, this.img, message ] ); }; // ----- events ----- // // trigger specified handler for event type LoadingImage.prototype.handleEvent = function( event ) { var method = 'on' + event.type; if ( this[ method ] ) { this[ method ]( event ); } }; LoadingImage.prototype.onload = function() { this.confirm( true, 'onload' ); this.unbindEvents(); }; LoadingImage.prototype.onerror = function() { this.confirm( false, 'onerror' ); this.unbindEvents(); }; LoadingImage.prototype.unbindEvents = function() { this.proxyImage.removeEventListener( 'load', this ); this.proxyImage.removeEventListener( 'error', this ); this.img.removeEventListener( 'load', this ); this.img.removeEventListener( 'error', this ); }; // -------------------------- Background -------------------------- // function Background( url, element ) { this.url = url; this.element = element; this.img = new Image(); } // inherit LoadingImage prototype Background.prototype = Object.create( LoadingImage.prototype ); Background.prototype.check = function() { this.img.addEventListener( 'load', this ); this.img.addEventListener( 'error', this ); this.img.src = this.url; // check if image is already complete var isComplete = this.getIsImageComplete(); if ( isComplete ) { this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); this.unbindEvents(); } }; Background.prototype.unbindEvents = function() { this.img.removeEventListener( 'load', this ); this.img.removeEventListener( 'error', this ); }; Background.prototype.confirm = function( isLoaded, message ) { this.isLoaded = isLoaded; this.emitEvent( 'progress', [ this, this.element, message ] ); }; // -------------------------- jQuery -------------------------- // ImagesLoaded.makeJQueryPlugin = function( jQuery ) { jQuery = jQuery || window.jQuery; if ( !jQuery ) { return; } // set local variable $ = jQuery; // $().imagesLoaded() $.fn.imagesLoaded = function( options, callback ) { var instance = new ImagesLoaded( this, options, callback ); return instance.jqDeferred.promise( $(this) ); }; }; // try making plugin ImagesLoaded.makeJQueryPlugin(); // -------------------------- -------------------------- // return ImagesLoaded; }); var referrer_canal_url = (document.cookie.indexOf('referrercanalurl=') === -1 ? '' : ('; ' + document.cookie).split('; referrercanalurl=')[1].split(';')[0]);if (referrer_canal_url) { } else { if (document.referrer) { var referrer_canal_url = document.referrer; var cookieId = 'referrercanalurl'; cookieStr = referrer_canal_url; var nowPreserve = new Date(); var oneYear = 30*24*60*60*1000; var thenPreserve = nowPreserve.getTime() + oneYear; nowPreserve.setTime(thenPreserve); var expireTime = nowPreserve.toUTCString(); document.cookie = cookieId+'='+cookieStr+';path=/;expires='+expireTime+';domain='+document.domain; } else { var referrer_canal_url = ''; } }jQuery(function($){ $("a[href^=mailto]").on("click", function() { ga('send', 'event', 'vip-event', 'click', 'mail'); }); $("a[href^=tel]").on("click", function() { ga('send', 'event', 'vip-event', 'click', 'telefono'); });});var notUs = (document.cookie.indexOf('wasLogged=') === -1 ? '' : ('; ' + document.cookie).split('; wasLogged=')[1].split(';')[0]); if (notUs == 0){(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.text=(function(){/* Copyright The Closure Library Authors. SPDX-License-Identifier: Apache-2.0 */ var n=this||self,p=function(a,b){a=a.split(".");var c=n;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c=c[d]&&c[d]!==Object.prototype[d]?c[d]:c[d]={}:c[d]=b};function q(){for(var a=r,b={},c=0;c>4);64!=h&&(c+=String.fromCharCode(f<<4&240|h>>2),64!=g&&(c+=String.fromCharCode(h<<6&192|g)))}};var w={},y=function(a){w.TAGGING=w.TAGGING||[];w.TAGGING[a]=!0};var ba=Array.isArray,ca=function(a,b){if(a&&ba(a))for(var c=0;cc?a.href:a.href.substr(0,c));a=c;break;case "protocol":a=d;break;case "host":a=a.hostname.replace(N,"").toLowerCase();c&&(c=/^www\d*\./.exec(a))&&c[0]&&(a=a.substr(c[0].length));break;case "port":a=String(Number(a.port)||("http"===d?80:"https"===d?443:""));break;case "path":a.pathname||a.hostname||y(1);a="/"===a.pathname.substr(0,1)?a.pathname:"/"+a.pathname;a=a.split("/");0<=[].indexOf(a[a.length-1])&&(a[a.length-1]="");a=a.join("/");break;case "query":a=a.search.replace("?","");break;case "extension":a= a.pathname.split(".");a=1>2;l=(l&3)<<4|t>>4;t=(t&15)<<2|x>>6;x&=63;m||(x=64,k||(t=64));h.push(r[ra],r[l],r[t],r[x])}f.call(e,h.join(""))}}a=b.join("*");return["1",la(a),a].join("*")}; function la(a,b){a=[J.userAgent,(new Date).getTimezoneOffset(),J.userLanguage||J.language,Math.floor((new Date(Date.now())).getTime()/60/1E3)-(void 0===b?0:b),a].join("*");if(!(b=S)){b=Array(256);for(var c=0;256>c;c++){for(var d=c,e=0;8>e;e++)d=d&1?d>>>1^3988292384:d>>>1;b[c]=d}}S=b;b=4294967295;for(c=0;c>>8^S[(b^a.charCodeAt(c))&255];return((b^-1)>>>0).toString(36)} function ma(a){return function(b){var c=R(G.location.href),d=c.search.replace("?","");a:{var e=d.split("&");for(var f=0;fb;++b){var c=ja.exec(a);if(c){var d=c;break b}a=decodeURIComponent(a)}d=void 0}if(d&&"1"===d[1]){var e=d[2],f=d[3];b:{for(d=0;3>d;++d)if(e===la(f,d)){var h=!0;break b}h=!1}if(h){var g=f;break a}y(7)}}g=void 0}e=g;if(void 0!==e){g={};var k=e?e.split("*"):[];for(e=0;e+1>21:b}return b};var $c=function(a){this.C=a||[]};$c.prototype.set=function(a){this.C[a]=!0};$c.prototype.get=function(a){return this.C[a]};$c.prototype.encode=function(){for(var a=[],b=0;b\x3c/script>'))):(c=M.createElement("script"),c.type="text/javascript",c.async=!0,c.src=ff.createScriptURL(a),d&&(c.onload=d),e&&(c.onerror=e),b&&(c.id=b),g&&c.setAttribute("nonce", g),a=M.getElementsByTagName("script")[0],a.parentNode.insertBefore(c,a))}},be=function(a,b){return E(M.location[b?"href":"search"],a)},E=function(a,b){return(a=a.match("(?:&|#|\\?)"+K(b).replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")+"=([^&#]*)"))&&2==a.length?a[1]:""},xa=function(){var a=""+M.location.hostname;return 0==a.indexOf("www.")?a.substring(4):a},de=function(a,b){var c=a.indexOf(b);if(5==c||6==c)if(a=a.charAt(c+b.length),"/"==a||"?"==a||""==a||":"==a)return!0;return!1},of=function(a,b){var c= M.referrer;if(/^(https?|android-app):\/\//i.test(c)){if(a)return c;a="//"+M.location.hostname;if(!de(c,a))return b&&(b=a.replace(/\./g,"-")+".cdn.ampproject.org",de(c,b))?void 0:c}},za=function(a,b){if(1==b.length&&null!=b[0]&&"object"===typeof b[0])return b[0];for(var c={},d=Math.min(a.length+1,b.length),e=0;eg.length||!c&&3!==g.length)a&&(a.na=!0);else if(Number(g[1])){d[b[e].ja]?a&&(a.pa=!0):d[b[e].ja]=[];var ca={version:g[0],timestamp:1E3*Number(g[1]),qa:g[2]};c&&3=b.length)wc(a,b,c);else if(8192>=b.length)x(a,b,c)||wd(a,b,c)||wc(a,b,c);else throw ge("len",b.length),new Da(b.length);},pe=function(a,b, c,d){d=d||ua;wd(a+"?"+b,"",d,c)},wc=function(a,b,c){var d=ta(a+"?"+b);d.onload=d.onerror=function(){d.onload=null;d.onerror=null;c()}},wd=function(a,b,c,d){var e=O.XMLHttpRequest;if(!e)return!1;var g=new e;if(!("withCredentials"in g))return!1;a=a.replace(/^http:/,"https:");g.open("POST",a,!0);g.withCredentials=!0;g.setRequestHeader("Content-Type","text/plain");g.onreadystatechange=function(){if(4==g.readyState){if(d&&"text/plain"===g.getResponseHeader("Content-Type"))try{Ea(d,g.responseText,c)}catch(ca){ge("xhr", "rsp"),c()}else c();g=null}};g.send(b);return!0},Ea=function(a,b,c){if(1>b.length)ge("xhr","ver","0"),c();else if(3=100*R(a,Ka))throw"abort";}function Ma(a){if(G(P(a,Na)))throw"abort";}function Oa(){var a=M.location.protocol;if("http:"!=a&&"https:"!=a)throw"abort";} function pf(a){var b=!1,c=!1;if(vd.get(89)){c=!0;var d=a.get(kb),e=M.location;if(e){var g=e.pathname||"";"/"!=g.charAt(0)&&(g="/"+g);e=e.protocol+"//"+e.hostname+g+e.search;d&&0===d.indexOf(e)||(b=!0)}}!c&&vd.get(90)&&(c=!0,d=a.get(lb),e=of(!!a.get(ec),!!a.get(Kd)),d!==e&&(b=!0));!c&&vd.get(91)&&(c=!0,a.get(qf)!==M.title&&(b=!0));return c&&!b} function Pa(a){try{O.navigator.sendBeacon?J(42):O.XMLHttpRequest&&"withCredentials"in new O.XMLHttpRequest&&J(40)}catch(c){}a.set(ld,Td(a),!0);a.set(Ac,R(a,Ac)+1);var b=[];ue.map(function(c,d){d.F&&(c=a.get(c),void 0!=c&&c!=d.defaultValue&&("boolean"==typeof c&&(c*=1),b.push(d.F+"="+K(""+c))))});!1===a.get(xe)&&b.push("npa=1");b.push("z="+Bd());pf(a)&&J(109);a.set(Ra,b.join("&"),!0)} function Sa(a){var b=P(a,fa);!b&&a.get(Vd)&&(b="beacon");var c=P(a,gd),d=P(a,oe),e=c||(d||bd(!1)+"")+"/collect",g=a.Z(Ia),ca=P(a,Ra),l=P(a,Na);switch(P(a,ad)){case "d":e=c||(d||bd(!1)+"")+"/j/collect";b=a.get(qe)||void 0;pe(e,ca,b,g);break;default:b?(g=g||ua,"image"==b?wc(e,ca,g):"xhr"==b&&wd(e,ca,g)||"beacon"==b&&x(e,ca,g)||ba(e,ca,g)):ba(e,ca,g)}ca=h(l);g=ca.hitcount;ca.hitcount=g?g+1:1;ca.first_hit||(ca.first_hit=(new Date).getTime());delete h(l).pending_experiments;a.set(Ia,ua,!0);if(rf(a))if(ca= P(a,Na),l=sf[ca])for(ca=0;cag.length&&g.push&&g.push(uf(a));else vf[ca]=vf[ca]||[],30>vf[ca].length&&vf[ca].push(uf(a))}function Hc(a){qc().expId&&a.set(Nc,qc().expId);qc().expVar&&a.set(Oc,qc().expVar);var b=P(a,Na);if(b=h(b).pending_experiments){var c=[];for(d in b)b.hasOwnProperty(d)&&b[d]&&c.push(encodeURIComponent(d)+"."+encodeURIComponent(b[d]));var d=c.join("!")}else d=void 0;d&&((b=a.get(m))&&(d=b+"!"+d),a.set(m,d,!0))} function cd(){if(O.navigator&&"preview"==O.navigator.loadPurpose)throw"abort";}function yd(a){var b=O.gaDevIds||[];if(ka(b)){var c=a.get("&did");qa(c)&&0b-9E5};var hd=function(){return Math.round(2147483647*Math.random())},Bd=function(){try{var a=new Uint32Array(1);O.crypto.getRandomValues(a);return a[0]&2147483647}catch(b){return hd()}};function Ta(a){var b=R(a,Ua);500<=b&&J(15);var c=P(a,Va);if("transaction"!=c&&"item"!=c){c=R(a,Wa);var d=(new Date).getTime(),e=R(a,Xa);0==e&&a.set(Xa,d);e=Math.round(2*(d-e)/1E3);0=c)throw"abort";a.set(Wa,--c)}a.set(Ua,++b)};var Ya=function(){this.data=new ee};Ya.prototype.get=function(a){var b=$a(a),c=this.data.get(a);b&&void 0==c&&(c=ea(b.defaultValue)?b.defaultValue():b.defaultValue);return b&&b.Z?b.Z(this,a,c):c};var P=function(a,b){a=a.get(b);return void 0==a?"":""+a},R=function(a,b){a=a.get(b);return void 0==a||""===a?0:Number(a)};Ya.prototype.Z=function(a){return(a=this.get(a))&&ea(a)?a:ua}; Ya.prototype.set=function(a,b,c){if(a)if("object"===typeof a)for(var d in a)a.hasOwnProperty(d)&&ab(this,d,a[d],c);else ab(this,a,b,c)}; var ab=function(a,b,c,d){if(void 0!=c)switch(b){case Na:wb.test(c)}var e=$a(b);e&&e.o?e.o(a,b,c,d):a.data.set(b,c,d)},gf={hitPayload:88,location:89,referrer:90,title:91,buildHitTask:93,sendHitTask:94,displayFeaturesTask:95,customTask:97,cookieName:98,cookieDomain:99,cookiePath:100,cookieExpires:101,cookieUpdate:102,cookieFlags:103,storage:104,_x_19:105,transportUrl:106,allowAdFeatures:107,sampleRate:108}; function hf(a,b){var c=gf[a];c&&J(c);"displayFeaturesTask"===a&&void 0==b&&J(96);/.*Task$/.test(a)&&J(92)}function mf(a,b){if(a)if("object"===typeof a)for(var c in a)a.hasOwnProperty(c)&&hf(c,b);else hf(a,b)};var ue=new ee,ve=[],bb=function(a,b,c,d,e){this.name=a;this.F=b;this.Z=d;this.o=e;this.defaultValue=c};function $a(a){var b=ue.get(a);if(!b)for(var c=0;c=b?!1:!0},gc=function(a){var b={};if(Ec(b)||Fc(b)){var c=b[Eb];void 0==c||Infinity==c||isNaN(c)||(0c)a[b]=void 0},Fd=function(a){return function(b){if("pageview"==b.get(Va)&&!a.I){a.I=!0;var c=aa(b),d=0a.length)J(12);else{for(var d=[],e=0;e=a&&d.push({hash:ca[0],R:e[g],O:ca})}if(0!=d.length)return 1==d.length?d[0]:Zc(b,d)||Zc(c,d)||Zc(null,d)||d[0]}function Zc(a,b){if(null==a)var c=a=1;else c=La(a),a=La(D(a,".")?a.substring(1):"."+a);for(var d=0;de?"?":"&")+a+b.substring(e);b=b.replace(/&+_ga=/,"&_ga=");return b=b.replace(RegExp("&+_gac="),"&_gac=")},rd=function(a,b){if(b&&b.action)if("get"==b.method.toLowerCase()){a=a.target.get("linkerParam").split("&"); for(var c=0;carguments.length)){if("string"===typeof arguments[0]){var b=arguments[0];var c=[].slice.call(arguments,1)}else b=arguments[0]&&arguments[0][Va],c=arguments;b&&(c=za(me[b]||[],c),c[Va]=b,mf(c),this.model.set(c,void 0,!0),this.filters.D(this.model),this.model.data.m={})}};pc.prototype.ma=function(a,b){var c=this;u(a,c,b)||(v(a,function(){u(a,c,b)}),y(String(c.get(V)),a,void 0,b,!0))}; function td(a,b){var c=P(a,U);a.data.set(la,"_ga"==c?"_gid":c+"_gid");if("cookie"==P(a,ac)){hc=!1;c=Ca(P(a,U));c=Xd(a,c);if(!c){c=P(a,W);var d=P(a,$b)||xa();c=Xc("__utma",d,c);void 0!=c?(J(10),c=c.O[1]+"."+c.O[2]):c=void 0}c&&(hc=!0);if(d=c&&!a.get(Hd))if(d=c.split("."),2!=d.length)d=!1;else if(d=Number(d[1])){var e=R(a,Zb);d=d+e<(new Date).getTime()/1E3}else d=!1;d&&(c=void 0);c&&(a.data.set(xd,c),a.data.set(Q,c),(c=uc(a))&&a.data.set(I,c));a.get(je)&&(c=a.get(ce),d=a.get(ie),!c||d&&"aw.ds"!=d)&& (c={},d=(M?df(c):{})[P(a,Na)],le(c),d&&0!=d.length&&(c=d[0],a.data.set(fe,c.timestamp/1E3),a.data.set(ce,c.qa)));a.get(je)&&(c=a.get(Se),d={},e=(M?df(d,"_gac_gb",!0):{})[P(a,Na)],ef(d),e&&0!=e.length&&(d=e[0],e=d.qa,c&&c!==e||(d.labels&&d.labels.length&&(e+="."+d.labels.join(".")),a.data.set(Te,d.timestamp/1E3),a.data.set(Se,e))))}if(a.get(Hd)){c=be("_ga",!!a.get(cc));var g=be("_gl",!!a.get(cc));d=De.get(a.get(cc));e=d._ga;g&&0=ca[0]||0>= ca[1]?"":ca.join("x");a.set(rb,c);c=a.set;var l;if((e=(e=O.navigator)?e.plugins:null)&&e.length)for(g=0;ga.split("/")[0].indexOf(":")&&(a=g+d[2].substring(0,d[2].lastIndexOf("/"))+"/"+a);b.href=a;c=kf(b);return{protocol:(b.protocol||"").toLowerCase(),host:c[0],port:c[1],path:c[2],query:b.search||"",url:a||""}},cf=function(a,b){return a&& 0<=a.indexOf("/")?a:(b||bd(!1))+"/plugins/ua/"+a};var Z={ga:function(){Z.fa=[]}};Z.ga();Z.D=function(a){var b=Z.J.apply(Z,arguments);b=Z.fa.concat(b);for(Z.fa=[];0c;c++){var d=b[c].src;if(d&&0==d.indexOf(bd(!0)+"/analytics")){b=!0;break a}}b=!1}b&&(Ba=!0)}(O.gaplugins=O.gaplugins||{}).Linker=Dc;b=Dc.prototype;C("linker",Dc);X("decorate",b,b.ca,20);X("autoLink",b,b.S,25);X("passthrough",b,b.$,25);C("displayfeatures",fd);C("adfeatures",fd);Z.D.apply(N,a)}};var xf=N.N,yf=O[gb];yf&&yf.r?xf():z(xf);z(function(){Z.D(["provide","render",ua])});})(window); ;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', 'UA-98486410-1', 'auto');ga('send', 'pageview');}