Photo Gallery by Envira – Responsive Image Gallery for WordPress - Version 1.5.2

Version Description

  • Fix: Justified layout setting of 150 pixels for row height applies to galleries that were using the older automattic layout.
Download this release

Release Info

Developer dimensionmedia
Plugin Icon 128x128 Photo Gallery by Envira – Responsive Image Gallery for WordPress
Version 1.5.2
Comparing to
See all releases

Code changes from version 1.5.1 to 1.5.2

assets/css/envira.css CHANGED
@@ -1 +1 @@
1
- .envira-gallery-wrap,.envira-gallery-wrap *,.envira-tags-filter-list,.envira-tags-filter-list *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envira-tags-filter-list{clear:both;margin:0 0 10px 0}.envira-tags-filter-list li.envira-tags-filter,.envira-tags-filter-list li.envira-tag-filter{float:left;margin:0 20px 10px 0}.envira-tags-filter-list .envira-tag-filter-link{font-size:13px;font-weight:bold}.envira-breadcrumbs{display:block;margin:0 0 20px 0;padding:10px;background:#eee}.envira-breadcrumbs a{text-decoration:none}.envira-gallery-wrap{width:100%;margin:0 auto 20px auto}.envira-gallery-wrap .envira-pagination{margin:0 0 20px 0}.envira-gallery-wrap .envira-gallery-description{clear:both}.envira-gallery-wrap .envira-gallery-public{width:100%;margin:0 auto 20px auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-clear{clear:both}.envira-gallery-wrap .envira-gallery-public.envira-clear:after{clear:both;content:'.';display:block;height:0;line-height:0;overflow:auto;visibility:hidden;zoom:1}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner{position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item{float:left}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item>.envira-gallery-link{display:block;outline:none;border:0 none;position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item img{float:none;display:block;margin:0 auto;padding:0;max-width:100%}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item iframe,.envira-gallery-wrap .envira-gallery-public .envira-gallery-item video{display:block;margin:0 auto;width:100%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item{clear:both;width:100%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item{width:50%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item{width:33.33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item{width:25%;margin:0;padding:0;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item{width:20%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:16.66%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-css-animations .envira-gallery-item img{opacity:0;transition:all .2s ease-in-out}.envira-gallery-wrap .envira-gallery-public.envira-gallery-css-animations .envira-gallery-item a:hover img{opacity:1 !important}.envira-gallery-public.justified-gallery .envira-gallery-item-inner{position:absolute}.envira-gallery-wrap.envira-gallery-rtl .envira-gallery-public .envira-gallery-item{float:right}@media only screen and (max-width: 768px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}@media only screen and (max-width: 459px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:50% !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:none !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(2n+1){clear:both !important}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}@media only screen and (max-width: 320px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:100% !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}/*! envirabox v2.1.5 fancyapps.com | fancyapps.com/envirabox/#license */.envirabox-wrap,.envirabox-skin,.envirabox-outer,.envirabox-inner,.envirabox-image,.envirabox-wrap iframe,.envirabox-wrap object,.envirabox-nav,.envirabox-nav span,.envirabox-tmp,.envirabox-buttons,.envirabox-thumbs,.envirabox-wrap *,.envirabox-thumbs *,.envirabox-buttons *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envirabox-wrap{position:absolute;top:0;left:0;z-index:988020}.envirabox-skin{position:relative;background:#f9f9f9;color:#444;text-shadow:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.envirabox-opened{z-index:988030}.envirabox-opened .envirabox-skin{-webkit-box-shadow:0 10px 25px rgba(0,0,0,0.5);-moz-box-shadow:0 10px 25px rgba(0,0,0,0.5);box-shadow:0 10px 25px rgba(0,0,0,0.5)}.envirabox-outer,.envirabox-inner{position:relative}.envirabox-inner{overflow:hidden}.envirabox-type-iframe .envirabox-inner{-webkit-overflow-scrolling:touch}.envirabox-error{color:#444;font:13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;margin:0;padding:15px;white-space:nowrap}.envirabox-image,.envirabox-iframe{display:block;width:100%;height:100%}.envirabox-image{max-width:100%;max-height:100%}#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite.png")}#envirabox-loading{position:fixed;top:50%;left:50%;margin-top:-22px;margin-left:-22px;background-position:0 -108px;opacity:0.8;cursor:pointer;z-index:988060}#envirabox-loading div{width:44px;height:44px;background:url("images/envirabox_loading.gif") center center no-repeat}.envirabox-close{position:absolute;top:-18px;right:-18px;width:36px;height:36px;cursor:pointer;z-index:988040}.envirabox-nav{position:absolute;top:0;width:40%;height:100%;cursor:pointer;text-decoration:none;background:transparent url("images/blank.gif");-webkit-tap-highlight-color:transparent;z-index:988040}.envirabox-prev{left:0}.envirabox-next{right:0}.envirabox-prev.envirabox-arrows-outside{left:-100px}.envirabox-next.envirabox-arrows-outside{right:-100px}.envirabox-nav span{position:absolute;top:50%;width:36px;height:34px;margin-top:-18px;cursor:pointer;z-index:988040;visibility:hidden}body.envira-touch .envirabox-nav span{visibility:visible}.envirabox-prev span{left:10px;background-position:0 -36px}.envirabox-next span{right:10px;background-position:0 -72px}.envirabox-nav:hover span{visibility:visible}.envirabox-tmp{position:absolute;top:-99999px;left:-99999px;max-width:99999px;max-height:99999px;overflow:visible !important}a.envirabox-close,a.envirabox-nav,a.fancy-close:hover,a.envirabox-nav:hover{border:0}.envirabox-lock{overflow:visible !important;width:auto}.envirabox-lock body{overflow:hidden !important}.envirabox-lock-test{overflow-y:hidden !important}.envirabox-overlay{position:absolute;top:0;left:0;overflow:hidden;display:none;z-index:988010;background:url("images/envirabox_overlay.png")}.envirabox-overlay-fixed{position:fixed;bottom:0;right:0}.envirabox-lock .envirabox-overlay{overflow:auto;overflow-y:scroll}.envirabox-title{visibility:hidden;font-size:13px;line-height:20px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:relative;text-shadow:none;z-index:988090}.envirabox-opened .envirabox-title{visibility:visible}.envirabox-title-float-wrap{position:absolute;bottom:auto;right:50%;margin-top:20px;z-index:988050;text-align:center}.envirabox-title-float-wrap .child{display:inline-block;margin-right:-100%;padding:2px 20px;background:transparent;background:rgba(0,0,0,0.8);-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;text-shadow:0 1px 2px #222;color:#FFF;line-height:24px;white-space:nowrap}.envirabox-title-float-wrap.envirabox-title-text-wrap .child{white-space:normal}.envirabox-title-outside-wrap{position:relative;margin-top:10px;color:#fff}.envirabox-title-inside-wrap{padding-top:10px}.envirabox-title-over-wrap{position:absolute;bottom:0;left:0;color:#fff;padding:10px;background:#000;background:rgba(0,0,0,0.8)}#envirabox-buttons{position:fixed;left:0;width:100%;z-index:988050}#envirabox-buttons.top{top:10px}#envirabox-buttons.bottom{bottom:10px}#envirabox-buttons.bottom.has-padding{bottom:80px}#envirabox-buttons.top.has-padding{top:80px}#envirabox-buttons ul{display:block;width:auto;height:30px;margin:0 auto;padding:0;list-style:none;border:1px solid #111;border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);-moz-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);background:#323232;background:-moz-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #444), color-stop(50%, #343434), color-stop(50%, #292929), color-stop(100%, #333));background:-webkit-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-o-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-ms-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 )}#envirabox-buttons ul li{float:left;margin:0;padding:0}#envirabox-buttons ul li#envirabox-buttons-title span{display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:30px;padding:0 10px;color:#fff}#envirabox-buttons a{display:block;width:30px;height:30px;text-indent:-9999px;background-color:transparent;background-image:url("images/envirabox_buttons.png");background-repeat:no-repeat;outline:none;opacity:0.8}#envirabox-buttons a:hover{opacity:1}#envirabox-buttons a.btnPrev{background-position:5px 0}#envirabox-buttons a.btnNext{background-position:-33px 0;border-right:1px solid #3e3e3e}#envirabox-buttons a.btnPlay{background-position:0 -30px}#envirabox-buttons a.btnPlayOn{background-position:-30px -30px}#envirabox-buttons a.btnToggle,#envirabox-buttons a.btnFullscreen{background-position:3px -60px;border-left:1px solid #111;border-right:1px solid #3e3e3e;width:35px}#envirabox-buttons a.btnToggleOn,#envirabox-buttons a.btnFullscreenOn{background-position:-27px -60px}#envirabox-buttons a.btnClose{border-left:1px solid #111;width:35px;background-position:-56px 0px}#envirabox-buttons a.btnDisabled{opacity:0.4;cursor:default}#envirabox-thumbs{position:fixed;left:0;width:100%;overflow:hidden;z-index:988050;box-sizing:border-box}#envirabox-thumbs.top{top:2px}#envirabox-thumbs.top.has-other-content{top:50px}#envirabox-thumbs.bottom{bottom:2px}#envirabox-thumbs.bottom.has-other-content{bottom:50px}#envirabox-thumbs.inline{position:absolute}#envirabox-thumbs *{box-sizing:border-box}#envirabox-thumbs ul{position:relative;list-style:none;margin:0;padding:0}#envirabox-thumbs ul li{border:3px solid #fff;float:left;margin:5px;opacity:1}#envirabox-thumbs ul li.active{opacity:0.75;border:3px solid #888}#envirabox-thumbs ul li:hover{opacity:0.75}#envirabox-thumbs ul li a{display:block;position:relative;overflow:hidden;border:1px solid #222;background:#111;outline:none}#envirabox-thumbs ul li img{display:block;position:relative;border:0;padding:0;max-width:none}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite@2x.png");background-size:44px 152px}#envirabox-loading div{background-image:url("images/envirabox_loading@2x.gif");background-size:24px 24px}}
1
+ .envira-gallery-wrap,.envira-gallery-wrap *,.envira-tags-filter-list,.envira-tags-filter-list *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envira-tags-filter-list{clear:both;margin:0 0 10px 0}.envira-tags-filter-list li.envira-tags-filter,.envira-tags-filter-list li.envira-tag-filter{float:left;margin:0 20px 10px 0}.envira-tags-filter-list .envira-tag-filter-link{font-size:13px;font-weight:bold}.envira-breadcrumbs{display:block;margin:0 0 20px 0;padding:10px;background:#eee}.envira-breadcrumbs a{text-decoration:none}.envira-gallery-wrap{width:100%;margin:0 auto 20px auto}.envira-gallery-wrap .envira-pagination{margin:0 0 20px 0}.envira-gallery-wrap .envira-gallery-description{clear:both}.envira-gallery-wrap .envira-gallery-public{width:100%;margin:0 auto 20px auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-clear{clear:both}.envira-gallery-wrap .envira-gallery-public.envira-clear:after{clear:both;content:'.';display:block;height:0;line-height:0;overflow:auto;visibility:hidden;zoom:1}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner{position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner .envira-gallery-position-overlay{box-sizing:border-box;position:absolute;overflow:visible;z-index:999}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner .envira-gallery-position-overlay.envira-gallery-top-left{top:0;left:0;padding:5px 0 0 5px}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner .envira-gallery-position-overlay.envira-gallery-top-right{top:0;right:0;padding:5px 5px 0 0;text-align:right}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner .envira-gallery-position-overlay.envira-gallery-bottom-left{bottom:0;left:0;padding:0 0 5px 5px}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner .envira-gallery-position-overlay.envira-gallery-bottom-right{bottom:0;right:0;padding:0 5px 5px 0;text-align:right}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item{float:left}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item>.envira-gallery-link{display:block;outline:none;border:0 none;position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item img{float:none;display:block;margin:0 auto;padding:0;max-width:100%}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item iframe,.envira-gallery-wrap .envira-gallery-public .envira-gallery-item video{display:block;margin:0 auto;width:100%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item{clear:both;width:100%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item{width:50%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item{width:33.33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item{width:25%;margin:0;padding:0;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item{width:20%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:16.66%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-css-animations .envira-gallery-item img{opacity:0;transition:all .2s ease-in-out}.envira-gallery-wrap .envira-gallery-public.envira-gallery-css-animations .envira-gallery-item a:hover img{opacity:1 !important}.envira-gallery-public.justified-gallery .envira-gallery-item-inner{position:absolute}.envira-gallery-wrap.envira-gallery-rtl .envira-gallery-public .envira-gallery-item{float:right}@media only screen and (max-width: 768px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}@media only screen and (max-width: 459px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:50% !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:none !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(2n+1){clear:both !important}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}@media only screen and (max-width: 320px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:100% !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}/*! envirabox v2.1.5 fancyapps.com | fancyapps.com/envirabox/#license */.envirabox-wrap,.envirabox-skin,.envirabox-outer,.envirabox-inner,.envirabox-image,.envirabox-wrap iframe,.envirabox-wrap object,.envirabox-nav,.envirabox-nav span,.envirabox-tmp,.envirabox-buttons,.envirabox-thumbs,.envirabox-wrap *,.envirabox-thumbs *,.envirabox-buttons *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envirabox-wrap{position:absolute;top:0;left:0;z-index:988020}.envirabox-skin{position:relative;background:#f9f9f9;color:#444;text-shadow:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.envirabox-opened{z-index:988030}.envirabox-opened .envirabox-skin{-webkit-box-shadow:0 10px 25px rgba(0,0,0,0.5);-moz-box-shadow:0 10px 25px rgba(0,0,0,0.5);box-shadow:0 10px 25px rgba(0,0,0,0.5)}.envirabox-outer,.envirabox-inner{position:relative}.envirabox-inner{overflow:hidden}.envirabox-inner .envirabox-position-overlay{box-sizing:border-box;position:absolute;overflow:visible;z-index:988041;padding:0}.envirabox-inner .envirabox-position-overlay.envira-gallery-top-left{top:0;left:0}.envirabox-inner .envirabox-position-overlay.envira-gallery-top-right{top:0;right:0;text-align:right}.envirabox-inner .envirabox-position-overlay.envira-gallery-bottom-left{bottom:0;left:0}.envirabox-inner .envirabox-position-overlay.envira-gallery-bottom-right{bottom:0;right:0;text-align:right}.envirabox-type-iframe .envirabox-inner{-webkit-overflow-scrolling:touch}.envirabox-error{color:#444;font:13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;margin:0;padding:15px;white-space:nowrap}.envirabox-image,.envirabox-iframe{display:block;width:100%;height:100%}.envirabox-image{max-width:100%;max-height:100%}#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite.png")}#envirabox-loading{position:fixed;top:50%;left:50%;margin-top:-22px;margin-left:-22px;background-position:0 -108px;opacity:0.8;cursor:pointer;z-index:988060}#envirabox-loading div{width:44px;height:44px;background:url("images/envirabox_loading.gif") center center no-repeat}.envirabox-close{position:absolute;top:-18px;right:-18px;width:36px;height:36px;cursor:pointer;z-index:988040}.envirabox-nav{position:absolute;top:0;width:40%;height:100%;cursor:pointer;text-decoration:none;background:transparent url("images/blank.gif");-webkit-tap-highlight-color:transparent;z-index:988040}.envirabox-prev{left:0}.envirabox-next{right:0}.envirabox-prev.envirabox-arrows-outside{left:-100px}.envirabox-next.envirabox-arrows-outside{right:-100px}.envirabox-nav span{position:absolute;top:50%;width:36px;height:34px;margin-top:-18px;cursor:pointer;z-index:988040;visibility:hidden}body.envira-touch .envirabox-nav span{visibility:visible}.envirabox-prev span{left:10px;background-position:0 -36px}.envirabox-next span{right:10px;background-position:0 -72px}.envirabox-nav:hover span{visibility:visible}.envirabox-tmp{position:absolute;top:-99999px;left:-99999px;max-width:99999px;max-height:99999px;overflow:visible !important}a.envirabox-close,a.envirabox-nav,a.fancy-close:hover,a.envirabox-nav:hover{border:0}.envirabox-lock{overflow:visible !important;width:auto}.envirabox-lock body{overflow:hidden !important}.envirabox-lock-test{overflow-y:hidden !important}.envirabox-overlay{position:absolute;top:0;left:0;overflow:hidden;display:none;z-index:988010;background:url("images/envirabox_overlay.png")}.envirabox-overlay-fixed{position:fixed;bottom:0;right:0}.envirabox-lock .envirabox-overlay{overflow:auto;overflow-y:scroll}.envirabox-title{visibility:hidden;font-size:13px;line-height:20px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:relative;text-shadow:none;z-index:988090}.envirabox-opened .envirabox-title{visibility:visible}.envirabox-title-float-wrap{position:absolute;bottom:auto;right:50%;margin-top:20px;z-index:988050;text-align:center}.envirabox-title-float-wrap .child{display:inline-block;margin-right:-100%;padding:2px 20px;background:transparent;background:rgba(0,0,0,0.8);-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;text-shadow:0 1px 2px #222;color:#FFF;line-height:24px;white-space:nowrap}.envirabox-title-float-wrap.envirabox-title-text-wrap .child{white-space:normal}.envirabox-title-outside-wrap{position:relative;margin-top:10px;color:#fff}.envirabox-title-inside-wrap{padding-top:10px}.envirabox-title-over-wrap{position:absolute;bottom:0;left:0;color:#fff;padding:10px;background:#000;background:rgba(0,0,0,0.8)}#envirabox-buttons{position:fixed;left:0;width:100%;z-index:988050}#envirabox-buttons.top{top:10px}#envirabox-buttons.bottom{bottom:10px}#envirabox-buttons.bottom.has-padding{bottom:80px}#envirabox-buttons.top.has-padding{top:80px}#envirabox-buttons ul{display:block;width:auto;height:30px;margin:0 auto;padding:0;list-style:none;border:1px solid #111;border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);-moz-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);background:#323232;background:-moz-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #444), color-stop(50%, #343434), color-stop(50%, #292929), color-stop(100%, #333));background:-webkit-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-o-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-ms-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 )}#envirabox-buttons ul li{float:left;margin:0;padding:0}#envirabox-buttons ul li#envirabox-buttons-title span{display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:30px;padding:0 10px;color:#fff}#envirabox-buttons a{display:block;width:30px;height:30px;text-indent:-9999px;background-color:transparent;background-image:url("images/envirabox_buttons.png");background-repeat:no-repeat;outline:none;opacity:0.8}#envirabox-buttons a:hover{opacity:1}#envirabox-buttons a.btnPrev{background-position:5px 0}#envirabox-buttons a.btnNext{background-position:-33px 0;border-right:1px solid #3e3e3e}#envirabox-buttons a.btnPlay{background-position:0 -30px}#envirabox-buttons a.btnPlayOn{background-position:-30px -30px}#envirabox-buttons a.btnToggle,#envirabox-buttons a.btnFullscreen{background-position:3px -60px;border-left:1px solid #111;border-right:1px solid #3e3e3e;width:35px}#envirabox-buttons a.btnToggleOn,#envirabox-buttons a.btnFullscreenOn{background-position:-27px -60px}#envirabox-buttons a.btnClose{border-left:1px solid #111;width:35px;background-position:-56px 0px}#envirabox-buttons a.btnDisabled{opacity:0.4;cursor:default}#envirabox-thumbs{position:fixed;left:0;width:100%;overflow:hidden;z-index:988050;box-sizing:border-box}#envirabox-thumbs.top{top:2px}#envirabox-thumbs.top.has-other-content{top:50px}#envirabox-thumbs.bottom{bottom:2px}#envirabox-thumbs.bottom.has-other-content{bottom:50px}#envirabox-thumbs.inline{position:absolute}#envirabox-thumbs *{box-sizing:border-box}#envirabox-thumbs ul{position:relative;list-style:none;margin:0;padding:0}#envirabox-thumbs ul li{border:3px solid #fff;float:left;margin:5px;opacity:1}#envirabox-thumbs ul li.active{opacity:0.75;border:3px solid #888}#envirabox-thumbs ul li:hover{opacity:0.75}#envirabox-thumbs ul li a{display:block;position:relative;overflow:hidden;border:1px solid #222;background:#111;outline:none}#envirabox-thumbs ul li img{display:block;position:relative;border:0;padding:0;max-width:none}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite@2x.png");background-size:44px 152px}#envirabox-loading div{background-image:url("images/envirabox_loading@2x.gif");background-size:24px 24px}}
assets/js/envira.js CHANGED
@@ -1,16 +1,18 @@
1
  /**
2
  * envira.js is a placeholder, which CodeKit attaches the following JS files to, before compiling as min/envira-min.js:
3
- * - lib/jquery.justifiedGallery.js
4
- * - lib/enviraJustifiedGallery-extension.js
5
- * - lib/touchswipe.js
6
- * - lib/mousewheel.js
7
- * - lib/imagesloaded.js
8
- * - lib/isotope.js
9
- * - lib/fancybox.js
10
- * - lib/fancybox-buttons.js
11
- * - lib/fancybox-media.js
12
- * - lib/fancybox-thumbs.js
13
- *
 
 
14
  * To load more JS resources:
15
  * - Add them to the lib subfolder
16
  * - Add the to the imports directive of this file in CodeKit
1
  /**
2
  * envira.js is a placeholder, which CodeKit attaches the following JS files to, before compiling as min/envira-min.js:
3
+ */
4
+ // @codekit-append "lib/jquery.justifiedGallery.js";
5
+ // @codekit-append "lib/enviraJustifiedGallery-extensions.js";
6
+ // @codekit-append "lib/touchswipe.js";
7
+ // @codekit-append "lib/mousewheel.js";
8
+ // @codekit-append "lib/imagesloaded.js";
9
+ // @codekit-append "lib/isotope.js";
10
+ // @codekit-append "lib/fancybox.js";
11
+ // @codekit-append "lib/fancybox-buttons.js";
12
+ // @codekit-append "lib/fancybox-media.js";
13
+ // @codekit-append "lib/fancybox-thumbs.js";
14
+ // @codekit-append "lib/fancybox-video.js";
15
+ /**
16
  * To load more JS resources:
17
  * - Add them to the lib subfolder
18
  * - Add the to the imports directive of this file in CodeKit
assets/js/lib/fancybox.js CHANGED
@@ -211,11 +211,15 @@
211
  * Static methods
212
  */
213
 
214
- open: function (group, opts) {
215
  if (!group) {
216
  return;
217
  }
218
 
 
 
 
 
219
  if (!$.isPlainObject(opts)) {
220
  opts = {};
221
  }
@@ -1936,7 +1940,7 @@
1936
  };
1937
 
1938
  // jQuery plugin initialization
1939
- $.fn.envirabox = function (options) {
1940
  var index,
1941
  that = $(this),
1942
  selector = this.selector || '',
@@ -1964,7 +1968,7 @@
1964
  options.index = idx;
1965
 
1966
  // Stop an event from bubbling if everything is fine
1967
- if (F.open(what, options) !== false) {
1968
  e.preventDefault();
1969
  }
1970
  }
211
  * Static methods
212
  */
213
 
214
+ open: function (group, opts, images) {
215
  if (!group) {
216
  return;
217
  }
218
 
219
+ if (images) {
220
+ group = images;
221
+ }
222
+
223
  if (!$.isPlainObject(opts)) {
224
  opts = {};
225
  }
1940
  };
1941
 
1942
  // jQuery plugin initialization
1943
+ $.fn.envirabox = function (options, images) {
1944
  var index,
1945
  that = $(this),
1946
  selector = this.selector || '',
1968
  options.index = idx;
1969
 
1970
  // Stop an event from bubbling if everything is fine
1971
+ if (F.open(what, options, images) !== false) {
1972
  e.preventDefault();
1973
  }
1974
  }
assets/js/min/envira-min.js CHANGED
@@ -1,1441 +1,4 @@
1
- /**
2
- * envira.js is a placeholder, which CodeKit attaches the following JS files to, before compiling as min/envira-min.js:
3
- * - lib/jquery.justifiedGallery.js
4
- * - lib/enviraJustifiedGallery-extension.js
5
- * - lib/touchswipe.js
6
- * - lib/mousewheel.js
7
- * - lib/imagesloaded.js
8
- * - lib/isotope.js
9
- * - lib/fancybox.js
10
- * - lib/fancybox-buttons.js
11
- * - lib/fancybox-media.js
12
- * - lib/fancybox-thumbs.js
13
- *
14
- * To load more JS resources:
15
- * - Add them to the lib subfolder
16
- * - Add the to the imports directive of this file in CodeKit
17
- */
18
-
19
- /**
20
- * If a lightbox caption's link is an anchor, close the lightbox
21
- */
22
- jQuery( document ).ready( function( $ ) {
23
-
24
- $( 'body' ).on( 'click', 'div.envirabox-title a[href*="#"]:not([href="#"])', function( e ) {
25
-
26
- if ( location.pathname.replace( /^\//, '' ) == this.pathname.replace( /^\//, '' ) && location.hostname == this.hostname ) {
27
- $.envirabox.close();
28
- return false;
29
- }
30
-
31
- } );
32
-
33
- } );
34
-
35
- function jg_effect_desaturate(src) {
36
- var supportsCanvas = !!document.createElement('canvas').getContext;
37
- if (supportsCanvas) {
38
- var canvas = document.createElement('canvas'),
39
- context = canvas.getContext('2d'),
40
- imageData, px, length, i = 0, gray,
41
- img = new Image();
42
-
43
- img.src = src;
44
- canvas.width = img.width;
45
- canvas.height = img.height;
46
- context.drawImage(img, 0, 0);
47
-
48
- imageData = context.getImageData(0, 0, canvas.width, canvas.height);
49
- px = imageData.data;
50
- length = px.length;
51
-
52
- for (; i < length; i += 4) {
53
- gray = px[i] * .3 + px[i + 1] * .59 + px[i + 2] * .11;
54
- px[i] = px[i + 1] = px[i + 2] = gray;
55
- }
56
-
57
- context.putImageData(imageData, 0, 0);
58
- return canvas.toDataURL();
59
- } else {
60
- return src;
61
- }
62
- }
63
-
64
- function jg_effect_threshold(src) {
65
- var supportsCanvas = !!document.createElement('canvas').getContext;
66
- if (supportsCanvas) {
67
- var canvas = document.createElement('canvas'),
68
- context = canvas.getContext('2d'),
69
- imageData, px, length, i = 0, gray,
70
- img = new Image();
71
-
72
- img.src = src;
73
- canvas.width = img.width;
74
- canvas.height = img.height;
75
- context.drawImage(img, 0, 0);
76
-
77
- imageData = context.getImageData(0, 0, canvas.width, canvas.height);
78
- px = imageData.data;
79
- length = px.length;
80
-
81
- threshold = 120;
82
-
83
- for (var i=0; i<length; i+=4) {
84
- var r = px[i];
85
- var g = px[i+1];
86
- var b = px[i+2];
87
- var v = (0.2126*r + 0.7152*g + 0.0722*b >= threshold) ? 255 : 0;
88
- px[i] = px[i+1] = px[i+2] = v
89
- }
90
-
91
- context.putImageData(imageData, 0, 0);
92
- return canvas.toDataURL();
93
- } else {
94
- return src;
95
- }
96
- }
97
-
98
- function jg_effect_blur(src) {
99
- var supportsCanvas = !!document.createElement('canvas').getContext;
100
- if (supportsCanvas) {
101
- var canvas = document.createElement('canvas'),
102
- context = canvas.getContext('2d'),
103
- imageData, px, length, i = 0, gray, top_x = 0, top_y = 0, radius = 30, iterations = 1
104
- img = new Image();
105
-
106
- img.src = src;
107
- canvas.width = img.width;
108
- canvas.height = img.height;
109
- context.drawImage(img, 0, 0);
110
-
111
- var imageData;
112
- var width = img.width;
113
- var height = img.height;
114
-
115
- imageData = context.getImageData( top_x, top_y, width, height );
116
- var pixels = imageData.data;
117
-
118
- var rsum,gsum,bsum,asum,x,y,i,p,p1,p2,yp,yi,yw,idx;
119
- var wm = width - 1;
120
- var hm = height - 1;
121
- var wh = width * height;
122
- var rad1 = radius + 1;
123
-
124
- var r = [];
125
- var g = [];
126
- var b = [];
127
-
128
- var mul_sum = mul_table[radius];
129
- var shg_sum = shg_table[radius];
130
-
131
- var vmin = [];
132
- var vmax = [];
133
-
134
- while ( iterations-- > 0 ){
135
- yw = yi = 0;
136
-
137
- for ( y=0; y < height; y++ ){
138
- rsum = pixels[yw] * rad1;
139
- gsum = pixels[yw+1] * rad1;
140
- bsum = pixels[yw+2] * rad1;
141
-
142
- for( i = 1; i <= radius; i++ ){
143
- p = yw + (((i > wm ? wm : i )) << 2 );
144
- rsum += pixels[p++];
145
- gsum += pixels[p++];
146
- bsum += pixels[p++];
147
- }
148
-
149
- for ( x = 0; x < width; x++ ){
150
- r[yi] = rsum;
151
- g[yi] = gsum;
152
- b[yi] = bsum;
153
-
154
- if( y==0) {
155
- vmin[x] = ( ( p = x + rad1) < wm ? p : wm ) << 2;
156
- vmax[x] = ( ( p = x - radius) > 0 ? p << 2 : 0 );
157
- }
158
-
159
- p1 = yw + vmin[x];
160
- p2 = yw + vmax[x];
161
-
162
- rsum += pixels[p1++] - pixels[p2++];
163
- gsum += pixels[p1++] - pixels[p2++];
164
- bsum += pixels[p1++] - pixels[p2++];
165
-
166
- yi++;
167
- }
168
- yw += ( width << 2 );
169
- }
170
-
171
- for ( x = 0; x < width; x++ ){
172
- yp = x;
173
- rsum = r[yp] * rad1;
174
- gsum = g[yp] * rad1;
175
- bsum = b[yp] * rad1;
176
-
177
- for( i = 1; i <= radius; i++ ){
178
- yp += ( i > hm ? 0 : width );
179
- rsum += r[yp];
180
- gsum += g[yp];
181
- bsum += b[yp];
182
- }
183
-
184
- yi = x << 2;
185
- for ( y = 0; y < height; y++){
186
- pixels[yi] = (rsum * mul_sum) >>> shg_sum;
187
- pixels[yi+1] = (gsum * mul_sum) >>> shg_sum;
188
- pixels[yi+2] = (bsum * mul_sum) >>> shg_sum;
189
-
190
- if( x == 0 ) {
191
- vmin[y] = ( ( p = y + rad1) < hm ? p : hm ) * width;
192
- vmax[y] = ( ( p = y - radius) > 0 ? p * width : 0 );
193
- }
194
-
195
- p1 = x + vmin[y];
196
- p2 = x + vmax[y];
197
-
198
- rsum += r[p1] - r[p2];
199
- gsum += g[p1] - g[p2];
200
- bsum += b[p1] - b[p2];
201
-
202
- yi += width << 2;
203
- }
204
- }
205
- }
206
- context.putImageData( imageData, top_x, top_y );
207
-
208
- return canvas.toDataURL();
209
-
210
- } else {
211
- return src;
212
- }
213
- }
214
-
215
- function jg_effect_vintage( img ) {
216
- var options = {
217
- onError: function() {
218
- alert('ERROR');
219
- }
220
- };
221
- var effect = {
222
- vignette: 1,
223
- sepia: true,
224
- noise: 50,
225
- desaturate: .2,
226
- lighten: .1
227
-
228
- };
229
- new VintageJS(img, options, effect);
230
- }
231
-
232
- /*!
233
- * Justified Gallery - v3.6.2
234
- * http://miromannino.github.io/Justified-Gallery/
235
- * Copyright (c) 2016 Miro Mannino
236
- * Licensed under the MIT license.
237
- */
238
- (function($) {
239
-
240
- function hasScrollBar() {
241
- return $("body").height() > $(window).height();
242
- }
243
- /**
244
- * Justified Gallery controller constructor
245
- *
246
- * @param $gallery the gallery to build
247
- * @param settings the settings (the defaults are in $.fn.justifiedGallery.defaults)
248
- * @constructor
249
- */
250
- var JustifiedGallery = function ($gallery, settings) {
251
-
252
- this.settings = settings;
253
- this.checkSettings();
254
-
255
- this.imgAnalyzerTimeout = null;
256
- this.entries = null;
257
- this.buildingRow = {
258
- entriesBuff : [],
259
- width : 0,
260
- height : 0,
261
- aspectRatio : 0
262
- };
263
- this.lastAnalyzedIndex = -1;
264
- this.yield = {
265
- every : 2, // do a flush every n flushes (must be greater than 1)
266
- flushed : 0 // flushed rows without a yield
267
- };
268
- this.border = settings.border >= 0 ? settings.border : settings.margins;
269
- this.maxRowHeight = this.retrieveMaxRowHeight();
270
- this.suffixRanges = this.retrieveSuffixRanges();
271
- this.offY = this.border;
272
- this.rows = 0;
273
- this.spinner = {
274
- phase : 0,
275
- timeSlot : 150,
276
- $el : $('<div class="spinner"><span></span><span></span><span></span></div>'),
277
- intervalId : null
278
- };
279
- this.checkWidthIntervalId = null;
280
- this.galleryWidth = $gallery.width();
281
- this.$gallery = $gallery;
282
-
283
- };
284
-
285
- /** @returns {String} the best suffix given the width and the height */
286
- JustifiedGallery.prototype.getSuffix = function (width, height) {
287
- var longestSide, i;
288
- longestSide = (width > height) ? width : height;
289
- for (i = 0; i < this.suffixRanges.length; i++) {
290
- if (longestSide <= this.suffixRanges[i]) {
291
- return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
292
- }
293
- }
294
- return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
295
- };
296
-
297
- /**
298
- * Remove the suffix from the string
299
- *
300
- * @returns {string} a new string without the suffix
301
- */
302
- JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
303
- return str.substring(0, str.length - suffix.length);
304
- };
305
-
306
- /**
307
- * @returns {boolean} a boolean to say if the suffix is contained in the str or not
308
- */
309
- JustifiedGallery.prototype.endsWith = function (str, suffix) {
310
- return str.indexOf(suffix, str.length - suffix.length) !== -1;
311
- };
312
-
313
- /**
314
- * Get the used suffix of a particular url
315
- *
316
- * @param str
317
- * @returns {String} return the used suffix
318
- */
319
- JustifiedGallery.prototype.getUsedSuffix = function (str) {
320
- for (var si in this.settings.sizeRangeSuffixes) {
321
- if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
322
- if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
323
- if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
324
- }
325
- }
326
- return '';
327
- };
328
-
329
- /**
330
- * Given an image src, with the width and the height, returns the new image src with the
331
- * best suffix to show the best quality thumbnail.
332
- *
333
- * @returns {String} the suffix to use
334
- */
335
- JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight) {
336
- var newImageSrc;
337
-
338
- if (this.settings.thumbnailPath) {
339
- newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight);
340
- } else {
341
- var matchRes = imageSrc.match(this.settings.extension);
342
- var ext = (matchRes !== null) ? matchRes[0] : '';
343
- newImageSrc = imageSrc.replace(this.settings.extension, '');
344
- newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
345
- newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
346
- }
347
-
348
- return newImageSrc;
349
- };
350
-
351
- /**
352
- * Shows the images that is in the given entry
353
- *
354
- * @param $entry the entry
355
- * @param callback the callback that is called when the show animation is finished
356
- */
357
- JustifiedGallery.prototype.showImg = function ($entry, callback) {
358
- if (this.settings.cssAnimation) {
359
- $entry.addClass('entry-visible');
360
- if (callback) callback();
361
- } else {
362
- $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
363
- }
364
- };
365
-
366
- /**
367
- * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
368
- * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
369
- *
370
- * @param $image the image to analyze
371
- * @returns {String} the extracted src
372
- */
373
- JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
374
- var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src');
375
- $image.data('jg.originalSrc', imageSrc);
376
- return imageSrc;
377
- };
378
-
379
- /** @returns {jQuery} the image in the given entry */
380
- JustifiedGallery.prototype.imgFromEntry = function ($entry) {
381
- var $img = $entry.find('> img');
382
- if ($img.length === 0) $img = $entry.find('> a > img');
383
- return $img.length === 0 ? null : $img;
384
- };
385
-
386
- /** @returns {jQuery} the caption in the given entry */
387
- JustifiedGallery.prototype.captionFromEntry = function ($entry) {
388
- var $caption = $entry.find('> .caption');
389
- return $caption.length === 0 ? null : $caption;
390
- };
391
-
392
- /**
393
- * Display the entry
394
- *
395
- * @param {jQuery} $entry the entry to display
396
- * @param {int} x the x position where the entry must be positioned
397
- * @param y the y position where the entry must be positioned
398
- * @param imgWidth the image width
399
- * @param imgHeight the image height
400
- * @param rowHeight the row height of the row that owns the entry
401
- */
402
- JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
403
- $entry.width(imgWidth);
404
- $entry.height(rowHeight);
405
- $entry.css('top', y);
406
- $entry.css('left', x);
407
-
408
- var $image = this.imgFromEntry($entry);
409
- if ($image !== null) {
410
- $image.css('width', imgWidth);
411
- $image.css('height', imgHeight);
412
- $image.css('margin-left', - imgWidth / 2);
413
- $image.css('margin-top', - imgHeight / 2);
414
-
415
- // Image reloading for an high quality of thumbnails
416
- var imageSrc = $image.attr('src');
417
- var newImageSrc = this.newSrc(imageSrc, imgWidth, imgHeight);
418
-
419
- $image.one('error', function () {
420
- $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it.
421
- });
422
-
423
- var loadNewImage = function () {
424
- if (imageSrc !== newImageSrc) { //load the new image after the fadeIn
425
- $image.attr('src', newImageSrc);
426
- }
427
- };
428
-
429
- if ($entry.data('jg.loaded') === 'skipped') {
430
- this.onImageEvent(imageSrc, $.proxy(function() {
431
- this.showImg($entry, loadNewImage);
432
- $entry.data('jg.loaded', true);
433
- }, this));
434
- } else {
435
- this.showImg($entry, loadNewImage);
436
- }
437
-
438
- } else {
439
- this.showImg($entry);
440
- }
441
-
442
- this.displayEntryCaption($entry);
443
- };
444
-
445
- /**
446
- * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
447
- * or the 'title' attributes.
448
- *
449
- * @param {jQuery} $entry the entry to process
450
- */
451
- JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
452
- var $image = this.imgFromEntry($entry);
453
- if ($image !== null && this.settings.captions) {
454
- var $imgCaption = this.captionFromEntry($entry);
455
-
456
- // Create it if it doesn't exists
457
- if ($imgCaption === null) {
458
- var caption = $image.attr('alt');
459
- if (!this.isValidCaption(caption)) caption = $entry.attr('title');
460
- if (this.isValidCaption(caption)) { // Create only we found something
461
- $imgCaption = $('<div class="caption">' + caption + '</div>');
462
- $entry.append($imgCaption);
463
- $entry.data('jg.createdCaption', true);
464
- }
465
- }
466
-
467
- // Create events (we check again the $imgCaption because it can be still inexistent)
468
- if ($imgCaption !== null) {
469
- if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
470
- this.addCaptionEventsHandlers($entry);
471
- }
472
- } else {
473
- this.removeCaptionEventsHandlers($entry);
474
- }
475
- };
476
-
477
- /**
478
- * Validates the caption
479
- *
480
- * @param caption The caption that should be validated
481
- * @return {boolean} Validation result
482
- */
483
- JustifiedGallery.prototype.isValidCaption = function (caption) {
484
- return (typeof caption !== 'undefined' && caption.length > 0);
485
- };
486
-
487
- /**
488
- * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
489
- * It shows the caption using jQuery (or using CSS if it is configured so)
490
- *
491
- * @param {Event} eventObject the event object
492
- */
493
- JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
494
- var $caption = this.captionFromEntry($(eventObject.currentTarget));
495
- if (this.settings.cssAnimation) {
496
- $caption.addClass('caption-visible').removeClass('caption-hidden');
497
- } else {
498
- $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
499
- this.settings.captionSettings.visibleOpacity);
500
- }
501
- };
502
-
503
- /**
504
- * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
505
- * It hides the caption using jQuery (or using CSS if it is configured so)
506
- *
507
- * @param {Event} eventObject the event object
508
- */
509
- JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
510
- var $caption = this.captionFromEntry($(eventObject.currentTarget));
511
- if (this.settings.cssAnimation) {
512
- $caption.removeClass('caption-visible').removeClass('caption-hidden');
513
- } else {
514
- $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
515
- this.settings.captionSettings.nonVisibleOpacity);
516
- }
517
- };
518
-
519
- /**
520
- * Add the handlers of the entry for the caption
521
- *
522
- * @param $entry the entry to modify
523
- */
524
- JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
525
- var captionMouseEvents = $entry.data('jg.captionMouseEvents');
526
- if (typeof captionMouseEvents === 'undefined') {
527
- captionMouseEvents = {
528
- mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
529
- mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
530
- };
531
- $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
532
- $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
533
- $entry.data('jg.captionMouseEvents', captionMouseEvents);
534
- }
535
- };
536
-
537
- /**
538
- * Remove the handlers of the entry for the caption
539
- *
540
- * @param $entry the entry to modify
541
- */
542
- JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
543
- var captionMouseEvents = $entry.data('jg.captionMouseEvents');
544
- if (typeof captionMouseEvents !== 'undefined') {
545
- $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
546
- $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
547
- $entry.removeData('jg.captionMouseEvents');
548
- }
549
- };
550
-
551
- /**
552
- * Justify the building row, preparing it to
553
- *
554
- * @param isLastRow
555
- * @returns a boolean to know if the row has been justified or not
556
- */
557
- JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow) {
558
- var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
559
- var minHeight = 0;
560
- var availableWidth = this.galleryWidth - 2 * this.border - (
561
- (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
562
- var rowHeight = availableWidth / this.buildingRow.aspectRatio;
563
- var defaultRowHeight = this.settings.rowHeight;
564
- var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
565
-
566
- //Skip the last row if we can't justify it and the lastRow == 'hide'
567
- if (isLastRow && this.settings.lastRow === 'hide' && !justifiable) {
568
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
569
- $entry = this.buildingRow.entriesBuff[i];
570
- if (this.settings.cssAnimation)
571
- $entry.removeClass('entry-visible');
572
- else
573
- $entry.stop().fadeTo(0, 0);
574
- }
575
- return -1;
576
- }
577
-
578
- // With lastRow = nojustify, justify if is justificable (the images will not become too big)
579
- if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
580
- justify = false;
581
-
582
- if (this.rows > 0) {
583
- defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
584
- if (defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold) {
585
- justify = true;
586
- } else {
587
- justify = false;
588
- }
589
- }
590
- }
591
-
592
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
593
- $entry = this.buildingRow.entriesBuff[i];
594
- imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
595
-
596
- if (justify) {
597
- newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
598
- newImgH = rowHeight;
599
-
600
- /* With fixedHeight the newImgH must be greater than rowHeight.
601
- In some cases here this is not satisfied (due to the justification).
602
- But we comment it, because is better to have a shorter but justified row instead
603
- to have a cropped image at the end. */
604
- /*if (this.settings.fixedHeight && newImgH < this.settings.rowHeight) {
605
- newImgW = this.settings.rowHeight * imgAspectRatio;
606
- newImgH = this.settings.rowHeight;
607
- }*/
608
-
609
- } else {
610
- newImgW = defaultRowHeight * imgAspectRatio;
611
- newImgH = defaultRowHeight;
612
- }
613
-
614
- availableWidth -= Math.round(newImgW);
615
- $entry.data('jg.jwidth', Math.round(newImgW));
616
- $entry.data('jg.jheight', Math.ceil(newImgH));
617
- if (i === 0 || minHeight > newImgH) minHeight = newImgH;
618
- }
619
-
620
- if (this.settings.fixedHeight && minHeight > this.settings.rowHeight)
621
- minHeight = this.settings.rowHeight;
622
-
623
- this.buildingRow.height = minHeight;
624
- return justify;
625
- };
626
-
627
- /**
628
- * Clear the building row data to be used for a new row
629
- */
630
- JustifiedGallery.prototype.clearBuildingRow = function () {
631
- this.buildingRow.entriesBuff = [];
632
- this.buildingRow.aspectRatio = 0;
633
- this.buildingRow.width = 0;
634
- };
635
-
636
- /**
637
- * Flush a row: justify it, modify the gallery height accordingly to the row height
638
- *
639
- * @param isLastRow
640
- */
641
- JustifiedGallery.prototype.flushRow = function (isLastRow) {
642
- var settings = this.settings;
643
- var $entry, buildingRowRes, offX = this.border, i;
644
-
645
- buildingRowRes = this.prepareBuildingRow(isLastRow);
646
- if (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1) {
647
- this.clearBuildingRow();
648
- return;
649
- }
650
-
651
- if (this.maxRowHeight.isPercentage) {
652
- if (this.maxRowHeight.value * settings.rowHeight < this.buildingRow.height) {
653
- this.buildingRow.height = this.maxRowHeight.value * settings.rowHeight;
654
- }
655
- } else {
656
- if (this.maxRowHeight.value > 0 && this.maxRowHeight.value < this.buildingRow.height) {
657
- this.buildingRow.height = this.maxRowHeight.value;
658
- }
659
- }
660
-
661
- //Align last (unjustified) row
662
- if (settings.lastRow === 'center' || settings.lastRow === 'right') {
663
- var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
664
-
665
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
666
- $entry = this.buildingRow.entriesBuff[i];
667
- availableWidth -= $entry.data('jg.jwidth');
668
- }
669
-
670
- if (settings.lastRow === 'center')
671
- offX += availableWidth / 2;
672
- else if (settings.lastRow === 'right')
673
- offX += availableWidth;
674
- }
675
-
676
- for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
677
- $entry = this.buildingRow.entriesBuff[i];
678
- this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
679
- offX += $entry.data('jg.jwidth') + settings.margins;
680
- }
681
-
682
- //Gallery Height
683
- this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
684
- this.$gallery.height(this.galleryHeightToSet + this.getSpinnerHeight());
685
-
686
- if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
687
- //Ready for a new row
688
- this.offY += this.buildingRow.height + settings.margins;
689
- this.rows += 1;
690
- this.clearBuildingRow();
691
- this.$gallery.trigger('jg.rowflush');
692
- }
693
- };
694
-
695
- /**
696
- * Checks the width of the gallery container, to know if a new justification is needed
697
- */
698
- var scrollBarOn = false;
699
- JustifiedGallery.prototype.checkWidth = function () {
700
- this.checkWidthIntervalId = setInterval($.proxy(function () {
701
- var galleryWidth = parseFloat(this.$gallery.width());
702
- if (hasScrollBar() === scrollBarOn){
703
-
704
- if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
705
- this.galleryWidth = galleryWidth;
706
- this.rewind();
707
-
708
- // Restart to analyze
709
- this.startImgAnalyzer(true);
710
- }
711
- } else {
712
- scrollBarOn = hasScrollBar();
713
- this.galleryWidth = galleryWidth;
714
- }
715
- }, this), this.settings.refreshTime);
716
- };
717
-
718
- /**
719
- * @returns {boolean} a boolean saying if the spinner is active or not
720
- */
721
- JustifiedGallery.prototype.isSpinnerActive = function () {
722
- return this.spinner.intervalId !== null;
723
- };
724
-
725
- /**
726
- * @returns {int} the spinner height
727
- */
728
- JustifiedGallery.prototype.getSpinnerHeight = function () {
729
- return this.spinner.$el.innerHeight();
730
- };
731
-
732
- /**
733
- * Stops the spinner animation and modify the gallery height to exclude the spinner
734
- */
735
- JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
736
- clearInterval(this.spinner.intervalId);
737
- this.spinner.intervalId = null;
738
- this.$gallery.height(this.$gallery.height() - this.getSpinnerHeight());
739
- this.spinner.$el.detach();
740
- };
741
-
742
- /**
743
- * Starts the spinner animation
744
- */
745
- JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
746
- var spinnerContext = this.spinner;
747
- var $spinnerPoints = spinnerContext.$el.find('span');
748
- clearInterval(spinnerContext.intervalId);
749
- this.$gallery.append(spinnerContext.$el);
750
- this.$gallery.height(this.offY + this.buildingRow.height + this.getSpinnerHeight());
751
- spinnerContext.intervalId = setInterval(function () {
752
- if (spinnerContext.phase < $spinnerPoints.length) {
753
- $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
754
- } else {
755
- $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
756
- }
757
- spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
758
- }, spinnerContext.timeSlot);
759
- };
760
-
761
- /**
762
- * Rewind the image analysis to start from the first entry.
763
- */
764
- JustifiedGallery.prototype.rewind = function () {
765
- this.lastAnalyzedIndex = -1;
766
- this.offY = this.border;
767
- this.rows = 0;
768
- this.clearBuildingRow();
769
- };
770
-
771
- /**
772
- * Update the entries searching it from the justified gallery HTML element
773
- *
774
- * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
775
- * @returns {boolean} true if some entries has been founded
776
- */
777
- JustifiedGallery.prototype.updateEntries = function (norewind) {
778
- this.entries = this.$gallery.find(this.settings.selector).toArray();
779
- if (this.entries.length === 0) return false;
780
-
781
- // Filter
782
- if (this.settings.filter) {
783
- this.modifyEntries(this.filterArray, norewind);
784
- } else {
785
- this.modifyEntries(this.resetFilters, norewind);
786
- }
787
-
788
- // Sort or randomize
789
- if ($.isFunction(this.settings.sort)) {
790
- this.modifyEntries(this.sortArray, norewind);
791
- } else if (this.settings.randomize) {
792
- this.modifyEntries(this.shuffleArray, norewind);
793
- }
794
-
795
- return true;
796
- };
797
-
798
- /**
799
- * Apply the entries order to the DOM, iterating the entries and appending the images
800
- *
801
- * @param entries the entries that has been modified and that must be re-ordered in the DOM
802
- */
803
- JustifiedGallery.prototype.insertToGallery = function (entries) {
804
- var that = this;
805
- $.each(entries, function () {
806
- $(this).appendTo(that.$gallery);
807
- });
808
- };
809
-
810
- /**
811
- * Shuffle the array using the Fisher-Yates shuffle algorithm
812
- *
813
- * @param a the array to shuffle
814
- * @return the shuffled array
815
- */
816
- JustifiedGallery.prototype.shuffleArray = function (a) {
817
- var i, j, temp;
818
- for (i = a.length - 1; i > 0; i--) {
819
- j = Math.floor(Math.random() * (i + 1));
820
- temp = a[i];
821
- a[i] = a[j];
822
- a[j] = temp;
823
- }
824
- this.insertToGallery(a);
825
- return a;
826
- };
827
-
828
- /**
829
- * Sort the array using settings.comparator as comparator
830
- *
831
- * @param a the array to sort (it is sorted)
832
- * @return the sorted array
833
- */
834
- JustifiedGallery.prototype.sortArray = function (a) {
835
- a.sort(this.settings.sort);
836
- this.insertToGallery(a);
837
- return a;
838
- };
839
-
840
- /**
841
- * Reset the filters removing the 'jg-filtered' class from all the entries
842
- *
843
- * @param a the array to reset
844
- */
845
- JustifiedGallery.prototype.resetFilters = function (a) {
846
- for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
847
- return a;
848
- };
849
-
850
- /**
851
- * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
852
- *
853
- * @param a the array to filter
854
- * @return the filtered array
855
- */
856
- JustifiedGallery.prototype.filterArray = function (a) {
857
- var settings = this.settings;
858
- if ($.type(settings.filter) === 'string') {
859
- // Filter only keeping the entries passed in the string
860
- return a.filter(function (el) {
861
- var $el = $(el);
862
- if ($el.is(settings.filter)) {
863
- $el.removeClass('jg-filtered');
864
- return true;
865
- } else {
866
- $el.addClass('jg-filtered');
867
- return false;
868
- }
869
- });
870
- } else if ($.isFunction(settings.filter)) {
871
- // Filter using the passed function
872
- return a.filter(settings.filter);
873
- }
874
- };
875
-
876
- /**
877
- * Modify the entries. With norewind only the new inserted images will be modified (the ones after lastAnalyzedIndex)
878
- *
879
- * @param functionToApply the function to call to modify the entries (e.g. sorting, randomization, filtering)
880
- * @param norewind specify if the norewind has been called or not
881
- */
882
- JustifiedGallery.prototype.modifyEntries = function (functionToApply, norewind) {
883
- var lastEntries = norewind ?
884
- this.entries.splice(this.lastAnalyzedIndex + 1, this.entries.length - this.lastAnalyzedIndex - 1)
885
- : this.entries;
886
- lastEntries = functionToApply.call(this, lastEntries);
887
- this.entries = norewind ? this.entries.concat(lastEntries) : lastEntries;
888
- };
889
-
890
- /**
891
- * Destroy the Justified Gallery instance.
892
- *
893
- * It clears all the css properties added in the style attributes. We doesn't backup the original
894
- * values for those css attributes, because it costs (performance) and because in general one
895
- * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
896
- * classes). Creating a backup is also difficult because JG could be called multiple times and
897
- * with different style attributes.
898
- */
899
- JustifiedGallery.prototype.destroy = function () {
900
- clearInterval(this.checkWidthIntervalId);
901
-
902
- $.each(this.entries, $.proxy(function(_, entry) {
903
- var $entry = $(entry);
904
-
905
- // Reset entry style
906
- $entry.css('width', '');
907
- $entry.css('height', '');
908
- $entry.css('top', '');
909
- $entry.css('left', '');
910
- $entry.data('jg.loaded', undefined);
911
- $entry.removeClass('jg-entry');
912
-
913
- // Reset image style
914
- var $img = this.imgFromEntry($entry);
915
- $img.css('width', '');
916
- $img.css('height', '');
917
- $img.css('margin-left', '');
918
- $img.css('margin-top', '');
919
- $img.attr('src', $img.data('jg.originalSrc'));
920
- $img.data('jg.originalSrc', undefined);
921
-
922
- // Remove caption
923
- this.removeCaptionEventsHandlers($entry);
924
- var $caption = this.captionFromEntry($entry);
925
- if ($entry.data('jg.createdCaption')) {
926
- // remove also the caption element (if created by jg)
927
- $entry.data('jg.createdCaption', undefined);
928
- if ($caption !== null) $caption.remove();
929
- } else {
930
- if ($caption !== null) $caption.fadeTo(0, 1);
931
- }
932
-
933
- }, this));
934
-
935
- this.$gallery.css('height', '');
936
- this.$gallery.removeClass('justified-gallery');
937
- this.$gallery.data('jg.controller', undefined);
938
- };
939
-
940
- /**
941
- * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
942
- *
943
- * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
944
- */
945
- JustifiedGallery.prototype.analyzeImages = function (isForResize) {
946
- for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
947
- var $entry = $(this.entries[i]);
948
- if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
949
- var availableWidth = this.galleryWidth - 2 * this.border - (
950
- (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
951
- var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
952
- if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
953
- this.flushRow(false);
954
- if(++this.yield.flushed >= this.yield.every) {
955
- this.startImgAnalyzer(isForResize);
956
- return;
957
- }
958
- }
959
-
960
- this.buildingRow.entriesBuff.push($entry);
961
- this.buildingRow.aspectRatio += imgAspectRatio;
962
- this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
963
- this.lastAnalyzedIndex = i;
964
-
965
- } else if ($entry.data('jg.loaded') !== 'error') {
966
- return;
967
- }
968
- }
969
-
970
- // Last row flush (the row is not full)
971
- if (this.buildingRow.entriesBuff.length > 0) this.flushRow(true);
972
-
973
- if (this.isSpinnerActive()) {
974
- this.stopLoadingSpinnerAnimation();
975
- }
976
-
977
- /* Stop, if there is, the timeout to start the analyzeImages.
978
- This is because an image can be set loaded, and the timeout can be set,
979
- but this image can be analyzed yet.
980
- */
981
- this.stopImgAnalyzerStarter();
982
-
983
- //On complete callback
984
- this.$gallery.trigger(isForResize ? 'jg.resize' : 'jg.complete');
985
- this.$gallery.height(this.galleryHeightToSet);
986
- };
987
-
988
- /**
989
- * Stops any ImgAnalyzer starter (that has an assigned timeout)
990
- */
991
- JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
992
- this.yield.flushed = 0;
993
- if (this.imgAnalyzerTimeout !== null) clearTimeout(this.imgAnalyzerTimeout);
994
- };
995
-
996
- /**
997
- * Starts the image analyzer. It is not immediately called to let the browser to update the view
998
- *
999
- * @param isForResize specifies if the image analyzer must be called for resizing or not
1000
- */
1001
- JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
1002
- var that = this;
1003
- this.stopImgAnalyzerStarter();
1004
- this.imgAnalyzerTimeout = setTimeout(function () {
1005
- that.analyzeImages(isForResize);
1006
- }, 0.001); // we can't start it immediately due to a IE different behaviour
1007
- };
1008
-
1009
- /**
1010
- * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
1011
- * because some browsers, with a 404 set complete = true.
1012
- *
1013
- * @param imageSrc the image src to load
1014
- * @param onLoad callback that is called when the image has been loaded
1015
- * @param onError callback that is called in case of an error
1016
- */
1017
- JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
1018
- if (!onLoad && !onError) return;
1019
-
1020
- var memImage = new Image();
1021
- var $memImage = $(memImage);
1022
- if (onLoad) {
1023
- $memImage.one('load', function () {
1024
- $memImage.off('load error');
1025
- onLoad(memImage);
1026
- });
1027
- }
1028
- if (onError) {
1029
- $memImage.one('error', function() {
1030
- $memImage.off('load error');
1031
- onError(memImage);
1032
- });
1033
- }
1034
- memImage.src = imageSrc;
1035
- };
1036
-
1037
- /**
1038
- * Init of Justified Gallery controlled
1039
- * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
1040
- */
1041
- JustifiedGallery.prototype.init = function () {
1042
- var imagesToLoad = false, skippedImages = false, that = this;
1043
- $.each(this.entries, function (index, entry) {
1044
- var $entry = $(entry);
1045
- var $image = that.imgFromEntry($entry);
1046
-
1047
- $entry.addClass('jg-entry');
1048
-
1049
- if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
1050
-
1051
- // Link Rel global overwrite
1052
- if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
1053
-
1054
- // Link Target global overwrite
1055
- if (that.settings.target !== null) $entry.attr('target', that.settings.target);
1056
-
1057
- if ($image !== null) {
1058
-
1059
- // Image src
1060
- var imageSrc = that.extractImgSrcFromImage($image);
1061
- $image.attr('src', imageSrc);
1062
-
1063
- /* If we have the height and the width, we don't wait that the image is loaded, but we start directly
1064
- * with the justification */
1065
- if (that.settings.waitThumbnailsLoad === false) {
1066
- var width = parseFloat($image.attr('width'));
1067
- var height = parseFloat($image.attr('height'));
1068
- if (!isNaN(width) && !isNaN(height)) {
1069
- $entry.data('jg.width', width);
1070
- $entry.data('jg.height', height);
1071
- $entry.data('jg.loaded', 'skipped');
1072
- skippedImages = true;
1073
- that.startImgAnalyzer(false);
1074
- return true; // continue
1075
- }
1076
- }
1077
-
1078
- $entry.data('jg.loaded', false);
1079
- imagesToLoad = true;
1080
-
1081
- // Spinner start
1082
- if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
1083
-
1084
- that.onImageEvent(imageSrc, function (loadImg) { // image loaded
1085
- $entry.data('jg.width', loadImg.width);
1086
- $entry.data('jg.height', loadImg.height);
1087
- $entry.data('jg.loaded', true);
1088
- that.startImgAnalyzer(false);
1089
- }, function () { // image load error
1090
- $entry.data('jg.loaded', 'error');
1091
- that.startImgAnalyzer(false);
1092
- });
1093
-
1094
- } else {
1095
- $entry.data('jg.loaded', true);
1096
- $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
1097
- $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
1098
- }
1099
-
1100
- }
1101
-
1102
- });
1103
-
1104
- if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
1105
- this.checkWidth();
1106
- };
1107
-
1108
- /**
1109
- * Checks that it is a valid number. If a string is passed it is converted to a number
1110
- *
1111
- * @param settingContainer the object that contains the setting (to allow the conversion)
1112
- * @param settingName the setting name
1113
- */
1114
- JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
1115
- if ($.type(settingContainer[settingName]) === 'string') {
1116
- settingContainer[settingName] = parseFloat(settingContainer[settingName]);
1117
- }
1118
-
1119
- if ($.type(settingContainer[settingName]) === 'number') {
1120
- if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
1121
- } else {
1122
- throw settingName + ' must be a number';
1123
- }
1124
- };
1125
-
1126
- /**
1127
- * Checks the sizeRangeSuffixes and, if necessary, converts
1128
- * its keys from string (e.g. old settings with 'lt100') to int.
1129
- */
1130
- JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
1131
- if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
1132
- throw 'sizeRangeSuffixes must be defined and must be an object';
1133
- }
1134
-
1135
- var suffixRanges = [];
1136
- for (var rangeIdx in this.settings.sizeRangeSuffixes) {
1137
- if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
1138
- }
1139
-
1140
- var newSizeRngSuffixes = {0: ''};
1141
- for (var i = 0; i < suffixRanges.length; i++) {
1142
- if ($.type(suffixRanges[i]) === 'string') {
1143
- try {
1144
- var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
1145
- newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
1146
- } catch (e) {
1147
- throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
1148
- }
1149
- } else {
1150
- newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
1151
- }
1152
- }
1153
-
1154
- this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
1155
- };
1156
-
1157
- /**
1158
- * check and convert the maxRowHeight setting
1159
- */
1160
- JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
1161
- var newMaxRowHeight = { };
1162
-
1163
- if ($.type(this.settings.maxRowHeight) === 'string') {
1164
- if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
1165
- newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
1166
- newMaxRowHeight.isPercentage = false;
1167
- } else {
1168
- newMaxRowHeight.value = parseFloat(this.settings.maxRowHeight);
1169
- newMaxRowHeight.isPercentage = true;
1170
- }
1171
- } else if ($.type(this.settings.maxRowHeight) === 'number') {
1172
- newMaxRowHeight.value = this.settings.maxRowHeight;
1173
- newMaxRowHeight.isPercentage = false;
1174
- } else {
1175
- throw 'maxRowHeight must be a number or a percentage';
1176
- }
1177
-
1178
- // check if the converted value is not a number
1179
- if (isNaN(newMaxRowHeight.value)) throw 'invalid number for maxRowHeight';
1180
-
1181
- // check values
1182
- if (newMaxRowHeight.isPercentage) {
1183
- if (newMaxRowHeight.value < 100) newMaxRowHeight.value = 100;
1184
- } else {
1185
- if (newMaxRowHeight.value > 0 && newMaxRowHeight.value < this.settings.rowHeight) {
1186
- newMaxRowHeight.value = this.settings.rowHeight;
1187
- }
1188
- }
1189
-
1190
- return newMaxRowHeight;
1191
-
1192
- };
1193
-
1194
- /**
1195
- * Checks the settings
1196
- */
1197
- JustifiedGallery.prototype.checkSettings = function () {
1198
- this.checkSizeRangesSuffixes();
1199
-
1200
- this.checkOrConvertNumber(this.settings, 'rowHeight');
1201
- this.checkOrConvertNumber(this.settings, 'margins');
1202
- this.checkOrConvertNumber(this.settings, 'border');
1203
-
1204
- var lastRowModes = [
1205
- 'justify',
1206
- 'nojustify',
1207
- 'left',
1208
- 'center',
1209
- 'right',
1210
- 'hide'
1211
- ];
1212
- if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
1213
- throw 'lastRow must be one of: ' + lastRowModes.join(', ');
1214
- }
1215
-
1216
- this.checkOrConvertNumber(this.settings, 'justifyThreshold');
1217
- if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
1218
- throw 'justifyThreshold must be in the interval [0,1]';
1219
- }
1220
- if ($.type(this.settings.cssAnimation) !== 'boolean') {
1221
- throw 'cssAnimation must be a boolean';
1222
- }
1223
-
1224
- if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
1225
- this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
1226
-
1227
- this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
1228
- if (this.settings.captionSettings.visibleOpacity < 0 ||
1229
- this.settings.captionSettings.visibleOpacity > 1) {
1230
- throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
1231
- }
1232
-
1233
- this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
1234
- if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
1235
- this.settings.captionSettings.nonVisibleOpacity > 1) {
1236
- throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
1237
- }
1238
-
1239
- if ($.type(this.settings.fixedHeight) !== 'boolean') throw 'fixedHeight must be a boolean';
1240
- this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
1241
- this.checkOrConvertNumber(this.settings, 'refreshTime');
1242
- this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
1243
- if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
1244
- if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
1245
-
1246
- if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
1247
- throw 'sort must be false or a comparison function';
1248
- }
1249
-
1250
- if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
1251
- $.type(this.settings.filter) !== 'string') {
1252
- throw 'filter must be false, a string or a filter function';
1253
- }
1254
- };
1255
-
1256
- /**
1257
- * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
1258
- * @returns {Array} sorted suffix ranges
1259
- */
1260
- JustifiedGallery.prototype.retrieveSuffixRanges = function () {
1261
- var suffixRanges = [];
1262
- for (var rangeIdx in this.settings.sizeRangeSuffixes) {
1263
- if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
1264
- }
1265
- suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
1266
- return suffixRanges;
1267
- };
1268
-
1269
- /**
1270
- * Update the existing settings only changing some of them
1271
- *
1272
- * @param newSettings the new settings (or a subgroup of them)
1273
- */
1274
- JustifiedGallery.prototype.updateSettings = function (newSettings) {
1275
- // In this case Justified Gallery has been called again changing only some options
1276
- this.settings = $.extend({}, this.settings, newSettings);
1277
- this.checkSettings();
1278
-
1279
- // As reported in the settings: negative value = same as margins, 0 = disabled
1280
- this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
1281
-
1282
- this.maxRowHeight = this.retrieveMaxRowHeight();
1283
- this.suffixRanges = this.retrieveSuffixRanges();
1284
- };
1285
-
1286
- /**
1287
- * Justified Gallery plugin for jQuery
1288
- *
1289
- * Events
1290
- * - jg.complete : called when all the gallery has been created
1291
- * - jg.resize : called when the gallery has been resized
1292
- * - jg.rowflush : when a new row appears
1293
- *
1294
- * @param arg the action (or the settings) passed when the plugin is called
1295
- * @returns {*} the object itself
1296
- */
1297
- $.fn.justifiedGallery = function (arg) {
1298
- return this.each(function (index, gallery) {
1299
-
1300
- var $gallery = $(gallery);
1301
- $gallery.addClass('justified-gallery');
1302
-
1303
- var controller = $gallery.data('jg.controller');
1304
- if (typeof controller === 'undefined') {
1305
- // Create controller and assign it to the object data
1306
- if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
1307
- if (arg === 'destroy') return; // Just a call to an unexisting object
1308
- throw 'The argument must be an object';
1309
- }
1310
- controller = new JustifiedGallery($gallery, $.extend({}, $.fn.justifiedGallery.defaults, arg));
1311
- $gallery.data('jg.controller', controller);
1312
- } else if (arg === 'norewind') {
1313
- // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
1314
- // ... left to be more readable
1315
- } else if (arg === 'destroy') {
1316
- controller.destroy();
1317
- return;
1318
- } else {
1319
- // In this case Justified Gallery has been called again changing only some options
1320
- controller.updateSettings(arg);
1321
- controller.rewind();
1322
- }
1323
-
1324
- // Update the entries list
1325
- if (!controller.updateEntries(arg === 'norewind')) return;
1326
-
1327
- // Init justified gallery
1328
- controller.init();
1329
-
1330
- });
1331
- };
1332
-
1333
- // Default options
1334
- $.fn.justifiedGallery.defaults = {
1335
- sizeRangeSuffixes: { }, /* e.g. Flickr configuration
1336
- {
1337
- 100: '_t', // used when longest is less than 100px
1338
- 240: '_m', // used when longest is between 101px and 240px
1339
- 320: '_n', // ...
1340
- 500: '',
1341
- 640: '_z',
1342
- 1024: '_b' // used as else case because it is the last
1343
- }
1344
- */
1345
- thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
1346
- path relative to a specific thumbnail size. The function should accept respectively three arguments:
1347
- current path, width and height */
1348
- rowHeight: 120,
1349
- maxRowHeight: -1, // negative value = no limits, number to express the value in pixels,
1350
- // '[0-9]+%' to express in percentage (e.g. 300% means that the row height
1351
- // can't exceed 3 * rowHeight)
1352
- margins: 1,
1353
- border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
1354
-
1355
- lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
1356
-
1357
- justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
1358
- * (i.e. lastRow setting is not considered) */
1359
- fixedHeight: false,
1360
- waitThumbnailsLoad: true,
1361
- captions: true,
1362
- cssAnimation: false,
1363
- imagesAnimationDuration: 500, // ignored with css animations
1364
- captionSettings: { // ignored with css animations
1365
- animationDuration: 500,
1366
- visibleOpacity: 0.7,
1367
- nonVisibleOpacity: 0.0
1368
- },
1369
- rel: null, // rewrite the rel of each analyzed links
1370
- target: null, // rewrite the target of all links
1371
- extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
1372
- refreshTime: 200, // time interval (in ms) to check if the page changes its width
1373
- refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
1374
- randomize: false,
1375
- sort: false, /*
1376
- - false: to do not sort
1377
- - function: to sort them using the function as comparator (see Array.prototype.sort())
1378
- */
1379
- filter: false, /*
1380
- - false: for a disabled filter
1381
- - a string: an entry is kept if entry.is(filter string) returns true
1382
- see jQuery's .is() function for further information
1383
- - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
1384
- see Array.prototype.filter for further information.
1385
- */
1386
- selector: '> a, > div:not(.spinner)' // The selector that is used to know what are the entries of the gallery
1387
- };
1388
-
1389
- }(jQuery));
1390
-
1391
- /*!
1392
- * Justified Gallery / Envira Extensions and Overrides - v3.6.2
1393
- * Copyright (c) 2016 David Bisset, Benjamin Rojas
1394
- * Licensed under the MIT license.
1395
- */
1396
-
1397
- (function ($) {
1398
- var justifiedGallery = $.fn.justifiedGallery;
1399
- var EnviraJustifiedGallery = {};
1400
-
1401
- $.fn.enviraJustifiedGallery = function () {
1402
- var obj = justifiedGallery.apply(this, arguments);
1403
- EnviraJustifiedGallery = obj.data('jg.controller');
1404
-
1405
- EnviraJustifiedGallery.displayEntryCaption = function ($entry) {
1406
-
1407
- var $image = this.imgFromEntry($entry);
1408
- if ($image !== null && this.settings.captions) {
1409
- var $imgCaption = this.captionFromEntry($entry);
1410
-
1411
- // Create it if it doesn't exists
1412
- if ($imgCaption === null) {
1413
-
1414
- var caption = $image.data('envira-caption');
1415
-
1416
- if (this.isValidCaption(caption)) { // Create only we found something
1417
- $imgCaption = $('<div class="caption">' + caption + '</div>');
1418
- $entry.append($imgCaption);
1419
- $entry.data('jg.createdCaption', true);
1420
- }
1421
- }
1422
-
1423
- // Create events (we check again the $imgCaption because it can be still inexistent)
1424
- if ($imgCaption !== null) {
1425
- if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
1426
- this.addCaptionEventsHandlers($entry);
1427
- }
1428
- } else {
1429
- this.removeCaptionEventsHandlers($entry);
1430
- }
1431
- };
1432
-
1433
- return EnviraJustifiedGallery;
1434
-
1435
- };
1436
- })(jQuery);
1437
-
1438
- /*!
1439
  * vintageJS
1440
  * Add a retro/vintage effect to images using the HTML5 canvas element
1441
  *
@@ -1443,9189 +6,6 @@ function jg_effect_vintage( img ) {
1443
  * @author Robert Fleischmann <rendro87@gmail.com>
1444
  * @version 1.1.5
1445
  */
1446
-
1447
- !function(a,b){"function"==typeof define&&define.amd?define("vintagejs",["jquery"],function(c){return a.VintageJS=b(c)}):"object"==typeof exports?module.exports=b(require("jquery")):a.VintageJS=b(jQuery)}(this,function(a){var b=function(a,b,c){if(!1==a instanceof HTMLImageElement)throw"The element (1st parameter) must be an instance of HTMLImageElement";var d,e,f,g,h,i,j,k,l,m=new Image,n=new Image,o=document.createElement("canvas"),p=o.getContext("2d"),q={onStart:function(){},onStop:function(){},onError:function(){},mime:"image/jpeg"},r={curves:!1,screen:!1,desaturate:!1,vignette:!1,lighten:!1,noise:!1,viewFinder:!1,sepia:!1,brightness:!1,contrast:!1};m.onerror=q.onError,m.onload=function(){i=o.width=m.width,j=o.height=m.height,d()},n.onerror=q.onError,n.onload=function(){p.clearRect(0,0,i,j),p.drawImage(n,0,0,i,j),(window.vjsImageCache||(window.vjsImageCache={}))[l]=p.getImageData(0,0,i,j).data,d()},e=function(a){q.onStart(),k={};for(var b in r)k[b]=a[b]||r[b];g=[],k.viewFinder&&g.push(k.viewFinder),m.src==h?d():m.src=h},d=function(){if(0===g.length)return f();var a=g.pop();return l=[i,j,a].join("-"),window.vjsImageCache&&window.vjsImageCache[l]?d():void(n.src=a)},f=function(){var b,c,d;p.clearRect(0,0,i,j),p.drawImage(m,0,0,i,j),(k.vignette||k.lighten)&&(b=Math.sqrt(Math.pow(i/2,2)+Math.pow(j/2,2))),k.vignette&&(p.globalCompositeOperation="source-over",c=p.createRadialGradient(i/2,j/2,0,i/2,j/2,b),c.addColorStop(0,"rgba(0,0,0,0)"),c.addColorStop(.5,"rgba(0,0,0,0)"),c.addColorStop(1,["rgba(0,0,0,",k.vignette,")"].join("")),p.fillStyle=c,p.fillRect(0,0,i,j)),k.lighten&&(p.globalCompositeOperation="lighter",c=p.createRadialGradient(i/2,j/2,0,i/2,j/2,b),c.addColorStop(0,["rgba(255,255,255,",k.lighten,")"].join("")),c.addColorStop(.5,"rgba(255,255,255,0)"),c.addColorStop(1,"rgba(0,0,0,0)"),p.fillStyle=c,p.fillRect(0,0,i,j)),d=p.getImageData(0,0,i,j);var e,f,g,h,l,n,o,r,s,t=d.data;k.contrast&&(s=259*(k.contrast+255)/(255*(259-k.contrast))),k.viewFinder&&(r=window.vjsImageCache[[i,j,k.viewFinder].join("-")]);for(var u=i*j;u>=0;--u)for(e=u<<2,k.curves&&(t[e]=k.curves.r[t[e]],t[e+1]=k.curves.g[t[e+1]],t[e+2]=k.curves.b[t[e+2]]),k.contrast&&(t[e]=s*(t[e]-128)+128,t[e+1]=s*(t[e+1]-128)+128,t[e+2]=s*(t[e+2]-128)+128),k.brightness&&(t[e]+=k.brightness,t[e+1]+=k.brightness,t[e+2]+=k.brightness),k.screen&&(t[e]=255-(255-t[e])*(255-k.screen.r*k.screen.a)/255,t[e+1]=255-(255-t[e+1])*(255-k.screen.g*k.screen.a)/255,t[e+2]=255-(255-t[e+2])*(255-k.screen.b*k.screen.a)/255),k.noise&&(o=k.noise-Math.random()*k.noise/2,t[e]+=o,t[e+1]+=o,t[e+2]+=o),k.viewFinder&&(t[e]=t[e]*r[e]/255,t[e+1]=t[e+1]*r[e+1]/255,t[e+2]=t[e+2]*r[e+2]/255),k.sepia&&(g=t[e],h=t[e+1],l=t[e+2],t[e]=.393*g+.769*h+.189*l,t[e+1]=.349*g+.686*h+.168*l,t[e+2]=.272*g+.534*h+.131*l),k.desaturate&&(n=(t[e]+t[e+1]+t[e+2])/3,t[e]+=(n-t[e])*k.desaturate,t[e+1]+=(n-t[e+1])*k.desaturate,t[e+2]+=(n-t[e+2])*k.desaturate),f=2;f>=0;--f)t[e+f]=~~(t[e+f]>255?255:t[e+f]<0?0:t[e+f]);p.putImageData(d,0,0),a.src=p.canvas.toDataURL(q.mime),q.onStop()},h=a.src,b=b||{};for(var s in q)q[s]=b[s]||q[s];return c&&e(c),{apply:function(){h=a.src},reset:function(){a.src=h},vintage:e}};return a.fn.vintage=function(c,d){return this.each(function(){a.data(this,"vintageJS")||a.data(this,"vintageJS",new b(this,c,d))})},b});
1448
-
1449
-
1450
- /*
1451
-
1452
- Superfast Blur - a fast Box Blur For Canvas
1453
-
1454
- Version: 0.5
1455
- Author: Mario Klingemann
1456
- Contact: mario@quasimondo.com
1457
- Website: http://www.quasimondo.com/BoxBlurForCanvas
1458
- Twitter: @quasimondo
1459
-
1460
- In case you find this class useful - especially in commercial projects -
1461
- I am not totally unhappy for a small donation to my PayPal account
1462
- mario@quasimondo.de
1463
-
1464
- Or support me on flattr:
1465
- https://flattr.com/thing/140066/Superfast-Blur-a-pretty-fast-Box-Blur-Effect-for-CanvasJavascript
1466
-
1467
- Copyright (c) 2011 Mario Klingemann
1468
-
1469
- Permission is hereby granted, free of charge, to any person
1470
- obtaining a copy of this software and associated documentation
1471
- files (the "Software"), to deal in the Software without
1472
- restriction, including without limitation the rights to use,
1473
- copy, modify, merge, publish, distribute, sublicense, and/or sell
1474
- copies of the Software, and to permit persons to whom the
1475
- Software is furnished to do so, subject to the following
1476
- conditions:
1477
-
1478
- The above copyright notice and this permission notice shall be
1479
- included in all copies or substantial portions of the Software.
1480
-
1481
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1482
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1483
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1484
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1485
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1486
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1487
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1488
- OTHER DEALINGS IN THE SOFTWARE.
1489
- */
1490
- var mul_table = [ 1,57,41,21,203,34,97,73,227,91,149,62,105,45,39,137,241,107,3,173,39,71,65,238,219,101,187,87,81,151,141,133,249,117,221,209,197,187,177,169,5,153,73,139,133,127,243,233,223,107,103,99,191,23,177,171,165,159,77,149,9,139,135,131,253,245,119,231,224,109,211,103,25,195,189,23,45,175,171,83,81,79,155,151,147,9,141,137,67,131,129,251,123,30,235,115,113,221,217,53,13,51,50,49,193,189,185,91,179,175,43,169,83,163,5,79,155,19,75,147,145,143,35,69,17,67,33,65,255,251,247,243,239,59,29,229,113,111,219,27,213,105,207,51,201,199,49,193,191,47,93,183,181,179,11,87,43,85,167,165,163,161,159,157,155,77,19,75,37,73,145,143,141,35,138,137,135,67,33,131,129,255,63,250,247,61,121,239,237,117,29,229,227,225,111,55,109,216,213,211,209,207,205,203,201,199,197,195,193,48,190,47,93,185,183,181,179,178,176,175,173,171,85,21,167,165,41,163,161,5,79,157,78,154,153,19,75,149,74,147,73,144,143,71,141,140,139,137,17,135,134,133,66,131,65,129,1];
1491
-
1492
-
1493
- var shg_table = [0,9,10,10,14,12,14,14,16,15,16,15,16,15,15,17,18,17,12,18,16,17,17,19,19,18,19,18,18,19,19,19,20,19,20,20,20,20,20,20,15,20,19,20,20,20,21,21,21,20,20,20,21,18,21,21,21,21,20,21,17,21,21,21,22,22,21,22,22,21,22,21,19,22,22,19,20,22,22,21,21,21,22,22,22,18,22,22,21,22,22,23,22,20,23,22,22,23,23,21,19,21,21,21,23,23,23,22,23,23,21,23,22,23,18,22,23,20,22,23,23,23,21,22,20,22,21,22,24,24,24,24,24,22,21,24,23,23,24,21,24,23,24,22,24,24,22,24,24,22,23,24,24,24,20,23,22,23,24,24,24,24,24,24,24,23,21,23,22,23,24,24,24,22,24,24,24,23,22,24,24,25,23,25,25,23,24,25,25,24,22,25,25,25,24,23,24,25,25,25,25,25,25,25,25,25,25,25,25,23,25,23,24,25,25,25,25,25,25,25,25,25,24,22,25,25,23,25,25,20,24,25,24,25,25,22,24,25,24,25,24,25,25,24,25,25,25,25,22,25,25,25,24,25,24,25,18];
1494
-
1495
-
1496
- function boxBlurImage( imageID, canvasID, radius, blurAlphaChannel, iterations ){
1497
-
1498
- var img = document.getElementById( imageID );
1499
- var w = img.naturalWidth;
1500
- var h = img.naturalHeight;
1501
-
1502
- var canvas = document.getElementById( canvasID );
1503
-
1504
- canvas.style.width = w + "px";
1505
- canvas.style.height = h + "px";
1506
- canvas.width = w;
1507
- canvas.height = h;
1508
-
1509
- var context = canvas.getContext("2d");
1510
- context.clearRect( 0, 0, w, h );
1511
- context.drawImage( img, 0, 0 );
1512
-
1513
- if ( isNaN(radius) || radius < 1 ) return;
1514
-
1515
- if ( blurAlphaChannel )
1516
- {
1517
- boxBlurCanvasRGBA( canvasID, 0, 0, w, h, radius, iterations );
1518
- } else {
1519
- boxBlurCanvasRGB( canvasID, 0, 0, w, h, radius, iterations );
1520
- }
1521
-
1522
- }
1523
-
1524
-
1525
- function boxBlurCanvasRGBA( id, top_x, top_y, width, height, radius, iterations ){
1526
- if ( isNaN(radius) || radius < 1 ) return;
1527
-
1528
- radius |= 0;
1529
-
1530
- if ( isNaN(iterations) ) iterations = 1;
1531
- iterations |= 0;
1532
- if ( iterations > 3 ) iterations = 3;
1533
- if ( iterations < 1 ) iterations = 1;
1534
-
1535
- var canvas = document.getElementById( id );
1536
- var context = canvas.getContext("2d");
1537
- var imageData;
1538
-
1539
- try {
1540
- try {
1541
- imageData = context.getImageData( top_x, top_y, width, height );
1542
- } catch(e) {
1543
-
1544
- // NOTE: this part is supposedly only needed if you want to work with local files
1545
- // so it might be okay to remove the whole try/catch block and just use
1546
- // imageData = context.getImageData( top_x, top_y, width, height );
1547
- try {
1548
- netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
1549
- imageData = context.getImageData( top_x, top_y, width, height );
1550
- } catch(e) {
1551
- alert("Cannot access local image");
1552
- throw new Error("unable to access local image data: " + e);
1553
- return;
1554
- }
1555
- }
1556
- } catch(e) {
1557
- alert("Cannot access image");
1558
- throw new Error("unable to access image data: " + e);
1559
- return;
1560
- }
1561
-
1562
- var pixels = imageData.data;
1563
-
1564
- var rsum,gsum,bsum,asum,x,y,i,p,p1,p2,yp,yi,yw,idx,pa;
1565
- var wm = width - 1;
1566
- var hm = height - 1;
1567
- var wh = width * height;
1568
- var rad1 = radius + 1;
1569
-
1570
- var mul_sum = mul_table[radius];
1571
- var shg_sum = shg_table[radius];
1572
-
1573
- var r = [];
1574
- var g = [];
1575
- var b = [];
1576
- var a = [];
1577
-
1578
- var vmin = [];
1579
- var vmax = [];
1580
-
1581
- while ( iterations-- > 0 ){
1582
- yw = yi = 0;
1583
-
1584
- for ( y=0; y < height; y++ ){
1585
- rsum = pixels[yw] * rad1;
1586
- gsum = pixels[yw+1] * rad1;
1587
- bsum = pixels[yw+2] * rad1;
1588
- asum = pixels[yw+3] * rad1;
1589
-
1590
-
1591
- for( i = 1; i <= radius; i++ ){
1592
- p = yw + (((i > wm ? wm : i )) << 2 );
1593
- rsum += pixels[p++];
1594
- gsum += pixels[p++];
1595
- bsum += pixels[p++];
1596
- asum += pixels[p]
1597
- }
1598
-
1599
- for ( x = 0; x < width; x++ ) {
1600
- r[yi] = rsum;
1601
- g[yi] = gsum;
1602
- b[yi] = bsum;
1603
- a[yi] = asum;
1604
-
1605
- if( y==0) {
1606
- vmin[x] = ( ( p = x + rad1) < wm ? p : wm ) << 2;
1607
- vmax[x] = ( ( p = x - radius) > 0 ? p << 2 : 0 );
1608
- }
1609
-
1610
- p1 = yw + vmin[x];
1611
- p2 = yw + vmax[x];
1612
-
1613
- rsum += pixels[p1++] - pixels[p2++];
1614
- gsum += pixels[p1++] - pixels[p2++];
1615
- bsum += pixels[p1++] - pixels[p2++];
1616
- asum += pixels[p1] - pixels[p2];
1617
-
1618
- yi++;
1619
- }
1620
- yw += ( width << 2 );
1621
- }
1622
-
1623
- for ( x = 0; x < width; x++ ) {
1624
- yp = x;
1625
- rsum = r[yp] * rad1;
1626
- gsum = g[yp] * rad1;
1627
- bsum = b[yp] * rad1;
1628
- asum = a[yp] * rad1;
1629
-
1630
- for( i = 1; i <= radius; i++ ) {
1631
- yp += ( i > hm ? 0 : width );
1632
- rsum += r[yp];
1633
- gsum += g[yp];
1634
- bsum += b[yp];
1635
- asum += a[yp];
1636
- }
1637
-
1638
- yi = x << 2;
1639
- for ( y = 0; y < height; y++) {
1640
-
1641
- pixels[yi+3] = pa = (asum * mul_sum) >>> shg_sum;
1642
- if ( pa > 0 )
1643
- {
1644
- pa = 255 / pa;
1645
- pixels[yi] = ((rsum * mul_sum) >>> shg_sum) * pa;
1646
- pixels[yi+1] = ((gsum * mul_sum) >>> shg_sum) * pa;
1647
- pixels[yi+2] = ((bsum * mul_sum) >>> shg_sum) * pa;
1648
- } else {
1649
- pixels[yi] = pixels[yi+1] = pixels[yi+2] = 0;
1650
- }
1651
- if( x == 0 ) {
1652
- vmin[y] = ( ( p = y + rad1) < hm ? p : hm ) * width;
1653
- vmax[y] = ( ( p = y - radius) > 0 ? p * width : 0 );
1654
- }
1655
-
1656
- p1 = x + vmin[y];
1657
- p2 = x + vmax[y];
1658
-
1659
- rsum += r[p1] - r[p2];
1660
- gsum += g[p1] - g[p2];
1661
- bsum += b[p1] - b[p2];
1662
- asum += a[p1] - a[p2];
1663
-
1664
- yi += width << 2;
1665
- }
1666
- }
1667
- }
1668
-
1669
- context.putImageData( imageData, top_x, top_y );
1670
-
1671
- }
1672
-
1673
- function boxBlurCanvasRGB( id, top_x, top_y, width, height, radius, iterations ){
1674
- if ( isNaN(radius) || radius < 1 ) return;
1675
-
1676
- radius |= 0;
1677
-
1678
- if ( isNaN(iterations) ) iterations = 1;
1679
- iterations |= 0;
1680
- if ( iterations > 3 ) iterations = 3;
1681
- if ( iterations < 1 ) iterations = 1;
1682
-
1683
- var canvas = id;
1684
- var context = canvas.getContext("2d");
1685
- var imageData;
1686
-
1687
- try {
1688
- try {
1689
- imageData = context.getImageData( top_x, top_y, width, height );
1690
- } catch(e) {
1691
-
1692
- // NOTE: this part is supposedly only needed if you want to work with local files
1693
- // so it might be okay to remove the whole try/catch block and just use
1694
- // imageData = context.getImageData( top_x, top_y, width, height );
1695
- try {
1696
- netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
1697
- imageData = context.getImageData( top_x, top_y, width, height );
1698
- } catch(e) {
1699
- alert("Cannot access local image");
1700
- throw new Error("unable to access local image data: " + e);
1701
- return;
1702
- }
1703
- }
1704
- } catch(e) {
1705
- alert("Cannot access image");
1706
- throw new Error("unable to access image data: " + e);
1707
- return;
1708
- }
1709
-
1710
- var pixels = imageData.data;
1711
-
1712
- var rsum,gsum,bsum,asum,x,y,i,p,p1,p2,yp,yi,yw,idx;
1713
- var wm = width - 1;
1714
- var hm = height - 1;
1715
- var wh = width * height;
1716
- var rad1 = radius + 1;
1717
-
1718
- var r = [];
1719
- var g = [];
1720
- var b = [];
1721
-
1722
- var mul_sum = mul_table[radius];
1723
- var shg_sum = shg_table[radius];
1724
-
1725
- var vmin = [];
1726
- var vmax = [];
1727
-
1728
- while ( iterations-- > 0 ){
1729
- yw = yi = 0;
1730
-
1731
- for ( y=0; y < height; y++ ){
1732
- rsum = pixels[yw] * rad1;
1733
- gsum = pixels[yw+1] * rad1;
1734
- bsum = pixels[yw+2] * rad1;
1735
-
1736
- for( i = 1; i <= radius; i++ ){
1737
- p = yw + (((i > wm ? wm : i )) << 2 );
1738
- rsum += pixels[p++];
1739
- gsum += pixels[p++];
1740
- bsum += pixels[p++];
1741
- }
1742
-
1743
- for ( x = 0; x < width; x++ ){
1744
- r[yi] = rsum;
1745
- g[yi] = gsum;
1746
- b[yi] = bsum;
1747
-
1748
- if( y==0) {
1749
- vmin[x] = ( ( p = x + rad1) < wm ? p : wm ) << 2;
1750
- vmax[x] = ( ( p = x - radius) > 0 ? p << 2 : 0 );
1751
- }
1752
-
1753
- p1 = yw + vmin[x];
1754
- p2 = yw + vmax[x];
1755
-
1756
- rsum += pixels[p1++] - pixels[p2++];
1757
- gsum += pixels[p1++] - pixels[p2++];
1758
- bsum += pixels[p1++] - pixels[p2++];
1759
-
1760
- yi++;
1761
- }
1762
- yw += ( width << 2 );
1763
- }
1764
-
1765
- for ( x = 0; x < width; x++ ){
1766
- yp = x;
1767
- rsum = r[yp] * rad1;
1768
- gsum = g[yp] * rad1;
1769
- bsum = b[yp] * rad1;
1770
-
1771
- for( i = 1; i <= radius; i++ ){
1772
- yp += ( i > hm ? 0 : width );
1773
- rsum += r[yp];
1774
- gsum += g[yp];
1775
- bsum += b[yp];
1776
- }
1777
-
1778
- yi = x << 2;
1779
- for ( y = 0; y < height; y++){
1780
- pixels[yi] = (rsum * mul_sum) >>> shg_sum;
1781
- pixels[yi+1] = (gsum * mul_sum) >>> shg_sum;
1782
- pixels[yi+2] = (bsum * mul_sum) >>> shg_sum;
1783
-
1784
- if( x == 0 ) {
1785
- vmin[y] = ( ( p = y + rad1) < hm ? p : hm ) * width;
1786
- vmax[y] = ( ( p = y - radius) > 0 ? p * width : 0 );
1787
- }
1788
-
1789
- p1 = x + vmin[y];
1790
- p2 = x + vmax[y];
1791
-
1792
- rsum += r[p1] - r[p2];
1793
- gsum += g[p1] - g[p2];
1794
- bsum += b[p1] - b[p2];
1795
-
1796
- yi += width << 2;
1797
- }
1798
- }
1799
- }
1800
- context.putImageData( imageData, top_x, top_y );
1801
-
1802
- }
1803
-
1804
- /*
1805
- * @fileOverview TouchSwipe - jQuery Plugin
1806
- * @version 1.6.6
1807
- *
1808
- * @author Matt Bryson http://www.github.com/mattbryson
1809
- * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
1810
- * @see http://labs.rampinteractive.co.uk/touchSwipe/
1811
- * @see http://plugins.jquery.com/project/touchSwipe
1812
- *
1813
- * Copyright (c) 2010-2015 Matt Bryson
1814
- * Dual licensed under the MIT or GPL Version 2 licenses.
1815
- *
1816
- */
1817
-
1818
- /*
1819
- *
1820
- * Changelog
1821
- * $Date: 2010-12-12 (Wed, 12 Dec 2010) $
1822
- * $version: 1.0.0
1823
- * $version: 1.0.1 - removed multibyte comments
1824
- *
1825
- * $Date: 2011-21-02 (Mon, 21 Feb 2011) $
1826
- * $version: 1.1.0 - added allowPageScroll property to allow swiping and scrolling of page
1827
- * - changed handler signatures so one handler can be used for multiple events
1828
- * $Date: 2011-23-02 (Wed, 23 Feb 2011) $
1829
- * $version: 1.2.0 - added click handler. This is fired if the user simply clicks and does not swipe. The event object and click target are passed to handler.
1830
- * - If you use the http://code.google.com/p/jquery-ui-for-ipad-and-iphone/ plugin, you can also assign jQuery mouse events to children of a touchSwipe object.
1831
- * $version: 1.2.1 - removed console log!
1832
- *
1833
- * $version: 1.2.2 - Fixed bug where scope was not preserved in callback methods.
1834
- *
1835
- * $Date: 2011-28-04 (Thurs, 28 April 2011) $
1836
- * $version: 1.2.4 - Changed licence terms to be MIT or GPL inline with jQuery. Added check for support of touch events to stop non compatible browsers erroring.
1837
- *
1838
- * $Date: 2011-27-09 (Tues, 27 September 2011) $
1839
- * $version: 1.2.5 - Added support for testing swipes with mouse on desktop browser (thanks to https://github.com/joelhy)
1840
- *
1841
- * $Date: 2012-14-05 (Mon, 14 May 2012) $
1842
- * $version: 1.2.6 - Added timeThreshold between start and end touch, so user can ignore slow swipes (thanks to Mark Chase). Default is null, all swipes are detected
1843
- *
1844
- * $Date: 2012-05-06 (Tues, 05 June 2012) $
1845
- * $version: 1.2.7 - Changed time threshold to have null default for backwards compatibility. Added duration param passed back in events, and refactored how time is handled.
1846
- *
1847
- * $Date: 2012-05-06 (Tues, 05 June 2012) $
1848
- * $version: 1.2.8 - Added the possibility to return a value like null or false in the trigger callback. In that way we can control when the touch start/move should take effect or not (simply by returning in some cases return null; or return false;) This effects the ontouchstart/ontouchmove event.
1849
- *
1850
- * $Date: 2012-06-06 (Wed, 06 June 2012) $
1851
- * $version: 1.3.0 - Refactored whole plugin to allow for methods to be executed, as well as exposed defaults for user override. Added 'enable', 'disable', and 'destroy' methods
1852
- *
1853
- * $Date: 2012-05-06 (Fri, 05 June 2012) $
1854
- * $version: 1.3.1 - Bug fixes - bind() with false as last argument is no longer supported in jQuery 1.6, also, if you just click, the duration is now returned correctly.
1855
- *
1856
- * $Date: 2012-29-07 (Sun, 29 July 2012) $
1857
- * $version: 1.3.2 - Added fallbackToMouseEvents option to NOT capture mouse events on non touch devices.
1858
- * - Added "all" fingers value to the fingers property, so any combination of fingers triggers the swipe, allowing event handlers to check the finger count
1859
- *
1860
- * $Date: 2012-09-08 (Thurs, 9 Aug 2012) $
1861
- * $version: 1.3.3 - Code tidy prep for minefied version
1862
- *
1863
- * $Date: 2012-04-10 (wed, 4 Oct 2012) $
1864
- * $version: 1.4.0 - Added pinch support, pinchIn and pinchOut
1865
- *
1866
- * $Date: 2012-11-10 (Thurs, 11 Oct 2012) $
1867
- * $version: 1.5.0 - Added excludedElements, a jquery selector that specifies child elements that do NOT trigger swipes. By default, this is one select that removes all form, input select, button and anchor elements.
1868
- *
1869
- * $Date: 2012-22-10 (Mon, 22 Oct 2012) $
1870
- * $version: 1.5.1 - Fixed bug with jQuery 1.8 and trailing comma in excludedElements
1871
- * - Fixed bug with IE and eventPreventDefault()
1872
- * $Date: 2013-01-12 (Fri, 12 Jan 2013) $
1873
- * $version: 1.6.0 - Fixed bugs with pinching, mainly when both pinch and swipe enabled, as well as adding time threshold for multifinger gestures, so releasing one finger beofre the other doesnt trigger as single finger gesture.
1874
- * - made the demo site all static local HTML pages so they can be run locally by a developer
1875
- * - added jsDoc comments and added documentation for the plugin
1876
- * - code tidy
1877
- * - added triggerOnTouchLeave property that will end the event when the user swipes off the element.
1878
- * $Date: 2013-03-23 (Sat, 23 Mar 2013) $
1879
- * $version: 1.6.1 - Added support for ie8 touch events
1880
- * $version: 1.6.2 - Added support for events binding with on / off / bind in jQ for all callback names.
1881
- * - Deprecated the 'click' handler in favour of tap.
1882
- * - added cancelThreshold property
1883
- * - added option method to update init options at runtime
1884
- * $version 1.6.3 - added doubletap, longtap events and longTapThreshold, doubleTapThreshold property
1885
- *
1886
- * $Date: 2013-04-04 (Thurs, 04 April 2013) $
1887
- * $version 1.6.4 - Fixed bug with cancelThreshold introduced in 1.6.3, where swipe status no longer fired start event, and stopped once swiping back.
1888
- *
1889
- * $Date: 2013-08-24 (Sat, 24 Aug 2013) $
1890
- * $version 1.6.5 - Merged a few pull requests fixing various bugs, added AMD support.
1891
- *
1892
- * $Date: 2014-06-04 (Wed, 04 June 2014) $
1893
- * $version 1.6.6 - Merge of pull requests.
1894
- * - IE10 touch support
1895
- * - Only prevent default event handling on valid swipe
1896
- * - Separate license/changelog comment
1897
- * - Detect if the swipe is valid at the end of the touch event.
1898
- * - Pass fingerdata to event handlers.
1899
- * - Add 'hold' gesture
1900
- * - Be more tolerant about the tap distance
1901
- * - Typos and minor fixes
1902
- *
1903
- * $Date: 2015-22-01 (Thurs, 22 Jan 2015) $
1904
- * $version 1.6.7 - Added patch from https://github.com/mattbryson/TouchSwipe-Jquery-Plugin/issues/206 to fix memory leak
1905
- */
1906
-
1907
- /**
1908
- * See (http://jquery.com/).
1909
- * @name $
1910
- * @class
1911
- * See the jQuery Library (http://jquery.com/) for full details. This just
1912
- * documents the function and classes that are added to jQuery by this plug-in.
1913
- */
1914
-
1915
- /**
1916
- * See (http://jquery.com/)
1917
- * @name fn
1918
- * @class
1919
- * See the jQuery Library (http://jquery.com/) for full details. This just
1920
- * documents the function and classes that are added to jQuery by this plug-in.
1921
- * @memberOf $
1922
- */
1923
-
1924
-
1925
-
1926
- (function (factory) {
1927
- if (typeof define === 'function' && define.amd && define.amd.jQuery) {
1928
- // AMD. Register as anonymous module.
1929
- define(['jquery'], factory);
1930
- } else {
1931
- // Browser globals.
1932
- factory(jQuery);
1933
- }
1934
- }(function ($) {
1935
- "use strict";
1936
-
1937
- //Constants
1938
- var LEFT = "left",
1939
- RIGHT = "right",
1940
- UP = "up",
1941
- DOWN = "down",
1942
- IN = "in",
1943
- OUT = "out",
1944
-
1945
- NONE = "none",
1946
- AUTO = "auto",
1947
-
1948
- SWIPE = "swipe",
1949
- PINCH = "pinch",
1950
- TAP = "tap",
1951
- DOUBLE_TAP = "doubletap",
1952
- LONG_TAP = "longtap",
1953
- HOLD = "hold",
1954
-
1955
- HORIZONTAL = "horizontal",
1956
- VERTICAL = "vertical",
1957
-
1958
- ALL_FINGERS = "all",
1959
-
1960
- DOUBLE_TAP_THRESHOLD = 10,
1961
-
1962
- PHASE_START = "start",
1963
- PHASE_MOVE = "move",
1964
- PHASE_END = "end",
1965
- PHASE_CANCEL = "cancel",
1966
-
1967
- SUPPORTS_TOUCH = 'ontouchstart' in window,
1968
-
1969
- SUPPORTS_POINTER_IE10 = window.navigator.msPointerEnabled && !window.navigator.pointerEnabled,
1970
-
1971
- SUPPORTS_POINTER = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
1972
-
1973
- PLUGIN_NS = 'TouchSwipe';
1974
-
1975
-
1976
-
1977
- /**
1978
- * The default configuration, and available options to configure touch swipe with.
1979
- * You can set the default values by updating any of the properties prior to instantiation.
1980
- * @name $.fn.swipe.defaults
1981
- * @namespace
1982
- * @property {int} [fingers=1] The number of fingers to detect in a swipe. Any swipes that do not meet this requirement will NOT trigger swipe handlers.
1983
- * @property {int} [threshold=75] The number of pixels that the user must move their finger by before it is considered a swipe.
1984
- * @property {int} [cancelThreshold=null] The number of pixels that the user must move their finger back from the original swipe direction to cancel the gesture.
1985
- * @property {int} [pinchThreshold=20] The number of pixels that the user must pinch their finger by before it is considered a pinch.
1986
- * @property {int} [maxTimeThreshold=null] Time, in milliseconds, between touchStart and touchEnd must NOT exceed in order to be considered a swipe.
1987
- * @property {int} [fingerReleaseThreshold=250] Time in milliseconds between releasing multiple fingers. If 2 fingers are down, and are released one after the other, if they are within this threshold, it counts as a simultaneous release.
1988
- * @property {int} [longTapThreshold=500] Time in milliseconds between tap and release for a long tap
1989
- * @property {int} [doubleTapThreshold=200] Time in milliseconds between 2 taps to count as a double tap
1990
- * @property {function} [swipe=null] A handler to catch all swipes. See {@link $.fn.swipe#event:swipe}
1991
- * @property {function} [swipeLeft=null] A handler that is triggered for "left" swipes. See {@link $.fn.swipe#event:swipeLeft}
1992
- * @property {function} [swipeRight=null] A handler that is triggered for "right" swipes. See {@link $.fn.swipe#event:swipeRight}
1993
- * @property {function} [swipeUp=null] A handler that is triggered for "up" swipes. See {@link $.fn.swipe#event:swipeUp}
1994
- * @property {function} [swipeDown=null] A handler that is triggered for "down" swipes. See {@link $.fn.swipe#event:swipeDown}
1995
- * @property {function} [swipeStatus=null] A handler triggered for every phase of the swipe. See {@link $.fn.swipe#event:swipeStatus}
1996
- * @property {function} [pinchIn=null] A handler triggered for pinch in events. See {@link $.fn.swipe#event:pinchIn}
1997
- * @property {function} [pinchOut=null] A handler triggered for pinch out events. See {@link $.fn.swipe#event:pinchOut}
1998
- * @property {function} [pinchStatus=null] A handler triggered for every phase of a pinch. See {@link $.fn.swipe#event:pinchStatus}
1999
- * @property {function} [tap=null] A handler triggered when a user just taps on the item, rather than swipes it. If they do not move, tap is triggered, if they do move, it is not.
2000
- * @property {function} [doubleTap=null] A handler triggered when a user double taps on the item. The delay between taps can be set with the doubleTapThreshold property. See {@link $.fn.swipe.defaults#doubleTapThreshold}
2001
- * @property {function} [longTap=null] A handler triggered when a user long taps on the item. The delay between start and end can be set with the longTapThreshold property. See {@link $.fn.swipe.defaults#longTapThreshold}
2002
- * @property (function) [hold=null] A handler triggered when a user reaches longTapThreshold on the item. See {@link $.fn.swipe.defaults#longTapThreshold}
2003
- * @property {boolean} [triggerOnTouchEnd=true] If true, the swipe events are triggered when the touch end event is received (user releases finger). If false, it will be triggered on reaching the threshold, and then cancel the touch event automatically.
2004
- * @property {boolean} [triggerOnTouchLeave=false] If true, then when the user leaves the swipe object, the swipe will end and trigger appropriate handlers.
2005
- * @property {string|undefined} [allowPageScroll='auto'] How the browser handles page scrolls when the user is swiping on a touchSwipe object. See {@link $.fn.swipe.pageScroll}. <br/><br/>
2006
- <code>"auto"</code> : all undefined swipes will cause the page to scroll in that direction. <br/>
2007
- <code>"none"</code> : the page will not scroll when user swipes. <br/>
2008
- <code>"horizontal"</code> : will force page to scroll on horizontal swipes. <br/>
2009
- <code>"vertical"</code> : will force page to scroll on vertical swipes. <br/>
2010
- * @property {boolean} [fallbackToMouseEvents=true] If true mouse events are used when run on a non touch device, false will stop swipes being triggered by mouse events on non tocuh devices.
2011
- * @property {string} [excludedElements="button, input, select, textarea, a, .noSwipe"] A jquery selector that specifies child elements that do NOT trigger swipes. By default this excludes all form, input, select, button, anchor and .noSwipe elements.
2012
-
2013
- */
2014
- var defaults = {
2015
- fingers: 1,
2016
- threshold: 75,
2017
- cancelThreshold:null,
2018
- pinchThreshold:20,
2019
- maxTimeThreshold: null,
2020
- fingerReleaseThreshold:250,
2021
- longTapThreshold:500,
2022
- doubleTapThreshold:200,
2023
- swipe: null,
2024
- swipeLeft: null,
2025
- swipeRight: null,
2026
- swipeUp: null,
2027
- swipeDown: null,
2028
- swipeStatus: null,
2029
- pinchIn:null,
2030
- pinchOut:null,
2031
- pinchStatus:null,
2032
- click:null, //Deprecated since 1.6.2
2033
- tap:null,
2034
- doubleTap:null,
2035
- longTap:null,
2036
- hold:null,
2037
- triggerOnTouchEnd: true,
2038
- triggerOnTouchLeave:false,
2039
- allowPageScroll: "auto",
2040
- fallbackToMouseEvents: true,
2041
- excludedElements:"label, button, input, select, textarea, a, .noSwipe"
2042
- };
2043
-
2044
-
2045
-
2046
- /**
2047
- * Applies TouchSwipe behaviour to one or more jQuery objects.
2048
- * The TouchSwipe plugin can be instantiated via this method, or methods within
2049
- * TouchSwipe can be executed via this method as per jQuery plugin architecture.
2050
- * @see TouchSwipe
2051
- * @class
2052
- * @param {Mixed} method If the current DOMNode is a TouchSwipe object, and <code>method</code> is a TouchSwipe method, then
2053
- * the <code>method</code> is executed, and any following arguments are passed to the TouchSwipe method.
2054
- * If <code>method</code> is an object, then the TouchSwipe class is instantiated on the current DOMNode, passing the
2055
- * configuration properties defined in the object. See TouchSwipe
2056
- *
2057
- */
2058
- $.fn.swipe = function (method) {
2059
- var $this = $(this),
2060
- plugin = $this.data(PLUGIN_NS);
2061
-
2062
- //Check if we are already instantiated and trying to execute a method
2063
- if (plugin && typeof method === 'string') {
2064
- if (plugin[method]) {
2065
- return plugin[method].apply(this, Array.prototype.slice.call(arguments, 1));
2066
- } else {
2067
- $.error('Method ' + method + ' does not exist on jQuery.swipe');
2068
- }
2069
- }
2070
- //Else not instantiated and trying to pass init object (or nothing)
2071
- else if (!plugin && (typeof method === 'object' || !method)) {
2072
- return init.apply(this, arguments);
2073
- }
2074
-
2075
- return $this;
2076
- };
2077
-
2078
- //Expose our defaults so a user could override the plugin defaults
2079
- $.fn.swipe.defaults = defaults;
2080
-
2081
- /**
2082
- * The phases that a touch event goes through. The <code>phase</code> is passed to the event handlers.
2083
- * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
2084
- * @namespace
2085
- * @readonly
2086
- * @property {string} PHASE_START Constant indicating the start phase of the touch event. Value is <code>"start"</code>.
2087
- * @property {string} PHASE_MOVE Constant indicating the move phase of the touch event. Value is <code>"move"</code>.
2088
- * @property {string} PHASE_END Constant indicating the end phase of the touch event. Value is <code>"end"</code>.
2089
- * @property {string} PHASE_CANCEL Constant indicating the cancel phase of the touch event. Value is <code>"cancel"</code>.
2090
- */
2091
- $.fn.swipe.phases = {
2092
- PHASE_START: PHASE_START,
2093
- PHASE_MOVE: PHASE_MOVE,
2094
- PHASE_END: PHASE_END,
2095
- PHASE_CANCEL: PHASE_CANCEL
2096
- };
2097
-
2098
- /**
2099
- * The direction constants that are passed to the event handlers.
2100
- * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
2101
- * @namespace
2102
- * @readonly
2103
- * @property {string} LEFT Constant indicating the left direction. Value is <code>"left"</code>.
2104
- * @property {string} RIGHT Constant indicating the right direction. Value is <code>"right"</code>.
2105
- * @property {string} UP Constant indicating the up direction. Value is <code>"up"</code>.
2106
- * @property {string} DOWN Constant indicating the down direction. Value is <code>"cancel"</code>.
2107
- * @property {string} IN Constant indicating the in direction. Value is <code>"in"</code>.
2108
- * @property {string} OUT Constant indicating the out direction. Value is <code>"out"</code>.
2109
- */
2110
- $.fn.swipe.directions = {
2111
- LEFT: LEFT,
2112
- RIGHT: RIGHT,
2113
- UP: UP,
2114
- DOWN: DOWN,
2115
- IN : IN,
2116
- OUT: OUT
2117
- };
2118
-
2119
- /**
2120
- * The page scroll constants that can be used to set the value of <code>allowPageScroll</code> option
2121
- * These properties are read only
2122
- * @namespace
2123
- * @readonly
2124
- * @see $.fn.swipe.defaults#allowPageScroll
2125
- * @property {string} NONE Constant indicating no page scrolling is allowed. Value is <code>"none"</code>.
2126
- * @property {string} HORIZONTAL Constant indicating horizontal page scrolling is allowed. Value is <code>"horizontal"</code>.
2127
- * @property {string} VERTICAL Constant indicating vertical page scrolling is allowed. Value is <code>"vertical"</code>.
2128
- * @property {string} AUTO Constant indicating either horizontal or vertical will be allowed, depending on the swipe handlers registered. Value is <code>"auto"</code>.
2129
- */
2130
- $.fn.swipe.pageScroll = {
2131
- NONE: NONE,
2132
- HORIZONTAL: HORIZONTAL,
2133
- VERTICAL: VERTICAL,
2134
- AUTO: AUTO
2135
- };
2136
-
2137
- /**
2138
- * Constants representing the number of fingers used in a swipe. These are used to set both the value of <code>fingers</code> in the
2139
- * options object, as well as the value of the <code>fingers</code> event property.
2140
- * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
2141
- * @namespace
2142
- * @readonly
2143
- * @see $.fn.swipe.defaults#fingers
2144
- * @property {string} ONE Constant indicating 1 finger is to be detected / was detected. Value is <code>1</code>.
2145
- * @property {string} TWO Constant indicating 2 fingers are to be detected / were detected. Value is <code>1</code>.
2146
- * @property {string} THREE Constant indicating 3 finger are to be detected / were detected. Value is <code>1</code>.
2147
- * @property {string} ALL Constant indicating any combination of finger are to be detected. Value is <code>"all"</code>.
2148
- */
2149
- $.fn.swipe.fingers = {
2150
- ONE: 1,
2151
- TWO: 2,
2152
- THREE: 3,
2153
- ALL: ALL_FINGERS
2154
- };
2155
-
2156
- /**
2157
- * Initialise the plugin for each DOM element matched
2158
- * This creates a new instance of the main TouchSwipe class for each DOM element, and then
2159
- * saves a reference to that instance in the elements data property.
2160
- * @internal
2161
- */
2162
- function init(options) {
2163
- //Prep and extend the options
2164
- if (options && (options.allowPageScroll === undefined && (options.swipe !== undefined || options.swipeStatus !== undefined))) {
2165
- options.allowPageScroll = NONE;
2166
- }
2167
-
2168
- //Check for deprecated options
2169
- //Ensure that any old click handlers are assigned to the new tap, unless we have a tap
2170
- if(options.click!==undefined && options.tap===undefined) {
2171
- options.tap = options.click;
2172
- }
2173
-
2174
- if (!options) {
2175
- options = {};
2176
- }
2177
-
2178
- //pass empty object so we dont modify the defaults
2179
- options = $.extend({}, $.fn.swipe.defaults, options);
2180
-
2181
- //For each element instantiate the plugin
2182
- return this.each(function () {
2183
- var $this = $(this);
2184
-
2185
- //Check we havent already initialised the plugin
2186
- var plugin = $this.data(PLUGIN_NS);
2187
-
2188
- if (!plugin) {
2189
- plugin = new TouchSwipe(this, options);
2190
- $this.data(PLUGIN_NS, plugin);
2191
- }
2192
- });
2193
- }
2194
-
2195
- /**
2196
- * Main TouchSwipe Plugin Class.
2197
- * Do not use this to construct your TouchSwipe object, use the jQuery plugin method $.fn.swipe(); {@link $.fn.swipe}
2198
- * @private
2199
- * @name TouchSwipe
2200
- * @param {DOMNode} element The HTML DOM object to apply to plugin to
2201
- * @param {Object} options The options to configure the plugin with. @link {$.fn.swipe.defaults}
2202
- * @see $.fh.swipe.defaults
2203
- * @see $.fh.swipe
2204
- * @class
2205
- */
2206
- function TouchSwipe(element, options) {
2207
- var useTouchEvents = (SUPPORTS_TOUCH || SUPPORTS_POINTER || !options.fallbackToMouseEvents),
2208
- START_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerDown' : 'pointerdown') : 'touchstart') : 'mousedown',
2209
- MOVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerMove' : 'pointermove') : 'touchmove') : 'mousemove',
2210
- END_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerUp' : 'pointerup') : 'touchend') : 'mouseup',
2211
- LEAVE_EV = useTouchEvents ? null : 'mouseleave', //we manually detect leave on touch devices, so null event here
2212
- CANCEL_EV = (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerCancel' : 'pointercancel') : 'touchcancel');
2213
-
2214
-
2215
-
2216
- //touch properties
2217
- var distance = 0,
2218
- direction = null,
2219
- duration = 0,
2220
- startTouchesDistance = 0,
2221
- endTouchesDistance = 0,
2222
- pinchZoom = 1,
2223
- pinchDistance = 0,
2224
- pinchDirection = 0,
2225
- maximumsMap=null;
2226
-
2227
-
2228
-
2229
- //jQuery wrapped element for this instance
2230
- var $element = $(element);
2231
-
2232
- //Current phase of th touch cycle
2233
- var phase = "start";
2234
-
2235
- // the current number of fingers being used.
2236
- var fingerCount = 0;
2237
-
2238
- //track mouse points / delta
2239
- var fingerData=null;
2240
-
2241
- //track times
2242
- var startTime = 0,
2243
- endTime = 0,
2244
- previousTouchEndTime=0,
2245
- previousTouchFingerCount=0,
2246
- doubleTapStartTime=0;
2247
-
2248
- //Timeouts
2249
- var singleTapTimeout=null,
2250
- holdTimeout=null;
2251
-
2252
- // Add gestures to all swipable areas if supported
2253
- try {
2254
- $element.bind(START_EV, touchStart);
2255
- $element.bind(CANCEL_EV, touchCancel);
2256
- }
2257
- catch (e) {
2258
- $.error('events not supported ' + START_EV + ',' + CANCEL_EV + ' on jQuery.swipe');
2259
- }
2260
-
2261
- //
2262
- //Public methods
2263
- //
2264
-
2265
- /**
2266
- * re-enables the swipe plugin with the previous configuration
2267
- * @function
2268
- * @name $.fn.swipe#enable
2269
- * @return {DOMNode} The Dom element that was registered with TouchSwipe
2270
- * @example $("#element").swipe("enable");
2271
- */
2272
- this.enable = function () {
2273
- $element.bind(START_EV, touchStart);
2274
- $element.bind(CANCEL_EV, touchCancel);
2275
- return $element;
2276
- };
2277
-
2278
- /**
2279
- * disables the swipe plugin
2280
- * @function
2281
- * @name $.fn.swipe#disable
2282
- * @return {DOMNode} The Dom element that is now registered with TouchSwipe
2283
- * @example $("#element").swipe("disable");
2284
- */
2285
- this.disable = function () {
2286
- removeListeners();
2287
- return $element;
2288
- };
2289
-
2290
- /**
2291
- * Destroy the swipe plugin completely. To use any swipe methods, you must re initialise the plugin.
2292
- * @function
2293
- * @name $.fn.swipe#destroy
2294
- * @example $("#element").swipe("destroy");
2295
- */
2296
- this.destroy = function () {
2297
- removeListeners();
2298
- $element.data(PLUGIN_NS, null);
2299
- $element = null;
2300
- };
2301
-
2302
-
2303
- /**
2304
- * Allows run time updating of the swipe configuration options.
2305
- * @function
2306
- * @name $.fn.swipe#option
2307
- * @param {String} property The option property to get or set
2308
- * @param {Object} [value] The value to set the property to
2309
- * @return {Object} If only a property name is passed, then that property value is returned.
2310
- * @example $("#element").swipe("option", "threshold"); // return the threshold
2311
- * @example $("#element").swipe("option", "threshold", 100); // set the threshold after init
2312
- * @see $.fn.swipe.defaults
2313
- *
2314
- */
2315
- this.option = function (property, value) {
2316
- if(options[property]!==undefined) {
2317
- if(value===undefined) {
2318
- return options[property];
2319
- } else {
2320
- options[property] = value;
2321
- }
2322
- } else {
2323
- $.error('Option ' + property + ' does not exist on jQuery.swipe.options');
2324
- }
2325
-
2326
- return null;
2327
- }
2328
-
2329
- //
2330
- // Private methods
2331
- //
2332
-
2333
- //
2334
- // EVENTS
2335
- //
2336
- /**
2337
- * Event handler for a touch start event.
2338
- * Stops the default click event from triggering and stores where we touched
2339
- * @inner
2340
- * @param {object} jqEvent The normalised jQuery event object.
2341
- */
2342
- function touchStart(jqEvent) {
2343
- //If we already in a touch event (a finger already in use) then ignore subsequent ones..
2344
- if( getTouchInProgress() )
2345
- return;
2346
-
2347
- //Check if this element matches any in the excluded elements selectors, or its parent is excluded, if so, DON'T swipe
2348
- if( $(jqEvent.target).closest( options.excludedElements, $element ).length>0 )
2349
- return;
2350
-
2351
- //As we use Jquery bind for events, we need to target the original event object
2352
- //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
2353
- var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
2354
-
2355
- var ret,
2356
- evt = SUPPORTS_TOUCH ? event.touches[0] : event;
2357
-
2358
- phase = PHASE_START;
2359
-
2360
- //If we support touches, get the finger count
2361
- if (SUPPORTS_TOUCH) {
2362
- // get the total number of fingers touching the screen
2363
- fingerCount = event.touches.length;
2364
- }
2365
- //Else this is the desktop, so stop the browser from dragging the image
2366
- else {
2367
- jqEvent.preventDefault(); //call this on jq event so we are cross browser
2368
- }
2369
-
2370
- //clear vars..
2371
- distance = 0;
2372
- direction = null;
2373
- pinchDirection=null;
2374
- duration = 0;
2375
- startTouchesDistance=0;
2376
- endTouchesDistance=0;
2377
- pinchZoom = 1;
2378
- pinchDistance = 0;
2379
- fingerData=createAllFingerData();
2380
- maximumsMap=createMaximumsData();
2381
- cancelMultiFingerRelease();
2382
-
2383
-
2384
- // check the number of fingers is what we are looking for, or we are capturing pinches
2385
- if (!SUPPORTS_TOUCH || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
2386
- // get the coordinates of the touch
2387
- createFingerData( 0, evt );
2388
- startTime = getTimeStamp();
2389
-
2390
- if(fingerCount==2) {
2391
- //Keep track of the initial pinch distance, so we can calculate the diff later
2392
- //Store second finger data as start
2393
- createFingerData( 1, event.touches[1] );
2394
- startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
2395
- }
2396
-
2397
- if (options.swipeStatus || options.pinchStatus) {
2398
- ret = triggerHandler(event, phase);
2399
- }
2400
- }
2401
- else {
2402
- //A touch with more or less than the fingers we are looking for, so cancel
2403
- ret = false;
2404
- }
2405
-
2406
- //If we have a return value from the users handler, then return and cancel
2407
- if (ret === false) {
2408
- phase = PHASE_CANCEL;
2409
- triggerHandler(event, phase);
2410
- return ret;
2411
- }
2412
- else {
2413
- if (options.hold) {
2414
- holdTimeout = setTimeout($.proxy(function() {
2415
- //Trigger the event
2416
- $element.trigger('hold', [event.target]);
2417
- //Fire the callback
2418
- if(options.hold) {
2419
- ret = options.hold.call($element, event, event.target);
2420
- }
2421
- }, this), options.longTapThreshold );
2422
- }
2423
-
2424
- setTouchInProgress(true);
2425
- }
2426
-
2427
- return null;
2428
- };
2429
-
2430
-
2431
-
2432
- /**
2433
- * Event handler for a touch move event.
2434
- * If we change fingers during move, then cancel the event
2435
- * @inner
2436
- * @param {object} jqEvent The normalised jQuery event object.
2437
- */
2438
- function touchMove(jqEvent) {
2439
-
2440
- //As we use Jquery bind for events, we need to target the original event object
2441
- //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
2442
- var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
2443
-
2444
- //If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
2445
- if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
2446
- return;
2447
-
2448
- var ret,
2449
- evt = SUPPORTS_TOUCH ? event.touches[0] : event;
2450
-
2451
-
2452
- //Update the finger data
2453
- var currentFinger = updateFingerData(evt);
2454
- endTime = getTimeStamp();
2455
-
2456
- if (SUPPORTS_TOUCH) {
2457
- fingerCount = event.touches.length;
2458
- }
2459
-
2460
- if (options.hold)
2461
- clearTimeout(holdTimeout);
2462
-
2463
- phase = PHASE_MOVE;
2464
-
2465
- //If we have 2 fingers get Touches distance as well
2466
- if(fingerCount==2) {
2467
-
2468
- //Keep track of the initial pinch distance, so we can calculate the diff later
2469
- //We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
2470
- if(startTouchesDistance==0) {
2471
- //Create second finger if this is the first time...
2472
- createFingerData( 1, event.touches[1] );
2473
-
2474
- startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
2475
- } else {
2476
- //Else just update the second finger
2477
- updateFingerData(event.touches[1]);
2478
-
2479
- endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
2480
- pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
2481
- }
2482
-
2483
-
2484
- pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
2485
- pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
2486
- }
2487
-
2488
-
2489
- if ( (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH || hasPinches() ) {
2490
-
2491
- direction = calculateDirection(currentFinger.start, currentFinger.end);
2492
-
2493
- //Check if we need to prevent default event (page scroll / pinch zoom) or not
2494
- validateDefaultEvent(jqEvent, direction);
2495
-
2496
- //Distance and duration are all off the main finger
2497
- distance = calculateDistance(currentFinger.start, currentFinger.end);
2498
- duration = calculateDuration();
2499
-
2500
- //Cache the maximum distance we made in this direction
2501
- setMaxDistance(direction, distance);
2502
-
2503
-
2504
- if (options.swipeStatus || options.pinchStatus) {
2505
- ret = triggerHandler(event, phase);
2506
- }
2507
-
2508
-
2509
- //If we trigger end events when threshold are met, or trigger events when touch leaves element
2510
- if(!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
2511
-
2512
- var inBounds = true;
2513
-
2514
- //If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
2515
- if(options.triggerOnTouchLeave) {
2516
- var bounds = getbounds( this );
2517
- inBounds = isInBounds( currentFinger.end, bounds );
2518
- }
2519
-
2520
- //Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
2521
- if(!options.triggerOnTouchEnd && inBounds) {
2522
- phase = getNextPhase( PHASE_MOVE );
2523
- }
2524
- //We end if out of bounds here, so set current phase to END, and check if its modified
2525
- else if(options.triggerOnTouchLeave && !inBounds ) {
2526
- phase = getNextPhase( PHASE_END );
2527
- }
2528
-
2529
- if(phase==PHASE_CANCEL || phase==PHASE_END) {
2530
- triggerHandler(event, phase);
2531
- }
2532
- }
2533
- }
2534
- else {
2535
- phase = PHASE_CANCEL;
2536
- triggerHandler(event, phase);
2537
- }
2538
-
2539
- if (ret === false) {
2540
- phase = PHASE_CANCEL;
2541
- triggerHandler(event, phase);
2542
- }
2543
- }
2544
-
2545
-
2546
-
2547
- /**
2548
- * Event handler for a touch end event.
2549
- * Calculate the direction and trigger events
2550
- * @inner
2551
- * @param {object} jqEvent The normalised jQuery event object.
2552
- */
2553
- function touchEnd(jqEvent) {
2554
- //As we use Jquery bind for events, we need to target the original event object
2555
- var event = jqEvent.originalEvent;
2556
-
2557
-
2558
- //If we are still in a touch with another finger return
2559
- //This allows us to wait a fraction and see if the other finger comes up, if it does within the threshold, then we treat it as a multi release, not a single release.
2560
- if (SUPPORTS_TOUCH) {
2561
- if(event.touches.length>0) {
2562
- startMultiFingerRelease();
2563
- return true;
2564
- }
2565
- }
2566
-
2567
- //If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
2568
- //This is used to allow 2 fingers to release fractionally after each other, whilst maintainig the event as containg 2 fingers, not 1
2569
- if(inMultiFingerRelease()) {
2570
- fingerCount=previousTouchFingerCount;
2571
- }
2572
-
2573
- //Set end of swipe
2574
- endTime = getTimeStamp();
2575
-
2576
- //Get duration incase move was never fired
2577
- duration = calculateDuration();
2578
-
2579
- //If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
2580
- if(didSwipeBackToCancel() || !validateSwipeDistance()) {
2581
- phase = PHASE_CANCEL;
2582
- triggerHandler(event, phase);
2583
- } else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd == false && phase === PHASE_MOVE)) {
2584
- //call this on jq event so we are cross browser
2585
- jqEvent.preventDefault();
2586
- phase = PHASE_END;
2587
- triggerHandler(event, phase);
2588
- }
2589
- //Special cases - A tap should always fire on touch end regardless,
2590
- //So here we manually trigger the tap end handler by itself
2591
- //We dont run trigger handler as it will re-trigger events that may have fired already
2592
- else if (!options.triggerOnTouchEnd && hasTap()) {
2593
- //Trigger the pinch events...
2594
- phase = PHASE_END;
2595
- triggerHandlerForGesture(event, phase, TAP);
2596
- }
2597
- else if (phase === PHASE_MOVE) {
2598
- phase = PHASE_CANCEL;
2599
- triggerHandler(event, phase);
2600
- }
2601
-
2602
- setTouchInProgress(false);
2603
-
2604
- return null;
2605
- }
2606
-
2607
-
2608
-
2609
- /**
2610
- * Event handler for a touch cancel event.
2611
- * Clears current vars
2612
- * @inner
2613
- */
2614
- function touchCancel() {
2615
- // reset the variables back to default values
2616
- fingerCount = 0;
2617
- endTime = 0;
2618
- startTime = 0;
2619
- startTouchesDistance=0;
2620
- endTouchesDistance=0;
2621
- pinchZoom=1;
2622
-
2623
- //If we were in progress of tracking a possible multi touch end, then re set it.
2624
- cancelMultiFingerRelease();
2625
-
2626
- setTouchInProgress(false);
2627
- }
2628
-
2629
-
2630
- /**
2631
- * Event handler for a touch leave event.
2632
- * This is only triggered on desktops, in touch we work this out manually
2633
- * as the touchleave event is not supported in webkit
2634
- * @inner
2635
- */
2636
- function touchLeave(jqEvent) {
2637
- var event = jqEvent.originalEvent;
2638
-
2639
- //If we have the trigger on leave property set....
2640
- if(options.triggerOnTouchLeave) {
2641
- phase = getNextPhase( PHASE_END );
2642
- triggerHandler(event, phase);
2643
- }
2644
- }
2645
-
2646
- /**
2647
- * Removes all listeners that were associated with the plugin
2648
- * @inner
2649
- */
2650
- function removeListeners() {
2651
- $element.unbind(START_EV, touchStart);
2652
- $element.unbind(CANCEL_EV, touchCancel);
2653
- $element.unbind(MOVE_EV, touchMove);
2654
- $element.unbind(END_EV, touchEnd);
2655
-
2656
- //we only have leave events on desktop, we manually calculate leave on touch as its not supported in webkit
2657
- if(LEAVE_EV) {
2658
- $element.unbind(LEAVE_EV, touchLeave);
2659
- }
2660
-
2661
- setTouchInProgress(false);
2662
- }
2663
-
2664
-
2665
- /**
2666
- * Checks if the time and distance thresholds have been met, and if so then the appropriate handlers are fired.
2667
- */
2668
- function getNextPhase(currentPhase) {
2669
-
2670
- var nextPhase = currentPhase;
2671
-
2672
- // Ensure we have valid swipe (under time and over distance and check if we are out of bound...)
2673
- var validTime = validateSwipeTime();
2674
- var validDistance = validateSwipeDistance();
2675
- var didCancel = didSwipeBackToCancel();
2676
-
2677
- //If we have exceeded our time, then cancel
2678
- if(!validTime || didCancel) {
2679
- nextPhase = PHASE_CANCEL;
2680
- }
2681
- //Else if we are moving, and have reached distance then end
2682
- else if (validDistance && currentPhase == PHASE_MOVE && (!options.triggerOnTouchEnd || options.triggerOnTouchLeave) ) {
2683
- nextPhase = PHASE_END;
2684
- }
2685
- //Else if we have ended by leaving and didn't reach distance, then cancel
2686
- else if (!validDistance && currentPhase==PHASE_END && options.triggerOnTouchLeave) {
2687
- nextPhase = PHASE_CANCEL;
2688
- }
2689
-
2690
- return nextPhase;
2691
- }
2692
-
2693
-
2694
- /**
2695
- * Trigger the relevant event handler
2696
- * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
2697
- * @param {object} event the original event object
2698
- * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
2699
- * @inner
2700
- */
2701
- function triggerHandler(event, phase) {
2702
-
2703
- var ret = undefined;
2704
-
2705
- // SWIPE GESTURES
2706
- if(didSwipe() || hasSwipes()) { //hasSwipes as status needs to fire even if swipe is invalid
2707
- //Trigger the swipe events...
2708
- ret = triggerHandlerForGesture(event, phase, SWIPE);
2709
- }
2710
-
2711
- // PINCH GESTURES (if the above didn't cancel)
2712
- else if((didPinch() || hasPinches()) && ret!==false) {
2713
- //Trigger the pinch events...
2714
- ret = triggerHandlerForGesture(event, phase, PINCH);
2715
- }
2716
-
2717
- // CLICK / TAP (if the above didn't cancel)
2718
- if(didDoubleTap() && ret!==false) {
2719
- //Trigger the tap events...
2720
- ret = triggerHandlerForGesture(event, phase, DOUBLE_TAP);
2721
- }
2722
-
2723
- // CLICK / TAP (if the above didn't cancel)
2724
- else if(didLongTap() && ret!==false) {
2725
- //Trigger the tap events...
2726
- ret = triggerHandlerForGesture(event, phase, LONG_TAP);
2727
- }
2728
-
2729
- // CLICK / TAP (if the above didn't cancel)
2730
- else if(didTap() && ret!==false) {
2731
- //Trigger the tap event..
2732
- ret = triggerHandlerForGesture(event, phase, TAP);
2733
- }
2734
-
2735
-
2736
-
2737
- // If we are cancelling the gesture, then manually trigger the reset handler
2738
- if (phase === PHASE_CANCEL) {
2739
- touchCancel(event);
2740
- }
2741
-
2742
- // If we are ending the gesture, then manually trigger the reset handler IF all fingers are off
2743
- if(phase === PHASE_END) {
2744
- //If we support touch, then check that all fingers are off before we cancel
2745
- if (SUPPORTS_TOUCH) {
2746
- if(event.touches.length==0) {
2747
- touchCancel(event);
2748
- }
2749
- }
2750
- else {
2751
- touchCancel(event);
2752
- }
2753
- }
2754
-
2755
- return ret;
2756
- }
2757
-
2758
-
2759
-
2760
- /**
2761
- * Trigger the relevant event handler
2762
- * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
2763
- * @param {object} event the original event object
2764
- * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
2765
- * @param {string} gesture the gesture to trigger a handler for : PINCH or SWIPE {@link $.fn.swipe.gestures}
2766
- * @return Boolean False, to indicate that the event should stop propagation, or void.
2767
- * @inner
2768
- */
2769
- function triggerHandlerForGesture(event, phase, gesture) {
2770
-
2771
- var ret=undefined;
2772
-
2773
- //SWIPES....
2774
- if(gesture==SWIPE) {
2775
- //Trigger status every time..
2776
-
2777
- //Trigger the event...
2778
- $element.trigger('swipeStatus', [phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData]);
2779
-
2780
- //Fire the callback
2781
- if (options.swipeStatus) {
2782
- ret = options.swipeStatus.call($element, event, phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData);
2783
- //If the status cancels, then dont run the subsequent event handlers..
2784
- if(ret===false) return false;
2785
- }
2786
-
2787
-
2788
-
2789
-
2790
- if (phase == PHASE_END && validateSwipe()) {
2791
- //Fire the catch all event
2792
- $element.trigger('swipe', [direction, distance, duration, fingerCount, fingerData]);
2793
-
2794
- //Fire catch all callback
2795
- if (options.swipe) {
2796
- ret = options.swipe.call($element, event, direction, distance, duration, fingerCount, fingerData);
2797
- //If the status cancels, then dont run the subsequent event handlers..
2798
- if(ret===false) return false;
2799
- }
2800
-
2801
- //trigger direction specific event handlers
2802
- switch (direction) {
2803
- case LEFT:
2804
- //Trigger the event
2805
- $element.trigger('swipeLeft', [direction, distance, duration, fingerCount, fingerData]);
2806
-
2807
- //Fire the callback
2808
- if (options.swipeLeft) {
2809
- ret = options.swipeLeft.call($element, event, direction, distance, duration, fingerCount, fingerData);
2810
- }
2811
- break;
2812
-
2813
- case RIGHT:
2814
- //Trigger the event
2815
- $element.trigger('swipeRight', [direction, distance, duration, fingerCount, fingerData]);
2816
-
2817
- //Fire the callback
2818
- if (options.swipeRight) {
2819
- ret = options.swipeRight.call($element, event, direction, distance, duration, fingerCount, fingerData);
2820
- }
2821
- break;
2822
-
2823
- case UP:
2824
- //Trigger the event
2825
- $element.trigger('swipeUp', [direction, distance, duration, fingerCount, fingerData]);
2826
-
2827
- //Fire the callback
2828
- if (options.swipeUp) {
2829
- ret = options.swipeUp.call($element, event, direction, distance, duration, fingerCount, fingerData);
2830
- }
2831
- break;
2832
-
2833
- case DOWN:
2834
- //Trigger the event
2835
- $element.trigger('swipeDown', [direction, distance, duration, fingerCount, fingerData]);
2836
-
2837
- //Fire the callback
2838
- if (options.swipeDown) {
2839
- ret = options.swipeDown.call($element, event, direction, distance, duration, fingerCount, fingerData);
2840
- }
2841
- break;
2842
- }
2843
- }
2844
- }
2845
-
2846
-
2847
- //PINCHES....
2848
- if(gesture==PINCH) {
2849
- //Trigger the event
2850
- $element.trigger('pinchStatus', [phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
2851
-
2852
- //Fire the callback
2853
- if (options.pinchStatus) {
2854
- ret = options.pinchStatus.call($element, event, phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
2855
- //If the status cancels, then dont run the subsequent event handlers..
2856
- if(ret===false) return false;
2857
- }
2858
-
2859
- if(phase==PHASE_END && validatePinch()) {
2860
-
2861
- switch (pinchDirection) {
2862
- case IN:
2863
- //Trigger the event
2864
- $element.trigger('pinchIn', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
2865
-
2866
- //Fire the callback
2867
- if (options.pinchIn) {
2868
- ret = options.pinchIn.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
2869
- }
2870
- break;
2871
-
2872
- case OUT:
2873
- //Trigger the event
2874
- $element.trigger('pinchOut', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
2875
-
2876
- //Fire the callback
2877
- if (options.pinchOut) {
2878
- ret = options.pinchOut.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
2879
- }
2880
- break;
2881
- }
2882
- }
2883
- }
2884
-
2885
-
2886
-
2887
-
2888
-
2889
- if(gesture==TAP) {
2890
- if(phase === PHASE_CANCEL || phase === PHASE_END) {
2891
-
2892
-
2893
- //Cancel any existing double tap
2894
- clearTimeout(singleTapTimeout);
2895
- //Cancel hold timeout
2896
- clearTimeout(holdTimeout);
2897
-
2898
- //If we are also looking for doubelTaps, wait incase this is one...
2899
- if(hasDoubleTap() && !inDoubleTap()) {
2900
- //Cache the time of this tap
2901
- doubleTapStartTime = getTimeStamp();
2902
-
2903
- //Now wait for the double tap timeout, and trigger this single tap
2904
- //if its not cancelled by a double tap
2905
- singleTapTimeout = setTimeout($.proxy(function() {
2906
- doubleTapStartTime=null;
2907
- //Trigger the event
2908
- $element.trigger('tap', [event.target]);
2909
-
2910
-
2911
- //Fire the callback
2912
- if(options.tap) {
2913
- ret = options.tap.call($element, event, event.target);
2914
- }
2915
- }, this), options.doubleTapThreshold );
2916
-
2917
- } else {
2918
- doubleTapStartTime=null;
2919
-
2920
- //Trigger the event
2921
- $element.trigger('tap', [event.target]);
2922
-
2923
-
2924
- //Fire the callback
2925
- if(options.tap) {
2926
- ret = options.tap.call($element, event, event.target);
2927
- }
2928
- }
2929
- }
2930
- }
2931
-
2932
- else if (gesture==DOUBLE_TAP) {
2933
- if(phase === PHASE_CANCEL || phase === PHASE_END) {
2934
- //Cancel any pending singletap
2935
- clearTimeout(singleTapTimeout);
2936
- doubleTapStartTime=null;
2937
-
2938
- //Trigger the event
2939
- $element.trigger('doubletap', [event.target]);
2940
-
2941
- //Fire the callback
2942
- if(options.doubleTap) {
2943
- ret = options.doubleTap.call($element, event, event.target);
2944
- }
2945
- }
2946
- }
2947
-
2948
- else if (gesture==LONG_TAP) {
2949
- if(phase === PHASE_CANCEL || phase === PHASE_END) {
2950
- //Cancel any pending singletap (shouldnt be one)
2951
- clearTimeout(singleTapTimeout);
2952
- doubleTapStartTime=null;
2953
-
2954
- //Trigger the event
2955
- $element.trigger('longtap', [event.target]);
2956
-
2957
- //Fire the callback
2958
- if(options.longTap) {
2959
- ret = options.longTap.call($element, event, event.target);
2960
- }
2961
- }
2962
- }
2963
-
2964
- return ret;
2965
- }
2966
-
2967
-
2968
-
2969
-
2970
- //
2971
- // GESTURE VALIDATION
2972
- //
2973
-
2974
- /**
2975
- * Checks the user has swipe far enough
2976
- * @return Boolean if <code>threshold</code> has been set, return true if the threshold was met, else false.
2977
- * If no threshold was set, then we return true.
2978
- * @inner
2979
- */
2980
- function validateSwipeDistance() {
2981
- var valid = true;
2982
- //If we made it past the min swipe distance..
2983
- if (options.threshold !== null) {
2984
- valid = distance >= options.threshold;
2985
- }
2986
-
2987
- return valid;
2988
- }
2989
-
2990
- /**
2991
- * Checks the user has swiped back to cancel.
2992
- * @return Boolean if <code>cancelThreshold</code> has been set, return true if the cancelThreshold was met, else false.
2993
- * If no cancelThreshold was set, then we return true.
2994
- * @inner
2995
- */
2996
- function didSwipeBackToCancel() {
2997
- var cancelled = false;
2998
- if(options.cancelThreshold !== null && direction !==null) {
2999
- cancelled = (getMaxDistance( direction ) - distance) >= options.cancelThreshold;
3000
- }
3001
-
3002
- return cancelled;
3003
- }
3004
-
3005
- /**
3006
- * Checks the user has pinched far enough
3007
- * @return Boolean if <code>pinchThreshold</code> has been set, return true if the threshold was met, else false.
3008
- * If no threshold was set, then we return true.
3009
- * @inner
3010
- */
3011
- function validatePinchDistance() {
3012
- if (options.pinchThreshold !== null) {
3013
- return pinchDistance >= options.pinchThreshold;
3014
- }
3015
- return true;
3016
- }
3017
-
3018
- /**
3019
- * Checks that the time taken to swipe meets the minimum / maximum requirements
3020
- * @return Boolean
3021
- * @inner
3022
- */
3023
- function validateSwipeTime() {
3024
- var result;
3025
- //If no time set, then return true
3026
-
3027
- if (options.maxTimeThreshold) {
3028
- if (duration >= options.maxTimeThreshold) {
3029
- result = false;
3030
- } else {
3031
- result = true;
3032
- }
3033
- }
3034
- else {
3035
- result = true;
3036
- }
3037
-
3038
- return result;
3039
- }
3040
-
3041
-
3042
- /**
3043
- * Checks direction of the swipe and the value allowPageScroll to see if we should allow or prevent the default behaviour from occurring.
3044
- * This will essentially allow page scrolling or not when the user is swiping on a touchSwipe object.
3045
- * @param {object} jqEvent The normalised jQuery representation of the event object.
3046
- * @param {string} direction The direction of the event. See {@link $.fn.swipe.directions}
3047
- * @see $.fn.swipe.directions
3048
- * @inner
3049
- */
3050
- function validateDefaultEvent(jqEvent, direction) {
3051
- if (options.allowPageScroll === NONE || hasPinches()) {
3052
- jqEvent.preventDefault();
3053
- } else {
3054
- var auto = options.allowPageScroll === AUTO;
3055
-
3056
- switch (direction) {
3057
- case LEFT:
3058
- if ((options.swipeLeft && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
3059
- jqEvent.preventDefault();
3060
- }
3061
- break;
3062
-
3063
- case RIGHT:
3064
- if ((options.swipeRight && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
3065
- jqEvent.preventDefault();
3066
- }
3067
- break;
3068
-
3069
- case UP:
3070
- if ((options.swipeUp && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
3071
- jqEvent.preventDefault();
3072
- }
3073
- break;
3074
-
3075
- case DOWN:
3076
- if ((options.swipeDown && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
3077
- jqEvent.preventDefault();
3078
- }
3079
- break;
3080
- }
3081
- }
3082
-
3083
- }
3084
-
3085
-
3086
- // PINCHES
3087
- /**
3088
- * Returns true of the current pinch meets the thresholds
3089
- * @return Boolean
3090
- * @inner
3091
- */
3092
- function validatePinch() {
3093
- var hasCorrectFingerCount = validateFingers();
3094
- var hasEndPoint = validateEndPoint();
3095
- var hasCorrectDistance = validatePinchDistance();
3096
- return hasCorrectFingerCount && hasEndPoint && hasCorrectDistance;
3097
-
3098
- }
3099
-
3100
- /**
3101
- * Returns true if any Pinch events have been registered
3102
- * @return Boolean
3103
- * @inner
3104
- */
3105
- function hasPinches() {
3106
- //Enure we dont return 0 or null for false values
3107
- return !!(options.pinchStatus || options.pinchIn || options.pinchOut);
3108
- }
3109
-
3110
- /**
3111
- * Returns true if we are detecting pinches, and have one
3112
- * @return Boolean
3113
- * @inner
3114
- */
3115
- function didPinch() {
3116
- //Enure we dont return 0 or null for false values
3117
- return !!(validatePinch() && hasPinches());
3118
- }
3119
-
3120
-
3121
-
3122
-
3123
- // SWIPES
3124
- /**
3125
- * Returns true if the current swipe meets the thresholds
3126
- * @return Boolean
3127
- * @inner
3128
- */
3129
- function validateSwipe() {
3130
- //Check validity of swipe
3131
- var hasValidTime = validateSwipeTime();
3132
- var hasValidDistance = validateSwipeDistance();
3133
- var hasCorrectFingerCount = validateFingers();
3134
- var hasEndPoint = validateEndPoint();
3135
- var didCancel = didSwipeBackToCancel();
3136
-
3137
- // if the user swiped more than the minimum length, perform the appropriate action
3138
- // hasValidDistance is null when no distance is set
3139
- var valid = !didCancel && hasEndPoint && hasCorrectFingerCount && hasValidDistance && hasValidTime;
3140
-
3141
- return valid;
3142
- }
3143
-
3144
- /**
3145
- * Returns true if any Swipe events have been registered
3146
- * @return Boolean
3147
- * @inner
3148
- */
3149
- function hasSwipes() {
3150
- //Enure we dont return 0 or null for false values
3151
- return !!(options.swipe || options.swipeStatus || options.swipeLeft || options.swipeRight || options.swipeUp || options.swipeDown);
3152
- }
3153
-
3154
-
3155
- /**
3156
- * Returns true if we are detecting swipes and have one
3157
- * @return Boolean
3158
- * @inner
3159
- */
3160
- function didSwipe() {
3161
- //Enure we dont return 0 or null for false values
3162
- return !!(validateSwipe() && hasSwipes());
3163
- }
3164
-
3165
- /**
3166
- * Returns true if we have matched the number of fingers we are looking for
3167
- * @return Boolean
3168
- * @inner
3169
- */
3170
- function validateFingers() {
3171
- //The number of fingers we want were matched, or on desktop we ignore
3172
- return ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH);
3173
- }
3174
-
3175
- /**
3176
- * Returns true if we have an end point for the swipe
3177
- * @return Boolean
3178
- * @inner
3179
- */
3180
- function validateEndPoint() {
3181
- //We have an end value for the finger
3182
- return fingerData[0].end.x !== 0;
3183
- }
3184
-
3185
- // TAP / CLICK
3186
- /**
3187
- * Returns true if a click / tap events have been registered
3188
- * @return Boolean
3189
- * @inner
3190
- */
3191
- function hasTap() {
3192
- //Enure we dont return 0 or null for false values
3193
- return !!(options.tap) ;
3194
- }
3195
-
3196
- /**
3197
- * Returns true if a double tap events have been registered
3198
- * @return Boolean
3199
- * @inner
3200
- */
3201
- function hasDoubleTap() {
3202
- //Enure we dont return 0 or null for false values
3203
- return !!(options.doubleTap) ;
3204
- }
3205
-
3206
- /**
3207
- * Returns true if any long tap events have been registered
3208
- * @return Boolean
3209
- * @inner
3210
- */
3211
- function hasLongTap() {
3212
- //Enure we dont return 0 or null for false values
3213
- return !!(options.longTap) ;
3214
- }
3215
-
3216
- /**
3217
- * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
3218
- * @return Boolean
3219
- * @inner
3220
- */
3221
- function validateDoubleTap() {
3222
- if(doubleTapStartTime==null){
3223
- return false;
3224
- }
3225
- var now = getTimeStamp();
3226
- return (hasDoubleTap() && ((now-doubleTapStartTime) <= options.doubleTapThreshold));
3227
- }
3228
-
3229
- /**
3230
- * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
3231
- * @return Boolean
3232
- * @inner
3233
- */
3234
- function inDoubleTap() {
3235
- return validateDoubleTap();
3236
- }
3237
-
3238
-
3239
- /**
3240
- * Returns true if we have a valid tap
3241
- * @return Boolean
3242
- * @inner
3243
- */
3244
- function validateTap() {
3245
- return ((fingerCount === 1 || !SUPPORTS_TOUCH) && (isNaN(distance) || distance < options.threshold));
3246
- }
3247
-
3248
- /**
3249
- * Returns true if we have a valid long tap
3250
- * @return Boolean
3251
- * @inner
3252
- */
3253
- function validateLongTap() {
3254
- //slight threshold on moving finger
3255
- return ((duration > options.longTapThreshold) && (distance < DOUBLE_TAP_THRESHOLD));
3256
- }
3257
-
3258
- /**
3259
- * Returns true if we are detecting taps and have one
3260
- * @return Boolean
3261
- * @inner
3262
- */
3263
- function didTap() {
3264
- //Enure we dont return 0 or null for false values
3265
- return !!(validateTap() && hasTap());
3266
- }
3267
-
3268
-
3269
- /**
3270
- * Returns true if we are detecting double taps and have one
3271
- * @return Boolean
3272
- * @inner
3273
- */
3274
- function didDoubleTap() {
3275
- //Enure we dont return 0 or null for false values
3276
- return !!(validateDoubleTap() && hasDoubleTap());
3277
- }
3278
-
3279
- /**
3280
- * Returns true if we are detecting long taps and have one
3281
- * @return Boolean
3282
- * @inner
3283
- */
3284
- function didLongTap() {
3285
- //Enure we dont return 0 or null for false values
3286
- return !!(validateLongTap() && hasLongTap());
3287
- }
3288
-
3289
-
3290
-
3291
-
3292
- // MULTI FINGER TOUCH
3293
- /**
3294
- * Starts tracking the time between 2 finger releases, and keeps track of how many fingers we initially had up
3295
- * @inner
3296
- */
3297
- function startMultiFingerRelease() {
3298
- previousTouchEndTime = getTimeStamp();
3299
- previousTouchFingerCount = event.touches.length+1;
3300
- }
3301
-
3302
- /**
3303
- * Cancels the tracking of time between 2 finger releases, and resets counters
3304
- * @inner
3305
- */
3306
- function cancelMultiFingerRelease() {
3307
- previousTouchEndTime = 0;
3308
- previousTouchFingerCount = 0;
3309
- }
3310
-
3311
- /**
3312
- * Checks if we are in the threshold between 2 fingers being released
3313
- * @return Boolean
3314
- * @inner
3315
- */
3316
- function inMultiFingerRelease() {
3317
-
3318
- var withinThreshold = false;
3319
-
3320
- if(previousTouchEndTime) {
3321
- var diff = getTimeStamp() - previousTouchEndTime
3322
- if( diff<=options.fingerReleaseThreshold ) {
3323
- withinThreshold = true;
3324
- }
3325
- }
3326
-
3327
- return withinThreshold;
3328
- }
3329
-
3330
-
3331
- /**
3332
- * gets a data flag to indicate that a touch is in progress
3333
- * @return Boolean
3334
- * @inner
3335
- */
3336
- function getTouchInProgress() {
3337
- //strict equality to ensure only true and false are returned
3338
- return !!($element.data(PLUGIN_NS+'_intouch') === true);
3339
- }
3340
-
3341
- /**
3342
- * Sets a data flag to indicate that a touch is in progress
3343
- * @param {boolean} val The value to set the property to
3344
- * @inner
3345
- */
3346
- function setTouchInProgress(val) {
3347
-
3348
- //Add or remove event listeners depending on touch status
3349
- if(val===true) {
3350
- $element.bind(MOVE_EV, touchMove);
3351
- $element.bind(END_EV, touchEnd);
3352
-
3353
- //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
3354
- if(LEAVE_EV) {
3355
- $element.bind(LEAVE_EV, touchLeave);
3356
- }
3357
- } else {
3358
- $element.unbind(MOVE_EV, touchMove, false);
3359
- $element.unbind(END_EV, touchEnd, false);
3360
-
3361
- //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
3362
- if(LEAVE_EV) {
3363
- $element.unbind(LEAVE_EV, touchLeave, false);
3364
- }
3365
- }
3366
-
3367
-
3368
- //strict equality to ensure only true and false can update the value
3369
- $element.data(PLUGIN_NS+'_intouch', val === true);
3370
- }
3371
-
3372
-
3373
- /**
3374
- * Creates the finger data for the touch/finger in the event object.
3375
- * @param {int} index The index in the array to store the finger data (usually the order the fingers were pressed)
3376
- * @param {object} evt The event object containing finger data
3377
- * @return finger data object
3378
- * @inner
3379
- */
3380
- function createFingerData( index, evt ) {
3381
- var id = evt.identifier!==undefined ? evt.identifier : 0;
3382
-
3383
- fingerData[index].identifier = id;
3384
- fingerData[index].start.x = fingerData[index].end.x = evt.pageX||evt.clientX;
3385
- fingerData[index].start.y = fingerData[index].end.y = evt.pageY||evt.clientY;
3386
-
3387
- return fingerData[index];
3388
- }
3389
-
3390
- /**
3391
- * Updates the finger data for a particular event object
3392
- * @param {object} evt The event object containing the touch/finger data to upadte
3393
- * @return a finger data object.
3394
- * @inner
3395
- */
3396
- function updateFingerData(evt) {
3397
-
3398
- var id = evt.identifier!==undefined ? evt.identifier : 0;
3399
- var f = getFingerData( id );
3400
-
3401
- f.end.x = evt.pageX||evt.clientX;
3402
- f.end.y = evt.pageY||evt.clientY;
3403
-
3404
- return f;
3405
- }
3406
-
3407
- /**
3408
- * Returns a finger data object by its event ID.
3409
- * Each touch event has an identifier property, which is used
3410
- * to track repeat touches
3411
- * @param {int} id The unique id of the finger in the sequence of touch events.
3412
- * @return a finger data object.
3413
- * @inner
3414
- */
3415
- function getFingerData( id ) {
3416
- for(var i=0; i<fingerData.length; i++) {
3417
- if(fingerData[i].identifier == id) {
3418
- return fingerData[i];
3419
- }
3420
- }
3421
- }
3422
-
3423
- /**
3424
- * Creats all the finger onjects and returns an array of finger data
3425
- * @return Array of finger objects
3426
- * @inner
3427
- */
3428
- function createAllFingerData() {
3429
- var fingerData=[];
3430
- for (var i=0; i<=5; i++) {
3431
- fingerData.push({
3432
- start:{ x: 0, y: 0 },
3433
- end:{ x: 0, y: 0 },
3434
- identifier:0
3435
- });
3436
- }
3437
-
3438
- return fingerData;
3439
- }
3440
-
3441
- /**
3442
- * Sets the maximum distance swiped in the given direction.
3443
- * If the new value is lower than the current value, the max value is not changed.
3444
- * @param {string} direction The direction of the swipe
3445
- * @param {int} distance The distance of the swipe
3446
- * @inner
3447
- */
3448
- function setMaxDistance(direction, distance) {
3449
- distance = Math.max(distance, getMaxDistance(direction) );
3450
- maximumsMap[direction].distance = distance;
3451
- }
3452
-
3453
- /**
3454
- * gets the maximum distance swiped in the given direction.
3455
- * @param {string} direction The direction of the swipe
3456
- * @return int The distance of the swipe
3457
- * @inner
3458
- */
3459
- function getMaxDistance(direction) {
3460
- if (maximumsMap[direction]) return maximumsMap[direction].distance;
3461
- return undefined;
3462
- }
3463
-
3464
- /**
3465
- * Creats a map of directions to maximum swiped values.
3466
- * @return Object A dictionary of maximum values, indexed by direction.
3467
- * @inner
3468
- */
3469
- function createMaximumsData() {
3470
- var maxData={};
3471
- maxData[LEFT]=createMaximumVO(LEFT);
3472
- maxData[RIGHT]=createMaximumVO(RIGHT);
3473
- maxData[UP]=createMaximumVO(UP);
3474
- maxData[DOWN]=createMaximumVO(DOWN);
3475
-
3476
- return maxData;
3477
- }
3478
-
3479
- /**
3480
- * Creates a map maximum swiped values for a given swipe direction
3481
- * @param {string} The direction that these values will be associated with
3482
- * @return Object Maximum values
3483
- * @inner
3484
- */
3485
- function createMaximumVO(dir) {
3486
- return {
3487
- direction:dir,
3488
- distance:0
3489
- }
3490
- }
3491
-
3492
-
3493
- //
3494
- // MATHS / UTILS
3495
- //
3496
-
3497
- /**
3498
- * Calculate the duration of the swipe
3499
- * @return int
3500
- * @inner
3501
- */
3502
- function calculateDuration() {
3503
- return endTime - startTime;
3504
- }
3505
-
3506
- /**
3507
- * Calculate the distance between 2 touches (pinch)
3508
- * @param {point} startPoint A point object containing x and y co-ordinates
3509
- * @param {point} endPoint A point object containing x and y co-ordinates
3510
- * @return int;
3511
- * @inner
3512
- */
3513
- function calculateTouchesDistance(startPoint, endPoint) {
3514
- var diffX = Math.abs(startPoint.x - endPoint.x);
3515
- var diffY = Math.abs(startPoint.y - endPoint.y);
3516
-
3517
- return Math.round(Math.sqrt(diffX*diffX+diffY*diffY));
3518
- }
3519
-
3520
- /**
3521
- * Calculate the zoom factor between the start and end distances
3522
- * @param {int} startDistance Distance (between 2 fingers) the user started pinching at
3523
- * @param {int} endDistance Distance (between 2 fingers) the user ended pinching at
3524
- * @return float The zoom value from 0 to 1.
3525
- * @inner
3526
- */
3527
- function calculatePinchZoom(startDistance, endDistance) {
3528
- var percent = (endDistance/startDistance) * 1;
3529
- return percent.toFixed(2);
3530
- }
3531
-
3532
-
3533
- /**
3534
- * Returns the pinch direction, either IN or OUT for the given points
3535
- * @return string Either {@link $.fn.swipe.directions.IN} or {@link $.fn.swipe.directions.OUT}
3536
- * @see $.fn.swipe.directions
3537
- * @inner
3538
- */
3539
- function calculatePinchDirection() {
3540
- if(pinchZoom<1) {
3541
- return OUT;
3542
- }
3543
- else {
3544
- return IN;
3545
- }
3546
- }
3547
-
3548
-
3549
- /**
3550
- * Calculate the length / distance of the swipe
3551
- * @param {point} startPoint A point object containing x and y co-ordinates
3552
- * @param {point} endPoint A point object containing x and y co-ordinates
3553
- * @return int
3554
- * @inner
3555
- */
3556
- function calculateDistance(startPoint, endPoint) {
3557
- return Math.round(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)));
3558
- }
3559
-
3560
- /**
3561
- * Calculate the angle of the swipe
3562
- * @param {point} startPoint A point object containing x and y co-ordinates
3563
- * @param {point} endPoint A point object containing x and y co-ordinates
3564
- * @return int
3565
- * @inner
3566
- */
3567
- function calculateAngle(startPoint, endPoint) {
3568
- var x = startPoint.x - endPoint.x;
3569
- var y = endPoint.y - startPoint.y;
3570
- var r = Math.atan2(y, x); //radians
3571
- var angle = Math.round(r * 180 / Math.PI); //degrees
3572
-
3573
- //ensure value is positive
3574
- if (angle < 0) {
3575
- angle = 360 - Math.abs(angle);
3576
- }
3577
-
3578
- return angle;
3579
- }
3580
-
3581
- /**
3582
- * Calculate the direction of the swipe
3583
- * This will also call calculateAngle to get the latest angle of swipe
3584
- * @param {point} startPoint A point object containing x and y co-ordinates
3585
- * @param {point} endPoint A point object containing x and y co-ordinates
3586
- * @return string Either {@link $.fn.swipe.directions.LEFT} / {@link $.fn.swipe.directions.RIGHT} / {@link $.fn.swipe.directions.DOWN} / {@link $.fn.swipe.directions.UP}
3587
- * @see $.fn.swipe.directions
3588
- * @inner
3589
- */
3590
- function calculateDirection(startPoint, endPoint ) {
3591
- var angle = calculateAngle(startPoint, endPoint);
3592
-
3593
- if ((angle <= 45) && (angle >= 0)) {
3594
- return LEFT;
3595
- } else if ((angle <= 360) && (angle >= 315)) {
3596
- return LEFT;
3597
- } else if ((angle >= 135) && (angle <= 225)) {
3598
- return RIGHT;
3599
- } else if ((angle > 45) && (angle < 135)) {
3600
- return DOWN;
3601
- } else {
3602
- return UP;
3603
- }
3604
- }
3605
-
3606
-
3607
- /**
3608
- * Returns a MS time stamp of the current time
3609
- * @return int
3610
- * @inner
3611
- */
3612
- function getTimeStamp() {
3613
- var now = new Date();
3614
- return now.getTime();
3615
- }
3616
-
3617
-
3618
-
3619
- /**
3620
- * Returns a bounds object with left, right, top and bottom properties for the element specified.
3621
- * @param {DomNode} The DOM node to get the bounds for.
3622
- */
3623
- function getbounds( el ) {
3624
- el = $(el);
3625
- var offset = el.offset();
3626
-
3627
- var bounds = {
3628
- left:offset.left,
3629
- right:offset.left+el.outerWidth(),
3630
- top:offset.top,
3631
- bottom:offset.top+el.outerHeight()
3632
- }
3633
-
3634
- return bounds;
3635
- }
3636
-
3637
-
3638
- /**
3639
- * Checks if the point object is in the bounds object.
3640
- * @param {object} point A point object.
3641
- * @param {int} point.x The x value of the point.
3642
- * @param {int} point.y The x value of the point.
3643
- * @param {object} bounds The bounds object to test
3644
- * @param {int} bounds.left The leftmost value
3645
- * @param {int} bounds.right The righttmost value
3646
- * @param {int} bounds.top The topmost value
3647
- * @param {int} bounds.bottom The bottommost value
3648
- */
3649
- function isInBounds(point, bounds) {
3650
- return (point.x > bounds.left && point.x < bounds.right && point.y > bounds.top && point.y < bounds.bottom);
3651
- };
3652
-
3653
-
3654
- }
3655
-
3656
-
3657
-
3658
-
3659
- /**
3660
- * A catch all handler that is triggered for all swipe directions.
3661
- * @name $.fn.swipe#swipe
3662
- * @event
3663
- * @default null
3664
- * @param {EventObject} event The original event object
3665
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
3666
- * @param {int} distance The distance the user swiped
3667
- * @param {int} duration The duration of the swipe in milliseconds
3668
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3669
- * @param {object} fingerData The coordinates of fingers in event
3670
- */
3671
-
3672
-
3673
-
3674
-
3675
- /**
3676
- * A handler that is triggered for "left" swipes.
3677
- * @name $.fn.swipe#swipeLeft
3678
- * @event
3679
- * @default null
3680
- * @param {EventObject} event The original event object
3681
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
3682
- * @param {int} distance The distance the user swiped
3683
- * @param {int} duration The duration of the swipe in milliseconds
3684
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3685
- * @param {object} fingerData The coordinates of fingers in event
3686
- */
3687
-
3688
- /**
3689
- * A handler that is triggered for "right" swipes.
3690
- * @name $.fn.swipe#swipeRight
3691
- * @event
3692
- * @default null
3693
- * @param {EventObject} event The original event object
3694
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
3695
- * @param {int} distance The distance the user swiped
3696
- * @param {int} duration The duration of the swipe in milliseconds
3697
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3698
- * @param {object} fingerData The coordinates of fingers in event
3699
- */
3700
-
3701
- /**
3702
- * A handler that is triggered for "up" swipes.
3703
- * @name $.fn.swipe#swipeUp
3704
- * @event
3705
- * @default null
3706
- * @param {EventObject} event The original event object
3707
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
3708
- * @param {int} distance The distance the user swiped
3709
- * @param {int} duration The duration of the swipe in milliseconds
3710
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3711
- * @param {object} fingerData The coordinates of fingers in event
3712
- */
3713
-
3714
- /**
3715
- * A handler that is triggered for "down" swipes.
3716
- * @name $.fn.swipe#swipeDown
3717
- * @event
3718
- * @default null
3719
- * @param {EventObject} event The original event object
3720
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
3721
- * @param {int} distance The distance the user swiped
3722
- * @param {int} duration The duration of the swipe in milliseconds
3723
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3724
- * @param {object} fingerData The coordinates of fingers in event
3725
- */
3726
-
3727
- /**
3728
- * A handler triggered for every phase of the swipe. This handler is constantly fired for the duration of the pinch.
3729
- * This is triggered regardless of swipe thresholds.
3730
- * @name $.fn.swipe#swipeStatus
3731
- * @event
3732
- * @default null
3733
- * @param {EventObject} event The original event object
3734
- * @param {string} phase The phase of the swipe event. See {@link $.fn.swipe.phases}
3735
- * @param {string} direction The direction the user swiped in. This is null if the user has yet to move. See {@link $.fn.swipe.directions}
3736
- * @param {int} distance The distance the user swiped. This is 0 if the user has yet to move.
3737
- * @param {int} duration The duration of the swipe in milliseconds
3738
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3739
- * @param {object} fingerData The coordinates of fingers in event
3740
- */
3741
-
3742
- /**
3743
- * A handler triggered for pinch in events.
3744
- * @name $.fn.swipe#pinchIn
3745
- * @event
3746
- * @default null
3747
- * @param {EventObject} event The original event object
3748
- * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
3749
- * @param {int} distance The distance the user pinched
3750
- * @param {int} duration The duration of the swipe in milliseconds
3751
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3752
- * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
3753
- * @param {object} fingerData The coordinates of fingers in event
3754
- */
3755
-
3756
- /**
3757
- * A handler triggered for pinch out events.
3758
- * @name $.fn.swipe#pinchOut
3759
- * @event
3760
- * @default null
3761
- * @param {EventObject} event The original event object
3762
- * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
3763
- * @param {int} distance The distance the user pinched
3764
- * @param {int} duration The duration of the swipe in milliseconds
3765
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3766
- * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
3767
- * @param {object} fingerData The coordinates of fingers in event
3768
- */
3769
-
3770
- /**
3771
- * A handler triggered for all pinch events. This handler is constantly fired for the duration of the pinch. This is triggered regardless of thresholds.
3772
- * @name $.fn.swipe#pinchStatus
3773
- * @event
3774
- * @default null
3775
- * @param {EventObject} event The original event object
3776
- * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
3777
- * @param {int} distance The distance the user pinched
3778
- * @param {int} duration The duration of the swipe in milliseconds
3779
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
3780
- * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
3781
- * @param {object} fingerData The coordinates of fingers in event
3782
- */
3783
-
3784
- /**
3785
- * A click handler triggered when a user simply clicks, rather than swipes on an element.
3786
- * This is deprecated since version 1.6.2, any assignment to click will be assigned to the tap handler.
3787
- * You cannot use <code>on</code> to bind to this event as the default jQ <code>click</code> event will be triggered.
3788
- * Use the <code>tap</code> event instead.
3789
- * @name $.fn.swipe#click
3790
- * @event
3791
- * @deprecated since version 1.6.2, please use {@link $.fn.swipe#tap} instead
3792
- * @default null
3793
- * @param {EventObject} event The original event object
3794
- * @param {DomObject} target The element clicked on.
3795
- */
3796
-
3797
- /**
3798
- * A click / tap handler triggered when a user simply clicks or taps, rather than swipes on an element.
3799
- * @name $.fn.swipe#tap
3800
- * @event
3801
- * @default null
3802
- * @param {EventObject} event The original event object
3803
- * @param {DomObject} target The element clicked on.
3804
- */
3805
-
3806
- /**
3807
- * A double tap handler triggered when a user double clicks or taps on an element.
3808
- * You can set the time delay for a double tap with the {@link $.fn.swipe.defaults#doubleTapThreshold} property.
3809
- * Note: If you set both <code>doubleTap</code> and <code>tap</code> handlers, the <code>tap</code> event will be delayed by the <code>doubleTapThreshold</code>
3810
- * as the script needs to check if its a double tap.
3811
- * @name $.fn.swipe#doubleTap
3812
- * @see $.fn.swipe.defaults#doubleTapThreshold
3813
- * @event
3814
- * @default null
3815
- * @param {EventObject} event The original event object
3816
- * @param {DomObject} target The element clicked on.
3817
- */
3818
-
3819
- /**
3820
- * A long tap handler triggered once a tap has been release if the tap was longer than the longTapThreshold.
3821
- * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
3822
- * @name $.fn.swipe#longTap
3823
- * @see $.fn.swipe.defaults#longTapThreshold
3824
- * @event
3825
- * @default null
3826
- * @param {EventObject} event The original event object
3827
- * @param {DomObject} target The element clicked on.
3828
- */
3829
-
3830
- /**
3831
- * A hold tap handler triggered as soon as the longTapThreshold is reached
3832
- * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
3833
- * @name $.fn.swipe#hold
3834
- * @see $.fn.swipe.defaults#longTapThreshold
3835
- * @event
3836
- * @default null
3837
- * @param {EventObject} event The original event object
3838
- * @param {DomObject} target The element clicked on.
3839
- */
3840
-
3841
- }));
3842
-
3843
- /*!
3844
- * jQuery Mousewheel 3.1.12
3845
- *
3846
- * Copyright 2014 jQuery Foundation and other contributors
3847
- * Released under the MIT license.
3848
- * http://jquery.org/license
3849
- */
3850
-
3851
- (function (factory) {
3852
- if ( typeof define === 'function' && define.amd ) {
3853
- // AMD. Register as an anonymous module.
3854
- define(['jquery'], factory);
3855
- } else if (typeof exports === 'object') {
3856
- // Node/CommonJS style for Browserify
3857
- module.exports = factory;
3858
- } else {
3859
- // Browser globals
3860
- factory(jQuery);
3861
- }
3862
- }(function ($) {
3863
-
3864
- var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
3865
- toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
3866
- ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
3867
- slice = Array.prototype.slice,
3868
- nullLowestDeltaTimeout, lowestDelta;
3869
-
3870
- if ( $.event.fixHooks ) {
3871
- for ( var i = toFix.length; i; ) {
3872
- $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
3873
- }
3874
- }
3875
-
3876
- var special = $.event.special.mousewheel = {
3877
- version: '3.1.12',
3878
-
3879
- setup: function() {
3880
- if ( this.addEventListener ) {
3881
- for ( var i = toBind.length; i; ) {
3882
- this.addEventListener( toBind[--i], handler, false );
3883
- }
3884
- } else {
3885
- this.onmousewheel = handler;
3886
- }
3887
- // Store the line height and page height for this particular element
3888
- $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
3889
- $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
3890
- },
3891
-
3892
- teardown: function() {
3893
- if ( this.removeEventListener ) {
3894
- for ( var i = toBind.length; i; ) {
3895
- this.removeEventListener( toBind[--i], handler, false );
3896
- }
3897
- } else {
3898
- this.onmousewheel = null;
3899
- }
3900
- // Clean up the data we added to the element
3901
- $.removeData(this, 'mousewheel-line-height');
3902
- $.removeData(this, 'mousewheel-page-height');
3903
- },
3904
-
3905
- getLineHeight: function(elem) {
3906
- var $elem = $(elem),
3907
- $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
3908
- if (!$parent.length) {
3909
- $parent = $('body');
3910
- }
3911
- return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
3912
- },
3913
-
3914
- getPageHeight: function(elem) {
3915
- return $(elem).height();
3916
- },
3917
-
3918
- settings: {
3919
- adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
3920
- normalizeOffset: true // calls getBoundingClientRect for each event
3921
- }
3922
- };
3923
-
3924
- $.fn.extend({
3925
- mousewheel: function(fn) {
3926
- return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
3927
- },
3928
-
3929
- unmousewheel: function(fn) {
3930
- return this.unbind('mousewheel', fn);
3931
- }
3932
- });
3933
-
3934
-
3935
- function handler(event) {
3936
- var orgEvent = event || window.event,
3937
- args = slice.call(arguments, 1),
3938
- delta = 0,
3939
- deltaX = 0,
3940
- deltaY = 0,
3941
- absDelta = 0,
3942
- offsetX = 0,
3943
- offsetY = 0;
3944
- event = $.event.fix(orgEvent);
3945
- event.type = 'mousewheel';
3946
-
3947
- // Old school scrollwheel delta
3948
- if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
3949
- if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
3950
- if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
3951
- if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
3952
-
3953
- // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
3954
- if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
3955
- deltaX = deltaY * -1;
3956
- deltaY = 0;
3957
- }
3958
-
3959
- // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
3960
- delta = deltaY === 0 ? deltaX : deltaY;
3961
-
3962
- // New school wheel delta (wheel event)
3963
- if ( 'deltaY' in orgEvent ) {
3964
- deltaY = orgEvent.deltaY * -1;
3965
- delta = deltaY;
3966
- }
3967
- if ( 'deltaX' in orgEvent ) {
3968
- deltaX = orgEvent.deltaX;
3969
- if ( deltaY === 0 ) { delta = deltaX * -1; }
3970
- }
3971
-
3972
- // No change actually happened, no reason to go any further
3973
- if ( deltaY === 0 && deltaX === 0 ) { return; }
3974
-
3975
- // Need to convert lines and pages to pixels if we aren't already in pixels
3976
- // There are three delta modes:
3977
- // * deltaMode 0 is by pixels, nothing to do
3978
- // * deltaMode 1 is by lines
3979
- // * deltaMode 2 is by pages
3980
- if ( orgEvent.deltaMode === 1 ) {
3981
- var lineHeight = $.data(this, 'mousewheel-line-height');
3982
- delta *= lineHeight;
3983
- deltaY *= lineHeight;
3984
- deltaX *= lineHeight;
3985
- } else if ( orgEvent.deltaMode === 2 ) {
3986
- var pageHeight = $.data(this, 'mousewheel-page-height');
3987
- delta *= pageHeight;
3988
- deltaY *= pageHeight;
3989
- deltaX *= pageHeight;
3990
- }
3991
-
3992
- // Store lowest absolute delta to normalize the delta values
3993
- absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
3994
-
3995
- if ( !lowestDelta || absDelta < lowestDelta ) {
3996
- lowestDelta = absDelta;
3997
-
3998
- // Adjust older deltas if necessary
3999
- if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
4000
- lowestDelta /= 40;
4001
- }
4002
- }
4003
-
4004
- // Adjust older deltas if necessary
4005
- if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
4006
- // Divide all the things by 40!
4007
- delta /= 40;
4008
- deltaX /= 40;
4009
- deltaY /= 40;
4010
- }
4011
-
4012
- // Get a whole, normalized value for the deltas
4013
- delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
4014
- deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
4015
- deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
4016
-
4017
- // Normalise offsetX and offsetY properties
4018
- if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
4019
- var boundingRect = this.getBoundingClientRect();
4020
- offsetX = event.clientX - boundingRect.left;
4021
- offsetY = event.clientY - boundingRect.top;
4022
- }
4023
-
4024
- // Add information to the event object
4025
- event.deltaX = deltaX;
4026
- event.deltaY = deltaY;
4027
- event.deltaFactor = lowestDelta;
4028
- event.offsetX = offsetX;
4029
- event.offsetY = offsetY;
4030
- // Go ahead and set deltaMode to 0 since we converted to pixels
4031
- // Although this is a little odd since we overwrite the deltaX/Y
4032
- // properties with normalized deltas.
4033
- event.deltaMode = 0;
4034
-
4035
- // Add event and delta to the front of the arguments
4036
- args.unshift(event, delta, deltaX, deltaY);
4037
-
4038
- // Clearout lowestDelta after sometime to better
4039
- // handle multiple device types that give different
4040
- // a different lowestDelta
4041
- // Ex: trackpad = 3 and mouse wheel = 120
4042
- if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
4043
- nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
4044
-
4045
- return ($.event.dispatch || $.event.handle).apply(this, args);
4046
- }
4047
-
4048
- function nullLowestDelta() {
4049
- lowestDelta = null;
4050
- }
4051
-
4052
- function shouldAdjustOldDeltas(orgEvent, absDelta) {
4053
- // If this is an older event and the delta is divisable by 120,
4054
- // then we are assuming that the browser is treating this as an
4055
- // older mouse wheel event and that we should divide the deltas
4056
- // by 40 to try and get a more usable deltaFactor.
4057
- // Side note, this actually impacts the reported scroll distance
4058
- // in older browsers and can cause scrolling to be slower than native.
4059
- // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
4060
- return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
4061
- }
4062
-
4063
- }));
4064
-
4065
- /**
4066
- * enviraImagesLoaded PACKAGED v4.1.0
4067
- * JavaScript is all like "You images are done yet or what?"
4068
- * MIT License
4069
- */
4070
-
4071
- /**
4072
- * EvEmitter v1.0.1
4073
- * Lil' event emitter
4074
- * MIT License
4075
- */
4076
-
4077
- /* jshint unused: true, undef: true, strict: true */
4078
-
4079
- ( function( global, factory ) {
4080
- // universal module definition
4081
- /* jshint strict: false */ /* globals define, module */
4082
- if ( typeof define == 'function' && define.amd ) {
4083
- // AMD - RequireJS
4084
- define( 'ev-emitter/ev-emitter',factory );
4085
- } else if ( typeof module == 'object' && module.exports ) {
4086
- // CommonJS - Browserify, Webpack
4087
- module.exports = factory();
4088
- } else {
4089
- // Browser globals
4090
- global.EvEmitter = factory();
4091
- }
4092
-
4093
- }( this, function() {
4094
-
4095
-
4096
-
4097
- function EvEmitter() {}
4098
-
4099
- var proto = EvEmitter.prototype;
4100
-
4101
- proto.on = function( eventName, listener ) {
4102
- if ( !eventName || !listener ) {
4103
- return;
4104
- }
4105
- // set events hash
4106
- var events = this._events = this._events || {};
4107
- // set listeners array
4108
- var listeners = events[ eventName ] = events[ eventName ] || [];
4109
- // only add once
4110
- if ( listeners.indexOf( listener ) == -1 ) {
4111
- listeners.push( listener );
4112
- }
4113
-
4114
- return this;
4115
- };
4116
-
4117
- proto.once = function( eventName, listener ) {
4118
- if ( !eventName || !listener ) {
4119
- return;
4120
- }
4121
- // add event
4122
- this.on( eventName, listener );
4123
- // set once flag
4124
- // set onceEvents hash
4125
- var onceEvents = this._onceEvents = this._onceEvents || {};
4126
- // set onceListeners array
4127
- var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || [];
4128
- // set flag
4129
- onceListeners[ listener ] = true;
4130
-
4131
- return this;
4132
- };
4133
-
4134
- proto.off = function( eventName, listener ) {
4135
- var listeners = this._events && this._events[ eventName ];
4136
- if ( !listeners || !listeners.length ) {
4137
- return;
4138
- }
4139
- var index = listeners.indexOf( listener );
4140
- if ( index != -1 ) {
4141
- listeners.splice( index, 1 );
4142
- }
4143
-
4144
- return this;
4145
- };
4146
-
4147
- proto.emitEvent = function( eventName, args ) {
4148
- var listeners = this._events && this._events[ eventName ];
4149
- if ( !listeners || !listeners.length ) {
4150
- return;
4151
- }
4152
- var i = 0;
4153
- var listener = listeners[i];
4154
- args = args || [];
4155
- // once stuff
4156
- var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
4157
-
4158
- while ( listener ) {
4159
- var isOnce = onceListeners && onceListeners[ listener ];
4160
- if ( isOnce ) {
4161
- // remove listener
4162
- // remove before trigger to prevent recursion
4163
- this.off( eventName, listener );
4164
- // unset once flag
4165
- delete onceListeners[ listener ];
4166
- }
4167
- // trigger listener
4168
- listener.apply( this, args );
4169
- // get next listener
4170
- i += isOnce ? 0 : 1;
4171
- listener = listeners[i];
4172
- }
4173
-
4174
- return this;
4175
- };
4176
-
4177
- return EvEmitter;
4178
-
4179
- }));
4180
-
4181
- /*!
4182
- * enviraImagesLoaded v4.1.0
4183
- * JavaScript is all like "You images are done yet or what?"
4184
- * MIT License
4185
- */
4186
-
4187
- ( function( window, factory ) { 'use strict';
4188
- // universal module definition
4189
-
4190
- /*global define: false, module: false, require: false */
4191
-
4192
- if ( typeof define == 'function' && define.amd ) {
4193
- // AMD
4194
- define( [
4195
- 'ev-emitter/ev-emitter'
4196
- ], function( EvEmitter ) {
4197
- return factory( window, EvEmitter );
4198
- });
4199
- } else if ( typeof module == 'object' && module.exports ) {
4200
- // CommonJS
4201
- module.exports = factory(
4202
- window,
4203
- require('ev-emitter')
4204
- );
4205
- } else {
4206
- // browser global
4207
- window.enviraImagesLoaded = factory(
4208
- window,
4209
- window.EvEmitter
4210
- );
4211
- }
4212
-
4213
- })( window,
4214
-
4215
- // -------------------------- factory -------------------------- //
4216
-
4217
- function factory( window, EvEmitter ) {
4218
-
4219
-
4220
-
4221
- var $ = window.jQuery;
4222
- var console = window.console;
4223
-
4224
- // -------------------------- helpers -------------------------- //
4225
-
4226
- // extend objects
4227
- function extend( a, b ) {
4228
- for ( var prop in b ) {
4229
- a[ prop ] = b[ prop ];
4230
- }
4231
- return a;
4232
- }
4233
-
4234
- // turn element or nodeList into an array
4235
- function makeArray( obj ) {
4236
- var ary = [];
4237
- if ( Array.isArray( obj ) ) {
4238
- // use object if already an array
4239
- ary = obj;
4240
- } else if ( typeof obj.length == 'number' ) {
4241
- // convert nodeList to array
4242
- for ( var i=0; i < obj.length; i++ ) {
4243
- ary.push( obj[i] );
4244
- }
4245
- } else {
4246
- // array of single index
4247
- ary.push( obj );
4248
- }
4249
- return ary;
4250
- }
4251
-
4252
- // -------------------------- enviraImagesLoaded -------------------------- //
4253
-
4254
- /**
4255
- * @param {Array, Element, NodeList, String} elem
4256
- * @param {Object or Function} options - if function, use as callback
4257
- * @param {Function} onAlways - callback function
4258
- */
4259
- function EnviraImagesLoaded( elem, options, onAlways ) {
4260
- // coerce EnviraImagesLoaded() without new, to be new EnviraImagesLoaded()
4261
- if ( !( this instanceof EnviraImagesLoaded ) ) {
4262
- return new EnviraImagesLoaded( elem, options, onAlways );
4263
- }
4264
- // use elem as selector string
4265
- if ( typeof elem == 'string' ) {
4266
- elem = document.querySelectorAll( elem );
4267
- }
4268
-
4269
- this.elements = makeArray( elem );
4270
- this.options = extend( {}, this.options );
4271
-
4272
- if ( typeof options == 'function' ) {
4273
- onAlways = options;
4274
- } else {
4275
- extend( this.options, options );
4276
- }
4277
-
4278
- if ( onAlways ) {
4279
- this.on( 'always', onAlways );
4280
- }
4281
-
4282
- this.getImages();
4283
-
4284
- if ( $ ) {
4285
- // add jQuery Deferred object
4286
- this.jqDeferred = new $.Deferred();
4287
- }
4288
-
4289
- // HACK check async to allow time to bind listeners
4290
- setTimeout( function() {
4291
- this.check();
4292
- }.bind( this ));
4293
- }
4294
-
4295
- EnviraImagesLoaded.prototype = Object.create( EvEmitter.prototype );
4296
-
4297
- EnviraImagesLoaded.prototype.options = {};
4298
-
4299
- EnviraImagesLoaded.prototype.getImages = function() {
4300
- this.images = [];
4301
-
4302
- // filter & find items if we have an item selector
4303
- this.elements.forEach( this.addElementImages, this );
4304
- };
4305
-
4306
- /**
4307
- * @param {Node} element
4308
- */
4309
- EnviraImagesLoaded.prototype.addElementImages = function( elem ) {
4310
- // filter siblings
4311
- if ( elem.nodeName == 'IMG' ) {
4312
- this.addImage( elem );
4313
- }
4314
- // get background image on element
4315
- if ( this.options.background === true ) {
4316
- this.addElementBackgroundImages( elem );
4317
- }
4318
-
4319
- // find children
4320
- // no non-element nodes, #143
4321
- var nodeType = elem.nodeType;
4322
- if ( !nodeType || !elementNodeTypes[ nodeType ] ) {
4323
- return;
4324
- }
4325
- var childImgs = elem.querySelectorAll('img');
4326
- // concat childElems to filterFound array
4327
- for ( var i=0; i < childImgs.length; i++ ) {
4328
- var img = childImgs[i];
4329
- this.addImage( img );
4330
- }
4331
-
4332
- // get child background images
4333
- if ( typeof this.options.background == 'string' ) {
4334
- var children = elem.querySelectorAll( this.options.background );
4335
- for ( i=0; i < children.length; i++ ) {
4336
- var child = children[i];
4337
- this.addElementBackgroundImages( child );
4338
- }
4339
- }
4340
- };
4341
-
4342
- var elementNodeTypes = {
4343
- 1: true,
4344
- 9: true,
4345
- 11: true
4346
- };
4347
-
4348
- EnviraImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
4349
- var style = getComputedStyle( elem );
4350
- if ( !style ) {
4351
- // Firefox returns null if in a hidden iframe https://bugzil.la/548397
4352
- return;
4353
- }
4354
- // get url inside url("...")
4355
- var reURL = /url\((['"])?(.*?)\1\)/gi;
4356
- var matches = reURL.exec( style.backgroundImage );
4357
- while ( matches !== null ) {
4358
- var url = matches && matches[2];
4359
- if ( url ) {
4360
- this.addBackground( url, elem );
4361
- }
4362
- matches = reURL.exec( style.backgroundImage );
4363
- }
4364
- };
4365
-
4366
- /**
4367
- * @param {Image} img
4368
- */
4369
- EnviraImagesLoaded.prototype.addImage = function( img ) {
4370
- var loadingImage = new LoadingImage( img );
4371
- this.images.push( loadingImage );
4372
- };
4373
-
4374
- EnviraImagesLoaded.prototype.addBackground = function( url, elem ) {
4375
- var background = new Background( url, elem );
4376
- this.images.push( background );
4377
- };
4378
-
4379
- EnviraImagesLoaded.prototype.check = function() {
4380
- var _this = this;
4381
- this.progressedCount = 0;
4382
- this.hasAnyBroken = false;
4383
- // complete if no images
4384
- if ( !this.images.length ) {
4385
- this.complete();
4386
- return;
4387
- }
4388
-
4389
- function onProgress( image, elem, message ) {
4390
- // HACK - Chrome triggers event before object properties have changed. #83
4391
- setTimeout( function() {
4392
- _this.progress( image, elem, message );
4393
- });
4394
- }
4395
-
4396
- this.images.forEach( function( loadingImage ) {
4397
- loadingImage.once( 'progress', onProgress );
4398
- loadingImage.check();
4399
- });
4400
- };
4401
-
4402
- EnviraImagesLoaded.prototype.progress = function( image, elem, message ) {
4403
- this.progressedCount++;
4404
- this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
4405
- // progress event
4406
- this.emitEvent( 'progress', [ this, image, elem ] );
4407
- if ( this.jqDeferred && this.jqDeferred.notify ) {
4408
- this.jqDeferred.notify( this, image );
4409
- }
4410
- // check if completed
4411
- if ( this.progressedCount == this.images.length ) {
4412
- this.complete();
4413
- }
4414
-
4415
- if ( this.options.debug && console ) {
4416
- console.log( 'progress: ' + message, image, elem );
4417
- }
4418
- };
4419
-
4420
- EnviraImagesLoaded.prototype.complete = function() {
4421
- var eventName = this.hasAnyBroken ? 'fail' : 'done';
4422
- this.isComplete = true;
4423
- this.emitEvent( eventName, [ this ] );
4424
- this.emitEvent( 'always', [ this ] );
4425
- if ( this.jqDeferred ) {
4426
- var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
4427
- this.jqDeferred[ jqMethod ]( this );
4428
- }
4429
- };
4430
-
4431
- // -------------------------- -------------------------- //
4432
-
4433
- function LoadingImage( img ) {
4434
- this.img = img;
4435
- }
4436
-
4437
- LoadingImage.prototype = Object.create( EvEmitter.prototype );
4438
-
4439
- LoadingImage.prototype.check = function() {
4440
- // If complete is true and browser supports natural sizes,
4441
- // try to check for image status manually.
4442
- var isComplete = this.getIsImageComplete();
4443
- if ( isComplete ) {
4444
- // report based on naturalWidth
4445
- this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
4446
- return;
4447
- }
4448
-
4449
- // If none of the checks above matched, simulate loading on detached element.
4450
- this.proxyImage = new Image();
4451
- this.proxyImage.addEventListener( 'load', this );
4452
- this.proxyImage.addEventListener( 'error', this );
4453
- // bind to image as well for Firefox. #191
4454
- this.img.addEventListener( 'load', this );
4455
- this.img.addEventListener( 'error', this );
4456
- this.proxyImage.src = this.img.src;
4457
- };
4458
-
4459
- LoadingImage.prototype.getIsImageComplete = function() {
4460
- return this.img.complete && this.img.naturalWidth !== undefined;
4461
- };
4462
-
4463
- LoadingImage.prototype.confirm = function( isLoaded, message ) {
4464
- this.isLoaded = isLoaded;
4465
- this.emitEvent( 'progress', [ this, this.img, message ] );
4466
- };
4467
-
4468
- // ----- events ----- //
4469
-
4470
- // trigger specified handler for event type
4471
- LoadingImage.prototype.handleEvent = function( event ) {
4472
- var method = 'on' + event.type;
4473
- if ( this[ method ] ) {
4474
- this[ method ]( event );
4475
- }
4476
- };
4477
-
4478
- LoadingImage.prototype.onload = function() {
4479
- this.confirm( true, 'onload' );
4480
- this.unbindEvents();
4481
- };
4482
-
4483
- LoadingImage.prototype.onerror = function() {
4484
- this.confirm( false, 'onerror' );
4485
- this.unbindEvents();
4486
- };
4487
-
4488
- LoadingImage.prototype.unbindEvents = function() {
4489
- this.proxyImage.removeEventListener( 'load', this );
4490
- this.proxyImage.removeEventListener( 'error', this );
4491
- this.img.removeEventListener( 'load', this );
4492
- this.img.removeEventListener( 'error', this );
4493
- };
4494
-
4495
- // -------------------------- Background -------------------------- //
4496
-
4497
- function Background( url, element ) {
4498
- this.url = url;
4499
- this.element = element;
4500
- this.img = new Image();
4501
- }
4502
-
4503
- // inherit LoadingImage prototype
4504
- Background.prototype = Object.create( LoadingImage.prototype );
4505
-
4506
- Background.prototype.check = function() {
4507
- this.img.addEventListener( 'load', this );
4508
- this.img.addEventListener( 'error', this );
4509
- this.img.src = this.url;
4510
- // check if image is already complete
4511
- var isComplete = this.getIsImageComplete();
4512
- if ( isComplete ) {
4513
- this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
4514
- this.unbindEvents();
4515
- }
4516
- };
4517
-
4518
- Background.prototype.unbindEvents = function() {
4519
- this.img.removeEventListener( 'load', this );
4520
- this.img.removeEventListener( 'error', this );
4521
- };
4522
-
4523
- Background.prototype.confirm = function( isLoaded, message ) {
4524
- this.isLoaded = isLoaded;
4525
- this.emitEvent( 'progress', [ this, this.element, message ] );
4526
- };
4527
-
4528
- // -------------------------- jQuery -------------------------- //
4529
-
4530
- EnviraImagesLoaded.makeJQueryPlugin = function( jQuery ) {
4531
- jQuery = jQuery || window.jQuery;
4532
- if ( !jQuery ) {
4533
- return;
4534
- }
4535
- // set local variable
4536
- $ = jQuery;
4537
- // $().enviraImagesLoaded()
4538
- $.fn.enviraImagesLoaded = function( options, callback ) {
4539
- var instance = new EnviraImagesLoaded( this, options, callback );
4540
- return instance.jqDeferred.promise( $(this) );
4541
- };
4542
- };
4543
- // try making plugin
4544
- EnviraImagesLoaded.makeJQueryPlugin();
4545
-
4546
- // -------------------------- -------------------------- //
4547
-
4548
- return EnviraImagesLoaded;
4549
-
4550
- });
4551
-
4552
-
4553
- /*!
4554
- * Enviratope PACKAGED v3.0.0
4555
- *
4556
- * Licensed GPLv3 for open source use
4557
- * or Enviratope Commercial License for commercial use
4558
- *
4559
- * http://enviratope.metafizzy.co
4560
- * Copyright 2016 Metafizzy
4561
- */
4562
-
4563
- /**
4564
- * Bridget makes jQuery widgets
4565
- * v2.0.0
4566
- * MIT license
4567
- */
4568
-
4569
- /* jshint browser: true, strict: true, undef: true, unused: true */
4570
-
4571
- ( function( window, factory ) {
4572
- 'use strict';
4573
- /* globals define: false, module: false, require: false */
4574
-
4575
- if ( typeof define == 'function' && define.amd ) {
4576
- // AMD
4577
- define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
4578
- factory( window, jQuery );
4579
- });
4580
- } else if ( typeof module == 'object' && module.exports ) {
4581
- // CommonJS
4582
- module.exports = factory(
4583
- window,
4584
- require('jquery')
4585
- );
4586
- } else {
4587
- // browser global
4588
- window.jQueryBridget = factory(
4589
- window,
4590
- window.jQuery
4591
- );
4592
- }
4593
-
4594
- }( window, function factory( window, jQuery ) {
4595
- 'use strict';
4596
-
4597
- // ----- utils ----- //
4598
-
4599
- var arraySlice = Array.prototype.slice;
4600
-
4601
- // helper function for logging errors
4602
- // $.error breaks jQuery chaining
4603
- var console = window.console;
4604
- var logError = typeof console == 'undefined' ? function() {} :
4605
- function( message ) {
4606
- console.error( message );
4607
- };
4608
-
4609
- // ----- jQueryBridget ----- //
4610
-
4611
- function jQueryBridget( namespace, PluginClass, $ ) {
4612
- $ = $ || jQuery || window.jQuery;
4613
- if ( !$ ) {
4614
- return;
4615
- }
4616
-
4617
- // add option method -> $().plugin('option', {...})
4618
- if ( !PluginClass.prototype.option ) {
4619
- // option setter
4620
- PluginClass.prototype.option = function( opts ) {
4621
- // bail out if not an object
4622
- if ( !$.isPlainObject( opts ) ){
4623
- return;
4624
- }
4625
- this.options = $.extend( true, this.options, opts );
4626
- };
4627
- }
4628
-
4629
- // make jQuery plugin
4630
- $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
4631
- if ( typeof arg0 == 'string' ) {
4632
- // method call $().plugin( 'methodName', { options } )
4633
- // shift arguments by 1
4634
- var args = arraySlice.call( arguments, 1 );
4635
- return methodCall( this, arg0, args );
4636
- }
4637
- // just $().plugin({ options })
4638
- plainCall( this, arg0 );
4639
- return this;
4640
- };
4641
-
4642
- // $().plugin('methodName')
4643
- function methodCall( $elems, methodName, args ) {
4644
- var returnValue;
4645
- var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
4646
-
4647
- $elems.each( function( i, elem ) {
4648
- // get instance
4649
- var instance = $.data( elem, namespace );
4650
- if ( !instance ) {
4651
- logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
4652
- pluginMethodStr );
4653
- return;
4654
- }
4655
-
4656
- var method = instance[ methodName ];
4657
- if ( !method || methodName.charAt(0) == '_' ) {
4658
- logError( pluginMethodStr + ' is not a valid method' );
4659
- return;
4660
- }
4661
-
4662
- // apply method, get return value
4663
- var value = method.apply( instance, args );
4664
- // set return value if value is returned, use only first value
4665
- returnValue = returnValue === undefined ? value : returnValue;
4666
- });
4667
-
4668
- return returnValue !== undefined ? returnValue : $elems;
4669
- }
4670
-
4671
- function plainCall( $elems, options ) {
4672
- $elems.each( function( i, elem ) {
4673
- var instance = $.data( elem, namespace );
4674
- if ( instance ) {
4675
- // set options & init
4676
- instance.option( options );
4677
- instance._init();
4678
- } else {
4679
- // initialize new instance
4680
- instance = new PluginClass( elem, options );
4681
- $.data( elem, namespace, instance );
4682
- }
4683
- });
4684
- }
4685
-
4686
- updateJQuery( $ );
4687
-
4688
- }
4689
-
4690
- // ----- updateJQuery ----- //
4691
-
4692
- // set $.bridget for v1 backwards compatibility
4693
- function updateJQuery( $ ) {
4694
- if ( !$ || ( $ && $.bridget ) ) {
4695
- return;
4696
- }
4697
- $.bridget = jQueryBridget;
4698
- }
4699
-
4700
- updateJQuery( jQuery || window.jQuery );
4701
-
4702
- // ----- ----- //
4703
-
4704
- return jQueryBridget;
4705
-
4706
- }));
4707
-
4708
- /**
4709
- * EvEmitter v1.0.2
4710
- * Lil' event emitter
4711
- * MIT License
4712
- */
4713
-
4714
- /* jshint unused: true, undef: true, strict: true */
4715
-
4716
- ( function( global, factory ) {
4717
- // universal module definition
4718
- /* jshint strict: false */ /* globals define, module */
4719
- if ( typeof define == 'function' && define.amd ) {
4720
- // AMD - RequireJS
4721
- define( 'ev-emitter/ev-emitter',factory );
4722
- } else if ( typeof module == 'object' && module.exports ) {
4723
- // CommonJS - Browserify, Webpack
4724
- module.exports = factory();
4725
- } else {
4726
- // Browser globals
4727
- global.EvEmitter = factory();
4728
- }
4729
-
4730
- }( this, function() {
4731
-
4732
-
4733
-
4734
- function EvEmitter() {}
4735
-
4736
- var proto = EvEmitter.prototype;
4737
-
4738
- proto.on = function( eventName, listener ) {
4739
- if ( !eventName || !listener ) {
4740
- return;
4741
- }
4742
- // set events hash
4743
- var events = this._events = this._events || {};
4744
- // set listeners array
4745
- var listeners = events[ eventName ] = events[ eventName ] || [];
4746
- // only add once
4747
- if ( listeners.indexOf( listener ) == -1 ) {
4748
- listeners.push( listener );
4749
- }
4750
-
4751
- return this;
4752
- };
4753
-
4754
- proto.once = function( eventName, listener ) {
4755
- if ( !eventName || !listener ) {
4756
- return;
4757
- }
4758
- // add event
4759
- this.on( eventName, listener );
4760
- // set once flag
4761
- // set onceEvents hash
4762
- var onceEvents = this._onceEvents = this._onceEvents || {};
4763
- // set onceListeners object
4764
- var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
4765
- // set flag
4766
- onceListeners[ listener ] = true;
4767
-
4768
- return this;
4769
- };
4770
-
4771
- proto.off = function( eventName, listener ) {
4772
- var listeners = this._events && this._events[ eventName ];
4773
- if ( !listeners || !listeners.length ) {
4774
- return;
4775
- }
4776
- var index = listeners.indexOf( listener );
4777
- if ( index != -1 ) {
4778
- listeners.splice( index, 1 );
4779
- }
4780
-
4781
- return this;
4782
- };
4783
-
4784
- proto.emitEvent = function( eventName, args ) {
4785
- var listeners = this._events && this._events[ eventName ];
4786
- if ( !listeners || !listeners.length ) {
4787
- return;
4788
- }
4789
- var i = 0;
4790
- var listener = listeners[i];
4791
- args = args || [];
4792
- // once stuff
4793
- var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
4794
-
4795
- while ( listener ) {
4796
- var isOnce = onceListeners && onceListeners[ listener ];
4797
- if ( isOnce ) {
4798
- // remove listener
4799
- // remove before trigger to prevent recursion
4800
- this.off( eventName, listener );
4801
- // unset once flag
4802
- delete onceListeners[ listener ];
4803
- }
4804
- // trigger listener
4805
- listener.apply( this, args );
4806
- // get next listener
4807
- i += isOnce ? 0 : 1;
4808
- listener = listeners[i];
4809
- }
4810
-
4811
- return this;
4812
- };
4813
-
4814
- return EvEmitter;
4815
-
4816
- }));
4817
-
4818
- /*!
4819
- * getSize v2.0.2
4820
- * measure size of elements
4821
- * MIT license
4822
- */
4823
-
4824
- /*jshint browser: true, strict: true, undef: true, unused: true */
4825
- /*global define: false, module: false, console: false */
4826
-
4827
- ( function( window, factory ) {
4828
- 'use strict';
4829
-
4830
- if ( typeof define == 'function' && define.amd ) {
4831
- // AMD
4832
- define( 'get-size/get-size',[],function() {
4833
- return factory();
4834
- });
4835
- } else if ( typeof module == 'object' && module.exports ) {
4836
- // CommonJS
4837
- module.exports = factory();
4838
- } else {
4839
- // browser global
4840
- window.getSize = factory();
4841
- }
4842
-
4843
- })( window, function factory() {
4844
- 'use strict';
4845
-
4846
- // -------------------------- helpers -------------------------- //
4847
-
4848
- // get a number from a string, not a percentage
4849
- function getStyleSize( value ) {
4850
- var num = parseFloat( value );
4851
- // not a percent like '100%', and a number
4852
- var isValid = value.indexOf('%') == -1 && !isNaN( num );
4853
- return isValid && num;
4854
- }
4855
-
4856
- function noop() {}
4857
-
4858
- var logError = typeof console == 'undefined' ? noop :
4859
- function( message ) {
4860
- console.error( message );
4861
- };
4862
-
4863
- // -------------------------- measurements -------------------------- //
4864
-
4865
- var measurements = [
4866
- 'paddingLeft',
4867
- 'paddingRight',
4868
- 'paddingTop',
4869
- 'paddingBottom',
4870
- 'marginLeft',
4871
- 'marginRight',
4872
- 'marginTop',
4873
- 'marginBottom',
4874
- 'borderLeftWidth',
4875
- 'borderRightWidth',
4876
- 'borderTopWidth',
4877
- 'borderBottomWidth'
4878
- ];
4879
-
4880
- var measurementsLength = measurements.length;
4881
-
4882
- function getZeroSize() {
4883
- var size = {
4884
- width: 0,
4885
- height: 0,
4886
- innerWidth: 0,
4887
- innerHeight: 0,
4888
- outerWidth: 0,
4889
- outerHeight: 0
4890
- };
4891
- for ( var i=0; i < measurementsLength; i++ ) {
4892
- var measurement = measurements[i];
4893
- size[ measurement ] = 0;
4894
- }
4895
- return size;
4896
- }
4897
-
4898
- // -------------------------- getStyle -------------------------- //
4899
-
4900
- /**
4901
- * getStyle, get style of element, check for Firefox bug
4902
- * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
4903
- */
4904
- function getStyle( elem ) {
4905
- var style = getComputedStyle( elem );
4906
- if ( !style ) {
4907
- logError( 'Style returned ' + style +
4908
- '. Are you running this code in a hidden iframe on Firefox? ' +
4909
- 'See http://bit.ly/getsizebug1' );
4910
- }
4911
- return style;
4912
- }
4913
-
4914
- // -------------------------- setup -------------------------- //
4915
-
4916
- var isSetup = false;
4917
-
4918
- var isBoxSizeOuter;
4919
-
4920
- /**
4921
- * setup
4922
- * check isBoxSizerOuter
4923
- * do on first getSize() rather than on page load for Firefox bug
4924
- */
4925
- function setup() {
4926
- // setup once
4927
- if ( isSetup ) {
4928
- return;
4929
- }
4930
- isSetup = true;
4931
-
4932
- // -------------------------- box sizing -------------------------- //
4933
-
4934
- /**
4935
- * WebKit measures the outer-width on style.width on border-box elems
4936
- * IE & Firefox<29 measures the inner-width
4937
- */
4938
- var div = document.createElement('div');
4939
- div.style.width = '200px';
4940
- div.style.padding = '1px 2px 3px 4px';
4941
- div.style.borderStyle = 'solid';
4942
- div.style.borderWidth = '1px 2px 3px 4px';
4943
- div.style.boxSizing = 'border-box';
4944
-
4945
- var body = document.body || document.documentElement;
4946
- body.appendChild( div );
4947
- var style = getStyle( div );
4948
-
4949
- getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200;
4950
- body.removeChild( div );
4951
-
4952
- }
4953
-
4954
- // -------------------------- getSize -------------------------- //
4955
-
4956
- function getSize( elem ) {
4957
- setup();
4958
-
4959
- // use querySeletor if elem is string
4960
- if ( typeof elem == 'string' ) {
4961
- elem = document.querySelector( elem );
4962
- }
4963
-
4964
- // do not proceed on non-objects
4965
- if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
4966
- return;
4967
- }
4968
-
4969
- var style = getStyle( elem );
4970
-
4971
- // if hidden, everything is 0
4972
- if ( style.display == 'none' ) {
4973
- return getZeroSize();
4974
- }
4975
-
4976
- var size = {};
4977
- size.width = elem.offsetWidth;
4978
- size.height = elem.offsetHeight;
4979
-
4980
- var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
4981
-
4982
- // get all measurements
4983
- for ( var i=0; i < measurementsLength; i++ ) {
4984
- var measurement = measurements[i];
4985
- var value = style[ measurement ];
4986
- var num = parseFloat( value );
4987
- // any 'auto', 'medium' value will be 0
4988
- size[ measurement ] = !isNaN( num ) ? num : 0;
4989
- }
4990
-
4991
- var paddingWidth = size.paddingLeft + size.paddingRight;
4992
- var paddingHeight = size.paddingTop + size.paddingBottom;
4993
- var marginWidth = size.marginLeft + size.marginRight;
4994
- var marginHeight = size.marginTop + size.marginBottom;
4995
- var borderWidth = size.borderLeftWidth + size.borderRightWidth;
4996
- var borderHeight = size.borderTopWidth + size.borderBottomWidth;
4997
-
4998
- var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
4999
-
5000
- // overwrite width and height if we can get it from style
5001
- var styleWidth = getStyleSize( style.width );
5002
- if ( styleWidth !== false ) {
5003
- size.width = styleWidth +
5004
- // add padding and border unless it's already including it
5005
- ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
5006
- }
5007
-
5008
- var styleHeight = getStyleSize( style.height );
5009
- if ( styleHeight !== false ) {
5010
- size.height = styleHeight +
5011
- // add padding and border unless it's already including it
5012
- ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
5013
- }
5014
-
5015
- size.innerWidth = size.width - ( paddingWidth + borderWidth );
5016
- size.innerHeight = size.height - ( paddingHeight + borderHeight );
5017
-
5018
- size.outerWidth = size.width + marginWidth;
5019
- size.outerHeight = size.height + marginHeight;
5020
-
5021
- return size;
5022
- }
5023
-
5024
- return getSize;
5025
-
5026
- });
5027
-
5028
- /**
5029
- * matchesSelector v2.0.1
5030
- * matchesSelector( element, '.selector' )
5031
- * MIT license
5032
- */
5033
-
5034
- /*jshint browser: true, strict: true, undef: true, unused: true */
5035
-
5036
- ( function( window, factory ) {
5037
- /*global define: false, module: false */
5038
- 'use strict';
5039
- // universal module definition
5040
- if ( typeof define == 'function' && define.amd ) {
5041
- // AMD
5042
- define( 'desandro-matches-selector/matches-selector',factory );
5043
- } else if ( typeof module == 'object' && module.exports ) {
5044
- // CommonJS
5045
- module.exports = factory();
5046
- } else {
5047
- // browser global
5048
- window.matchesSelector = factory();
5049
- }
5050
-
5051
- }( window, function factory() {
5052
- 'use strict';
5053
-
5054
- var matchesMethod = ( function() {
5055
- var ElemProto = Element.prototype;
5056
- // check for the standard method name first
5057
- if ( ElemProto.matches ) {
5058
- return 'matches';
5059
- }
5060
- // check un-prefixed
5061
- if ( ElemProto.matchesSelector ) {
5062
- return 'matchesSelector';
5063
- }
5064
- // check vendor prefixes
5065
- var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
5066
-
5067
- for ( var i=0; i < prefixes.length; i++ ) {
5068
- var prefix = prefixes[i];
5069
- var method = prefix + 'MatchesSelector';
5070
- if ( ElemProto[ method ] ) {
5071
- return method;
5072
- }
5073
- }
5074
- })();
5075
-
5076
- return function matchesSelector( elem, selector ) {
5077
- return elem[ matchesMethod ]( selector );
5078
- };
5079
-
5080
- }));
5081
-
5082
- /**
5083
- * Fizzy UI utils v2.0.1
5084
- * MIT license
5085
- */
5086
-
5087
- /*jshint browser: true, undef: true, unused: true, strict: true */
5088
-
5089
- ( function( window, factory ) {
5090
- // universal module definition
5091
- /*jshint strict: false */ /*globals define, module, require */
5092
-
5093
- if ( typeof define == 'function' && define.amd ) {
5094
- // AMD
5095
- define( 'fizzy-ui-utils/utils',[
5096
- 'desandro-matches-selector/matches-selector'
5097
- ], function( matchesSelector ) {
5098
- return factory( window, matchesSelector );
5099
- });
5100
- } else if ( typeof module == 'object' && module.exports ) {
5101
- // CommonJS
5102
- module.exports = factory(
5103
- window,
5104
- require('desandro-matches-selector')
5105
- );
5106
- } else {
5107
- // browser global
5108
- window.fizzyUIUtils = factory(
5109
- window,
5110
- window.matchesSelector
5111
- );
5112
- }
5113
-
5114
- }( window, function factory( window, matchesSelector ) {
5115
-
5116
-
5117
-
5118
- var utils = {};
5119
-
5120
- // ----- extend ----- //
5121
-
5122
- // extends objects
5123
- utils.extend = function( a, b ) {
5124
- for ( var prop in b ) {
5125
- a[ prop ] = b[ prop ];
5126
- }
5127
- return a;
5128
- };
5129
-
5130
- // ----- modulo ----- //
5131
-
5132
- utils.modulo = function( num, div ) {
5133
- return ( ( num % div ) + div ) % div;
5134
- };
5135
-
5136
- // ----- makeArray ----- //
5137
-
5138
- // turn element or nodeList into an array
5139
- utils.makeArray = function( obj ) {
5140
- var ary = [];
5141
- if ( Array.isArray( obj ) ) {
5142
- // use object if already an array
5143
- ary = obj;
5144
- } else if ( obj && typeof obj.length == 'number' ) {
5145
- // convert nodeList to array
5146
- for ( var i=0; i < obj.length; i++ ) {
5147
- ary.push( obj[i] );
5148
- }
5149
- } else {
5150
- // array of single index
5151
- ary.push( obj );
5152
- }
5153
- return ary;
5154
- };
5155
-
5156
- // ----- removeFrom ----- //
5157
-
5158
- utils.removeFrom = function( ary, obj ) {
5159
- var index = ary.indexOf( obj );
5160
- if ( index != -1 ) {
5161
- ary.splice( index, 1 );
5162
- }
5163
- };
5164
-
5165
- // ----- getParent ----- //
5166
-
5167
- utils.getParent = function( elem, selector ) {
5168
- while ( elem != document.body ) {
5169
- elem = elem.parentNode;
5170
- if ( matchesSelector( elem, selector ) ) {
5171
- return elem;
5172
- }
5173
- }
5174
- };
5175
-
5176
- // ----- getQueryElement ----- //
5177
-
5178
- // use element as selector string
5179
- utils.getQueryElement = function( elem ) {
5180
- if ( typeof elem == 'string' ) {
5181
- return document.querySelector( elem );
5182
- }
5183
- return elem;
5184
- };
5185
-
5186
- // ----- handleEvent ----- //
5187
-
5188
- // enable .ontype to trigger from .addEventListener( elem, 'type' )
5189
- utils.handleEvent = function( event ) {
5190
- var method = 'on' + event.type;
5191
- if ( this[ method ] ) {
5192
- this[ method ]( event );
5193
- }
5194
- };
5195
-
5196
- // ----- filterFindElements ----- //
5197
-
5198
- utils.filterFindElements = function( elems, selector ) {
5199
- // make array of elems
5200
- elems = utils.makeArray( elems );
5201
- var ffElems = [];
5202
-
5203
- elems.forEach( function( elem ) {
5204
- // check that elem is an actual element
5205
- if ( !( elem instanceof HTMLElement ) ) {
5206
- return;
5207
- }
5208
- // add elem if no selector
5209
- if ( !selector ) {
5210
- ffElems.push( elem );
5211
- return;
5212
- }
5213
- // filter & find items if we have a selector
5214
- // filter
5215
- if ( matchesSelector( elem, selector ) ) {
5216
- ffElems.push( elem );
5217
- }
5218
- // find children
5219
- var childElems = elem.querySelectorAll( selector );
5220
- // concat childElems to filterFound array
5221
- for ( var i=0; i < childElems.length; i++ ) {
5222
- ffElems.push( childElems[i] );
5223
- }
5224
- });
5225
-
5226
- return ffElems;
5227
- };
5228
-
5229
- // ----- debounceMethod ----- //
5230
-
5231
- utils.debounceMethod = function( _class, methodName, threshold ) {
5232
- // original method
5233
- var method = _class.prototype[ methodName ];
5234
- var timeoutName = methodName + 'Timeout';
5235
-
5236
- _class.prototype[ methodName ] = function() {
5237
- var timeout = this[ timeoutName ];
5238
- if ( timeout ) {
5239
- clearTimeout( timeout );
5240
- }
5241
- var args = arguments;
5242
-
5243
- var _this = this;
5244
- this[ timeoutName ] = setTimeout( function() {
5245
- method.apply( _this, args );
5246
- delete _this[ timeoutName ];
5247
- }, threshold || 100 );
5248
- };
5249
- };
5250
-
5251
- // ----- docReady ----- //
5252
-
5253
- utils.docReady = function( callback ) {
5254
- if ( document.readyState == 'complete' ) {
5255
- callback();
5256
- } else {
5257
- document.addEventListener( 'DOMContentLoaded', callback );
5258
- }
5259
- };
5260
-
5261
- // ----- htmlInit ----- //
5262
-
5263
- // http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
5264
- utils.toDashed = function( str ) {
5265
- return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
5266
- return $1 + '-' + $2;
5267
- }).toLowerCase();
5268
- };
5269
-
5270
- var console = window.console;
5271
- /**
5272
- * allow user to initialize classes via [data-namespace] or .js-namespace class
5273
- * htmlInit( Widget, 'widgetName' )
5274
- * options are parsed from data-namespace-options
5275
- */
5276
- utils.htmlInit = function( WidgetClass, namespace ) {
5277
- utils.docReady( function() {
5278
- var dashedNamespace = utils.toDashed( namespace );
5279
- var dataAttr = 'data-' + dashedNamespace;
5280
- var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
5281
- var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
5282
- var elems = utils.makeArray( dataAttrElems )
5283
- .concat( utils.makeArray( jsDashElems ) );
5284
- var dataOptionsAttr = dataAttr + '-options';
5285
- var jQuery = window.jQuery;
5286
-
5287
- elems.forEach( function( elem ) {
5288
- var attr = elem.getAttribute( dataAttr ) ||
5289
- elem.getAttribute( dataOptionsAttr );
5290
- var options;
5291
- try {
5292
- options = attr && JSON.parse( attr );
5293
- } catch ( error ) {
5294
- // log error, do not initialize
5295
- if ( console ) {
5296
- console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
5297
- ': ' + error );
5298
- }
5299
- return;
5300
- }
5301
- // initialize
5302
- var instance = new WidgetClass( elem, options );
5303
- // make available via $().data('layoutname')
5304
- if ( jQuery ) {
5305
- jQuery.data( elem, namespace, instance );
5306
- }
5307
- });
5308
-
5309
- });
5310
- };
5311
-
5312
- // ----- ----- //
5313
-
5314
- return utils;
5315
-
5316
- }));
5317
-
5318
- /**
5319
- * Outlayer Item
5320
- */
5321
-
5322
- ( function( window, factory ) {
5323
- // universal module definition
5324
- /* jshint strict: false */ /* globals define, module, require */
5325
- if ( typeof define == 'function' && define.amd ) {
5326
- // AMD - RequireJS
5327
- define( 'outlayer/item',[
5328
- 'ev-emitter/ev-emitter',
5329
- 'get-size/get-size'
5330
- ],
5331
- factory
5332
- );
5333
- } else if ( typeof module == 'object' && module.exports ) {
5334
- // CommonJS - Browserify, Webpack
5335
- module.exports = factory(
5336
- require('ev-emitter'),
5337
- require('get-size')
5338
- );
5339
- } else {
5340
- // browser global
5341
- window.Outlayer = {};
5342
- window.Outlayer.Item = factory(
5343
- window.EvEmitter,
5344
- window.getSize
5345
- );
5346
- }
5347
-
5348
- }( window, function factory( EvEmitter, getSize ) {
5349
- 'use strict';
5350
-
5351
- // ----- helpers ----- //
5352
-
5353
- function isEmptyObj( obj ) {
5354
- for ( var prop in obj ) {
5355
- return false;
5356
- }
5357
- prop = null;
5358
- return true;
5359
- }
5360
-
5361
- // -------------------------- CSS3 support -------------------------- //
5362
-
5363
-
5364
- var docElemStyle = document.documentElement.style;
5365
-
5366
- var transitionProperty = typeof docElemStyle.transition == 'string' ?
5367
- 'transition' : 'WebkitTransition';
5368
- var transformProperty = typeof docElemStyle.transform == 'string' ?
5369
- 'transform' : 'WebkitTransform';
5370
-
5371
- var transitionEndEvent = {
5372
- WebkitTransition: 'webkitTransitionEnd',
5373
- transition: 'transitionend'
5374
- }[ transitionProperty ];
5375
-
5376
- // cache all vendor properties that could have vendor prefix
5377
- var vendorProperties = {
5378
- transform: transformProperty,
5379
- transition: transitionProperty,
5380
- transitionDuration: transitionProperty + 'Duration',
5381
- transitionProperty: transitionProperty + 'Property',
5382
- transitionDelay: transitionProperty + 'Delay'
5383
- };
5384
-
5385
- // -------------------------- Item -------------------------- //
5386
-
5387
- function Item( element, layout ) {
5388
- if ( !element ) {
5389
- return;
5390
- }
5391
-
5392
- this.element = element;
5393
- // parent layout class, i.e. Masonry, Enviratope, or Packery
5394
- this.layout = layout;
5395
- this.position = {
5396
- x: 0,
5397
- y: 0
5398
- };
5399
-
5400
- this._create();
5401
- }
5402
-
5403
- // inherit EvEmitter
5404
- var proto = Item.prototype = Object.create( EvEmitter.prototype );
5405
- proto.constructor = Item;
5406
-
5407
- proto._create = function() {
5408
- // transition objects
5409
- this._transn = {
5410
- ingProperties: {},
5411
- clean: {},
5412
- onEnd: {}
5413
- };
5414
-
5415
- this.css({
5416
- position: 'absolute'
5417
- });
5418
- };
5419
-
5420
- // trigger specified handler for event type
5421
- proto.handleEvent = function( event ) {
5422
- var method = 'on' + event.type;
5423
- if ( this[ method ] ) {
5424
- this[ method ]( event );
5425
- }
5426
- };
5427
-
5428
- proto.getSize = function() {
5429
- this.size = getSize( this.element );
5430
- };
5431
-
5432
- /**
5433
- * apply CSS styles to element
5434
- * @param {Object} style
5435
- */
5436
- proto.css = function( style ) {
5437
- var elemStyle = this.element.style;
5438
-
5439
- for ( var prop in style ) {
5440
- // use vendor property if available
5441
- var supportedProp = vendorProperties[ prop ] || prop;
5442
- elemStyle[ supportedProp ] = style[ prop ];
5443
- }
5444
- };
5445
-
5446
- // measure position, and sets it
5447
- proto.getPosition = function() {
5448
- var style = getComputedStyle( this.element );
5449
- var isOriginLeft = this.layout._getOption('originLeft');
5450
- var isOriginTop = this.layout._getOption('originTop');
5451
- var xValue = style[ isOriginLeft ? 'left' : 'right' ];
5452
- var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
5453
- // convert percent to pixels
5454
- var layoutSize = this.layout.size;
5455
- var x = xValue.indexOf('%') != -1 ?
5456
- ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );
5457
- var y = yValue.indexOf('%') != -1 ?
5458
- ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );
5459
-
5460
- // clean up 'auto' or other non-integer values
5461
- x = isNaN( x ) ? 0 : x;
5462
- y = isNaN( y ) ? 0 : y;
5463
- // remove padding from measurement
5464
- x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
5465
- y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
5466
-
5467
- this.position.x = x;
5468
- this.position.y = y;
5469
- };
5470
-
5471
- // set settled position, apply padding
5472
- proto.layoutPosition = function() {
5473
- var layoutSize = this.layout.size;
5474
- var style = {};
5475
- var isOriginLeft = this.layout._getOption('originLeft');
5476
- var isOriginTop = this.layout._getOption('originTop');
5477
-
5478
- // x
5479
- var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
5480
- var xProperty = isOriginLeft ? 'left' : 'right';
5481
- var xResetProperty = isOriginLeft ? 'right' : 'left';
5482
-
5483
- var x = this.position.x + layoutSize[ xPadding ];
5484
- // set in percentage or pixels
5485
- style[ xProperty ] = this.getXValue( x );
5486
- // reset other property
5487
- style[ xResetProperty ] = '';
5488
-
5489
- // y
5490
- var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
5491
- var yProperty = isOriginTop ? 'top' : 'bottom';
5492
- var yResetProperty = isOriginTop ? 'bottom' : 'top';
5493
-
5494
- var y = this.position.y + layoutSize[ yPadding ];
5495
- // set in percentage or pixels
5496
- style[ yProperty ] = this.getYValue( y );
5497
- // reset other property
5498
- style[ yResetProperty ] = '';
5499
-
5500
- this.css( style );
5501
- this.emitEvent( 'layout', [ this ] );
5502
- };
5503
-
5504
- proto.getXValue = function( x ) {
5505
- var isHorizontal = this.layout._getOption('horizontal');
5506
- return this.layout.options.percentPosition && !isHorizontal ?
5507
- ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
5508
- };
5509
-
5510
- proto.getYValue = function( y ) {
5511
- var isHorizontal = this.layout._getOption('horizontal');
5512
- return this.layout.options.percentPosition && isHorizontal ?
5513
- ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
5514
- };
5515
-
5516
- proto._transitionTo = function( x, y ) {
5517
- this.getPosition();
5518
- // get current x & y from top/left
5519
- var curX = this.position.x;
5520
- var curY = this.position.y;
5521
-
5522
- var compareX = parseInt( x, 10 );
5523
- var compareY = parseInt( y, 10 );
5524
- var didNotMove = compareX === this.position.x && compareY === this.position.y;
5525
-
5526
- // save end position
5527
- this.setPosition( x, y );
5528
-
5529
- // if did not move and not transitioning, just go to layout
5530
- if ( didNotMove && !this.isTransitioning ) {
5531
- this.layoutPosition();
5532
- return;
5533
- }
5534
-
5535
- var transX = x - curX;
5536
- var transY = y - curY;
5537
- var transitionStyle = {};
5538
- transitionStyle.transform = this.getTranslate( transX, transY );
5539
-
5540
- this.transition({
5541
- to: transitionStyle,
5542
- onTransitionEnd: {
5543
- transform: this.layoutPosition
5544
- },
5545
- isCleaning: true
5546
- });
5547
- };
5548
-
5549
- proto.getTranslate = function( x, y ) {
5550
- // flip cooridinates if origin on right or bottom
5551
- var isOriginLeft = this.layout._getOption('originLeft');
5552
- var isOriginTop = this.layout._getOption('originTop');
5553
- x = isOriginLeft ? x : -x;
5554
- y = isOriginTop ? y : -y;
5555
- return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
5556
- };
5557
-
5558
- // non transition + transform support
5559
- proto.goTo = function( x, y ) {
5560
- this.setPosition( x, y );
5561
- this.layoutPosition();
5562
- };
5563
-
5564
- proto.moveTo = proto._transitionTo;
5565
-
5566
- proto.setPosition = function( x, y ) {
5567
- this.position.x = parseInt( x, 10 );
5568
- this.position.y = parseInt( y, 10 );
5569
- };
5570
-
5571
- // ----- transition ----- //
5572
-
5573
- /**
5574
- * @param {Object} style - CSS
5575
- * @param {Function} onTransitionEnd
5576
- */
5577
-
5578
- // non transition, just trigger callback
5579
- proto._nonTransition = function( args ) {
5580
- this.css( args.to );
5581
- if ( args.isCleaning ) {
5582
- this._removeStyles( args.to );
5583
- }
5584
- for ( var prop in args.onTransitionEnd ) {
5585
- args.onTransitionEnd[ prop ].call( this );
5586
- }
5587
- };
5588
-
5589
- /**
5590
- * proper transition
5591
- * @param {Object} args - arguments
5592
- * @param {Object} to - style to transition to
5593
- * @param {Object} from - style to start transition from
5594
- * @param {Boolean} isCleaning - removes transition styles after transition
5595
- * @param {Function} onTransitionEnd - callback
5596
- */
5597
- proto.transition = function( args ) {
5598
- // redirect to nonTransition if no transition duration
5599
- if ( !parseFloat( this.layout.options.transitionDuration ) ) {
5600
- this._nonTransition( args );
5601
- return;
5602
- }
5603
-
5604
- var _transition = this._transn;
5605
- // keep track of onTransitionEnd callback by css property
5606
- for ( var prop in args.onTransitionEnd ) {
5607
- _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
5608
- }
5609
- // keep track of properties that are transitioning
5610
- for ( prop in args.to ) {
5611
- _transition.ingProperties[ prop ] = true;
5612
- // keep track of properties to clean up when transition is done
5613
- if ( args.isCleaning ) {
5614
- _transition.clean[ prop ] = true;
5615
- }
5616
- }
5617
-
5618
- // set from styles
5619
- if ( args.from ) {
5620
- this.css( args.from );
5621
- // force redraw. http://blog.alexmaccaw.com/css-transitions
5622
- var h = this.element.offsetHeight;
5623
- // hack for JSHint to hush about unused var
5624
- h = null;
5625
- }
5626
- // enable transition
5627
- this.enableTransition( args.to );
5628
- // set styles that are transitioning
5629
- this.css( args.to );
5630
-
5631
- this.isTransitioning = true;
5632
-
5633
- };
5634
-
5635
- // dash before all cap letters, including first for
5636
- // WebkitTransform => -webkit-transform
5637
- function toDashedAll( str ) {
5638
- return str.replace( /([A-Z])/g, function( $1 ) {
5639
- return '-' + $1.toLowerCase();
5640
- });
5641
- }
5642
-
5643
- var transitionProps = 'opacity,' + toDashedAll( transformProperty );
5644
-
5645
- proto.enableTransition = function(/* style */) {
5646
- // HACK changing transitionProperty during a transition
5647
- // will cause transition to jump
5648
- if ( this.isTransitioning ) {
5649
- return;
5650
- }
5651
-
5652
- // make `transition: foo, bar, baz` from style object
5653
- // HACK un-comment this when enableTransition can work
5654
- // while a transition is happening
5655
- // var transitionValues = [];
5656
- // for ( var prop in style ) {
5657
- // // dash-ify camelCased properties like WebkitTransition
5658
- // prop = vendorProperties[ prop ] || prop;
5659
- // transitionValues.push( toDashedAll( prop ) );
5660
- // }
5661
- // munge number to millisecond, to match stagger
5662
- var duration = this.layout.options.transitionDuration;
5663
- duration = typeof duration == 'number' ? duration + 'ms' : duration;
5664
- // enable transition styles
5665
- this.css({
5666
- transitionProperty: transitionProps,
5667
- transitionDuration: duration,
5668
- transitionDelay: this.staggerDelay || 0
5669
- });
5670
- // listen for transition end event
5671
- this.element.addEventListener( transitionEndEvent, this, false );
5672
- };
5673
-
5674
- // ----- events ----- //
5675
-
5676
- proto.onwebkitTransitionEnd = function( event ) {
5677
- this.ontransitionend( event );
5678
- };
5679
-
5680
- proto.onotransitionend = function( event ) {
5681
- this.ontransitionend( event );
5682
- };
5683
-
5684
- // properties that I munge to make my life easier
5685
- var dashedVendorProperties = {
5686
- '-webkit-transform': 'transform'
5687
- };
5688
-
5689
- proto.ontransitionend = function( event ) {
5690
- // disregard bubbled events from children
5691
- if ( event.target !== this.element ) {
5692
- return;
5693
- }
5694
- var _transition = this._transn;
5695
- // get property name of transitioned property, convert to prefix-free
5696
- var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
5697
-
5698
- // remove property that has completed transitioning
5699
- delete _transition.ingProperties[ propertyName ];
5700
- // check if any properties are still transitioning
5701
- if ( isEmptyObj( _transition.ingProperties ) ) {
5702
- // all properties have completed transitioning
5703
- this.disableTransition();
5704
- }
5705
- // clean style
5706
- if ( propertyName in _transition.clean ) {
5707
- // clean up style
5708
- this.element.style[ event.propertyName ] = '';
5709
- delete _transition.clean[ propertyName ];
5710
- }
5711
- // trigger onTransitionEnd callback
5712
- if ( propertyName in _transition.onEnd ) {
5713
- var onTransitionEnd = _transition.onEnd[ propertyName ];
5714
- onTransitionEnd.call( this );
5715
- delete _transition.onEnd[ propertyName ];
5716
- }
5717
-
5718
- this.emitEvent( 'transitionEnd', [ this ] );
5719
- };
5720
-
5721
- proto.disableTransition = function() {
5722
- this.removeTransitionStyles();
5723
- this.element.removeEventListener( transitionEndEvent, this, false );
5724
- this.isTransitioning = false;
5725
- };
5726
-
5727
- /**
5728
- * removes style property from element
5729
- * @param {Object} style
5730
- **/
5731
- proto._removeStyles = function( style ) {
5732
- // clean up transition styles
5733
- var cleanStyle = {};
5734
- for ( var prop in style ) {
5735
- cleanStyle[ prop ] = '';
5736
- }
5737
- this.css( cleanStyle );
5738
- };
5739
-
5740
- var cleanTransitionStyle = {
5741
- transitionProperty: '',
5742
- transitionDuration: '',
5743
- transitionDelay: ''
5744
- };
5745
-
5746
- proto.removeTransitionStyles = function() {
5747
- // remove transition
5748
- this.css( cleanTransitionStyle );
5749
- };
5750
-
5751
- // ----- stagger ----- //
5752
-
5753
- proto.stagger = function( delay ) {
5754
- delay = isNaN( delay ) ? 0 : delay;
5755
- this.staggerDelay = delay + 'ms';
5756
- };
5757
-
5758
- // ----- show/hide/remove ----- //
5759
-
5760
- // remove element from DOM
5761
- proto.removeElem = function() {
5762
- this.element.parentNode.removeChild( this.element );
5763
- // remove display: none
5764
- this.css({ display: '' });
5765
- this.emitEvent( 'remove', [ this ] );
5766
- };
5767
-
5768
- proto.remove = function() {
5769
- // just remove element if no transition support or no transition
5770
- if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
5771
- this.removeElem();
5772
- return;
5773
- }
5774
-
5775
- // start transition
5776
- this.once( 'transitionEnd', function() {
5777
- this.removeElem();
5778
- });
5779
- this.hide();
5780
- };
5781
-
5782
- proto.reveal = function() {
5783
- delete this.isHidden;
5784
- // remove display: none
5785
- this.css({ display: '' });
5786
-
5787
- var options = this.layout.options;
5788
-
5789
- var onTransitionEnd = {};
5790
- var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
5791
- onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
5792
-
5793
- this.transition({
5794
- from: options.hiddenStyle,
5795
- to: options.visibleStyle,
5796
- isCleaning: true,
5797
- onTransitionEnd: onTransitionEnd
5798
- });
5799
- };
5800
-
5801
- proto.onRevealTransitionEnd = function() {
5802
- // check if still visible
5803
- // during transition, item may have been hidden
5804
- if ( !this.isHidden ) {
5805
- this.emitEvent('reveal');
5806
- }
5807
- };
5808
-
5809
- /**
5810
- * get style property use for hide/reveal transition end
5811
- * @param {String} styleProperty - hiddenStyle/visibleStyle
5812
- * @returns {String}
5813
- */
5814
- proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
5815
- var optionStyle = this.layout.options[ styleProperty ];
5816
- // use opacity
5817
- if ( optionStyle.opacity ) {
5818
- return 'opacity';
5819
- }
5820
- // get first property
5821
- for ( var prop in optionStyle ) {
5822
- return prop;
5823
- }
5824
- };
5825
-
5826
- proto.hide = function() {
5827
- // set flag
5828
- this.isHidden = true;
5829
- // remove display: none
5830
- this.css({ display: '' });
5831
-
5832
- var options = this.layout.options;
5833
-
5834
- var onTransitionEnd = {};
5835
- var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
5836
- onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
5837
-
5838
- this.transition({
5839
- from: options.visibleStyle,
5840
- to: options.hiddenStyle,
5841
- // keep hidden stuff hidden
5842
- isCleaning: true,
5843
- onTransitionEnd: onTransitionEnd
5844
- });
5845
- };
5846
-
5847
- proto.onHideTransitionEnd = function() {
5848
- // check if still hidden
5849
- // during transition, item may have been un-hidden
5850
- if ( this.isHidden ) {
5851
- this.css({ display: 'none' });
5852
- this.emitEvent('hide');
5853
- }
5854
- };
5855
-
5856
- proto.destroy = function() {
5857
- this.css({
5858
- position: '',
5859
- left: '',
5860
- right: '',
5861
- top: '',
5862
- bottom: '',
5863
- transition: '',
5864
- transform: ''
5865
- });
5866
- };
5867
-
5868
- return Item;
5869
-
5870
- }));
5871
-
5872
- /*!
5873
- * Outlayer v2.1.0
5874
- * the brains and guts of a layout library
5875
- * MIT license
5876
- */
5877
-
5878
- ( function( window, factory ) {
5879
- 'use strict';
5880
- // universal module definition
5881
- /* jshint strict: false */ /* globals define, module, require */
5882
- if ( typeof define == 'function' && define.amd ) {
5883
- // AMD - RequireJS
5884
- define( 'outlayer/outlayer',[
5885
- 'ev-emitter/ev-emitter',
5886
- 'get-size/get-size',
5887
- 'fizzy-ui-utils/utils',
5888
- './item'
5889
- ],
5890
- function( EvEmitter, getSize, utils, Item ) {
5891
- return factory( window, EvEmitter, getSize, utils, Item);
5892
- }
5893
- );
5894
- } else if ( typeof module == 'object' && module.exports ) {
5895
- // CommonJS - Browserify, Webpack
5896
- module.exports = factory(
5897
- window,
5898
- require('ev-emitter'),
5899
- require('get-size'),
5900
- require('fizzy-ui-utils'),
5901
- require('./item')
5902
- );
5903
- } else {
5904
- // browser global
5905
- window.Outlayer = factory(
5906
- window,
5907
- window.EvEmitter,
5908
- window.getSize,
5909
- window.fizzyUIUtils,
5910
- window.Outlayer.Item
5911
- );
5912
- }
5913
-
5914
- }( window, function factory( window, EvEmitter, getSize, utils, Item ) {
5915
- 'use strict';
5916
-
5917
- // ----- vars ----- //
5918
-
5919
- var console = window.console;
5920
- var jQuery = window.jQuery;
5921
- var noop = function() {};
5922
-
5923
- // -------------------------- Outlayer -------------------------- //
5924
-
5925
- // globally unique identifiers
5926
- var GUID = 0;
5927
- // internal store of all Outlayer intances
5928
- var instances = {};
5929
-
5930
-
5931
- /**
5932
- * @param {Element, String} element
5933
- * @param {Object} options
5934
- * @constructor
5935
- */
5936
- function Outlayer( element, options ) {
5937
- var queryElement = utils.getQueryElement( element );
5938
- if ( !queryElement ) {
5939
- if ( console ) {
5940
- console.error( 'Bad element for ' + this.constructor.namespace +
5941
- ': ' + ( queryElement || element ) );
5942
- }
5943
- return;
5944
- }
5945
- this.element = queryElement;
5946
- // add jQuery
5947
- if ( jQuery ) {
5948
- this.$element = jQuery( this.element );
5949
- }
5950
-
5951
- // options
5952
- this.options = utils.extend( {}, this.constructor.defaults );
5953
- this.option( options );
5954
-
5955
- // add id for Outlayer.getFromElement
5956
- var id = ++GUID;
5957
- this.element.outlayerGUID = id; // expando
5958
- instances[ id ] = this; // associate via id
5959
-
5960
- // kick it off
5961
- this._create();
5962
-
5963
- var isInitLayout = this._getOption('initLayout');
5964
- if ( isInitLayout ) {
5965
- this.layout();
5966
- }
5967
- }
5968
-
5969
- // settings are for internal use only
5970
- Outlayer.namespace = 'outlayer';
5971
- Outlayer.Item = Item;
5972
-
5973
- // default options
5974
- Outlayer.defaults = {
5975
- containerStyle: {
5976
- position: 'relative'
5977
- },
5978
- initLayout: true,
5979
- originLeft: true,
5980
- originTop: true,
5981
- resize: true,
5982
- resizeContainer: true,
5983
- // item options
5984
- transitionDuration: '0.4s',
5985
- hiddenStyle: {
5986
- opacity: 0,
5987
- transform: 'scale(0.001)'
5988
- },
5989
- visibleStyle: {
5990
- opacity: 1,
5991
- transform: 'scale(1)'
5992
- }
5993
- };
5994
-
5995
- var proto = Outlayer.prototype;
5996
- // inherit EvEmitter
5997
- utils.extend( proto, EvEmitter.prototype );
5998
-
5999
- /**
6000
- * set options
6001
- * @param {Object} opts
6002
- */
6003
- proto.option = function( opts ) {
6004
- utils.extend( this.options, opts );
6005
- };
6006
-
6007
- /**
6008
- * get backwards compatible option value, check old name
6009
- */
6010
- proto._getOption = function( option ) {
6011
- var oldOption = this.constructor.compatOptions[ option ];
6012
- return oldOption && this.options[ oldOption ] !== undefined ?
6013
- this.options[ oldOption ] : this.options[ option ];
6014
- };
6015
-
6016
- Outlayer.compatOptions = {
6017
- // currentName: oldName
6018
- initLayout: 'isInitLayout',
6019
- horizontal: 'isHorizontal',
6020
- layoutInstant: 'isLayoutInstant',
6021
- originLeft: 'isOriginLeft',
6022
- originTop: 'isOriginTop',
6023
- resize: 'isResizeBound',
6024
- resizeContainer: 'isResizingContainer'
6025
- };
6026
-
6027
- proto._create = function() {
6028
- // get items from children
6029
- this.reloadItems();
6030
- // elements that affect layout, but are not laid out
6031
- this.stamps = [];
6032
- this.stamp( this.options.stamp );
6033
- // set container style
6034
- utils.extend( this.element.style, this.options.containerStyle );
6035
-
6036
- // bind resize method
6037
- var canBindResize = this._getOption('resize');
6038
- if ( canBindResize ) {
6039
- this.bindResize();
6040
- }
6041
- };
6042
-
6043
- // goes through all children again and gets bricks in proper order
6044
- proto.reloadItems = function() {
6045
- // collection of item elements
6046
- this.items = this._itemize( this.element.children );
6047
- };
6048
-
6049
-
6050
- /**
6051
- * turn elements into Outlayer.Items to be used in layout
6052
- * @param {Array or NodeList or HTMLElement} elems
6053
- * @returns {Array} items - collection of new Outlayer Items
6054
- */
6055
- proto._itemize = function( elems ) {
6056
-
6057
- var itemElems = this._filterFindItemElements( elems );
6058
- var Item = this.constructor.Item;
6059
-
6060
- // create new Outlayer Items for collection
6061
- var items = [];
6062
- for ( var i=0; i < itemElems.length; i++ ) {
6063
- var elem = itemElems[i];
6064
- var item = new Item( elem, this );
6065
- items.push( item );
6066
- }
6067
-
6068
- return items;
6069
- };
6070
-
6071
- /**
6072
- * get item elements to be used in layout
6073
- * @param {Array or NodeList or HTMLElement} elems
6074
- * @returns {Array} items - item elements
6075
- */
6076
- proto._filterFindItemElements = function( elems ) {
6077
- return utils.filterFindElements( elems, this.options.itemSelector );
6078
- };
6079
-
6080
- /**
6081
- * getter method for getting item elements
6082
- * @returns {Array} elems - collection of item elements
6083
- */
6084
- proto.getItemElements = function() {
6085
- return this.items.map( function( item ) {
6086
- return item.element;
6087
- });
6088
- };
6089
-
6090
- // ----- init & layout ----- //
6091
-
6092
- /**
6093
- * lays out all items
6094
- */
6095
- proto.layout = function() {
6096
- this._resetLayout();
6097
- this._manageStamps();
6098
-
6099
- // don't animate first layout
6100
- var layoutInstant = this._getOption('layoutInstant');
6101
- var isInstant = layoutInstant !== undefined ?
6102
- layoutInstant : !this._isLayoutInited;
6103
- this.layoutItems( this.items, isInstant );
6104
-
6105
- // flag for initalized
6106
- this._isLayoutInited = true;
6107
- };
6108
-
6109
- // _init is alias for layout
6110
- proto._init = proto.layout;
6111
-
6112
- /**
6113
- * logic before any new layout
6114
- */
6115
- proto._resetLayout = function() {
6116
- this.getSize();
6117
- };
6118
-
6119
-
6120
- proto.getSize = function() {
6121
- this.size = getSize( this.element );
6122
- };
6123
-
6124
- /**
6125
- * get measurement from option, for columnWidth, rowHeight, gutter
6126
- * if option is String -> get element from selector string, & get size of element
6127
- * if option is Element -> get size of element
6128
- * else use option as a number
6129
- *
6130
- * @param {String} measurement
6131
- * @param {String} size - width or height
6132
- * @private
6133
- */
6134
- proto._getMeasurement = function( measurement, size ) {
6135
- var option = this.options[ measurement ];
6136
- var elem;
6137
- if ( !option ) {
6138
- // default to 0
6139
- this[ measurement ] = 0;
6140
- } else {
6141
- // use option as an element
6142
- if ( typeof option == 'string' ) {
6143
- elem = this.element.querySelector( option );
6144
- } else if ( option instanceof HTMLElement ) {
6145
- elem = option;
6146
- }
6147
- // use size of element, if element
6148
- this[ measurement ] = elem ? getSize( elem )[ size ] : option;
6149
- }
6150
- };
6151
-
6152
- /**
6153
- * layout a collection of item elements
6154
- * @api public
6155
- */
6156
- proto.layoutItems = function( items, isInstant ) {
6157
- items = this._getItemsForLayout( items );
6158
-
6159
- this._layoutItems( items, isInstant );
6160
-
6161
- this._postLayout();
6162
- };
6163
-
6164
- /**
6165
- * get the items to be laid out
6166
- * you may want to skip over some items
6167
- * @param {Array} items
6168
- * @returns {Array} items
6169
- */
6170
- proto._getItemsForLayout = function( items ) {
6171
- return items.filter( function( item ) {
6172
- return !item.isIgnored;
6173
- });
6174
- };
6175
-
6176
- /**
6177
- * layout items
6178
- * @param {Array} items
6179
- * @param {Boolean} isInstant
6180
- */
6181
- proto._layoutItems = function( items, isInstant ) {
6182
- this._emitCompleteOnItems( 'layout', items );
6183
-
6184
- if ( !items || !items.length ) {
6185
- // no items, emit event with empty array
6186
- return;
6187
- }
6188
-
6189
- var queue = [];
6190
-
6191
- items.forEach( function( item ) {
6192
- // get x/y object from method
6193
- var position = this._getItemLayoutPosition( item );
6194
- // enqueue
6195
- position.item = item;
6196
- position.isInstant = isInstant || item.isLayoutInstant;
6197
- queue.push( position );
6198
- }, this );
6199
-
6200
- this._processLayoutQueue( queue );
6201
- };
6202
-
6203
- /**
6204
- * get item layout position
6205
- * @param {Outlayer.Item} item
6206
- * @returns {Object} x and y position
6207
- */
6208
- proto._getItemLayoutPosition = function( /* item */ ) {
6209
- return {
6210
- x: 0,
6211
- y: 0
6212
- };
6213
- };
6214
-
6215
- /**
6216
- * iterate over array and position each item
6217
- * Reason being - separating this logic prevents 'layout invalidation'
6218
- * thx @paul_irish
6219
- * @param {Array} queue
6220
- */
6221
- proto._processLayoutQueue = function( queue ) {
6222
- this.updateStagger();
6223
- queue.forEach( function( obj, i ) {
6224
- this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
6225
- }, this );
6226
- };
6227
-
6228
- // set stagger from option in milliseconds number
6229
- proto.updateStagger = function() {
6230
- var stagger = this.options.stagger;
6231
- if ( stagger === null || stagger === undefined ) {
6232
- this.stagger = 0;
6233
- return;
6234
- }
6235
- this.stagger = getMilliseconds( stagger );
6236
- return this.stagger;
6237
- };
6238
-
6239
- /**
6240
- * Sets position of item in DOM
6241
- * @param {Outlayer.Item} item
6242
- * @param {Number} x - horizontal position
6243
- * @param {Number} y - vertical position
6244
- * @param {Boolean} isInstant - disables transitions
6245
- */
6246
- proto._positionItem = function( item, x, y, isInstant, i ) {
6247
- if ( isInstant ) {
6248
- // if not transition, just set CSS
6249
- item.goTo( x, y );
6250
- } else {
6251
- item.stagger( i * this.stagger );
6252
- item.moveTo( x, y );
6253
- }
6254
- };
6255
-
6256
- /**
6257
- * Any logic you want to do after each layout,
6258
- * i.e. size the container
6259
- */
6260
- proto._postLayout = function() {
6261
- this.resizeContainer();
6262
- };
6263
-
6264
- proto.resizeContainer = function() {
6265
- var isResizingContainer = this._getOption('resizeContainer');
6266
- if ( !isResizingContainer ) {
6267
- return;
6268
- }
6269
- var size = this._getContainerSize();
6270
- if ( size ) {
6271
- this._setContainerMeasure( size.width, true );
6272
- this._setContainerMeasure( size.height, false );
6273
- }
6274
- };
6275
-
6276
- /**
6277
- * Sets width or height of container if returned
6278
- * @returns {Object} size
6279
- * @param {Number} width
6280
- * @param {Number} height
6281
- */
6282
- proto._getContainerSize = noop;
6283
-
6284
- /**
6285
- * @param {Number} measure - size of width or height
6286
- * @param {Boolean} isWidth
6287
- */
6288
- proto._setContainerMeasure = function( measure, isWidth ) {
6289
- if ( measure === undefined ) {
6290
- return;
6291
- }
6292
-
6293
- var elemSize = this.size;
6294
- // add padding and border width if border box
6295
- if ( elemSize.isBorderBox ) {
6296
- measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
6297
- elemSize.borderLeftWidth + elemSize.borderRightWidth :
6298
- elemSize.paddingBottom + elemSize.paddingTop +
6299
- elemSize.borderTopWidth + elemSize.borderBottomWidth;
6300
- }
6301
-
6302
- measure = Math.max( measure, 0 );
6303
- this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
6304
- };
6305
-
6306
- /**
6307
- * emit eventComplete on a collection of items events
6308
- * @param {String} eventName
6309
- * @param {Array} items - Outlayer.Items
6310
- */
6311
- proto._emitCompleteOnItems = function( eventName, items ) {
6312
- var _this = this;
6313
- function onComplete() {
6314
- _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
6315
- }
6316
-
6317
- var count = items.length;
6318
- if ( !items || !count ) {
6319
- onComplete();
6320
- return;
6321
- }
6322
-
6323
- var doneCount = 0;
6324
- function tick() {
6325
- doneCount++;
6326
- if ( doneCount == count ) {
6327
- onComplete();
6328
- }
6329
- }
6330
-
6331
- // bind callback
6332
- items.forEach( function( item ) {
6333
- item.once( eventName, tick );
6334
- });
6335
- };
6336
-
6337
- /**
6338
- * emits events via EvEmitter and jQuery events
6339
- * @param {String} type - name of event
6340
- * @param {Event} event - original event
6341
- * @param {Array} args - extra arguments
6342
- */
6343
- proto.dispatchEvent = function( type, event, args ) {
6344
- // add original event to arguments
6345
- var emitArgs = event ? [ event ].concat( args ) : args;
6346
- this.emitEvent( type, emitArgs );
6347
-
6348
- if ( jQuery ) {
6349
- // set this.$element
6350
- this.$element = this.$element || jQuery( this.element );
6351
- if ( event ) {
6352
- // create jQuery event
6353
- var $event = jQuery.Event( event );
6354
- $event.type = type;
6355
- this.$element.trigger( $event, args );
6356
- } else {
6357
- // just trigger with type if no event available
6358
- this.$element.trigger( type, args );
6359
- }
6360
- }
6361
- };
6362
-
6363
- // -------------------------- ignore & stamps -------------------------- //
6364
-
6365
-
6366
- /**
6367
- * keep item in collection, but do not lay it out
6368
- * ignored items do not get skipped in layout
6369
- * @param {Element} elem
6370
- */
6371
- proto.ignore = function( elem ) {
6372
- var item = this.getItem( elem );
6373
- if ( item ) {
6374
- item.isIgnored = true;
6375
- }
6376
- };
6377
-
6378
- /**
6379
- * return item to layout collection
6380
- * @param {Element} elem
6381
- */
6382
- proto.unignore = function( elem ) {
6383
- var item = this.getItem( elem );
6384
- if ( item ) {
6385
- delete item.isIgnored;
6386
- }
6387
- };
6388
-
6389
- /**
6390
- * adds elements to stamps
6391
- * @param {NodeList, Array, Element, or String} elems
6392
- */
6393
- proto.stamp = function( elems ) {
6394
- elems = this._find( elems );
6395
- if ( !elems ) {
6396
- return;
6397
- }
6398
-
6399
- this.stamps = this.stamps.concat( elems );
6400
- // ignore
6401
- elems.forEach( this.ignore, this );
6402
- };
6403
-
6404
- /**
6405
- * removes elements to stamps
6406
- * @param {NodeList, Array, or Element} elems
6407
- */
6408
- proto.unstamp = function( elems ) {
6409
- elems = this._find( elems );
6410
- if ( !elems ){
6411
- return;
6412
- }
6413
-
6414
- elems.forEach( function( elem ) {
6415
- // filter out removed stamp elements
6416
- utils.removeFrom( this.stamps, elem );
6417
- this.unignore( elem );
6418
- }, this );
6419
- };
6420
-
6421
- /**
6422
- * finds child elements
6423
- * @param {NodeList, Array, Element, or String} elems
6424
- * @returns {Array} elems
6425
- */
6426
- proto._find = function( elems ) {
6427
- if ( !elems ) {
6428
- return;
6429
- }
6430
- // if string, use argument as selector string
6431
- if ( typeof elems == 'string' ) {
6432
- elems = this.element.querySelectorAll( elems );
6433
- }
6434
- elems = utils.makeArray( elems );
6435
- return elems;
6436
- };
6437
-
6438
- proto._manageStamps = function() {
6439
- if ( !this.stamps || !this.stamps.length ) {
6440
- return;
6441
- }
6442
-
6443
- this._getBoundingRect();
6444
-
6445
- this.stamps.forEach( this._manageStamp, this );
6446
- };
6447
-
6448
- // update boundingLeft / Top
6449
- proto._getBoundingRect = function() {
6450
- // get bounding rect for container element
6451
- var boundingRect = this.element.getBoundingClientRect();
6452
- var size = this.size;
6453
- this._boundingRect = {
6454
- left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
6455
- top: boundingRect.top + size.paddingTop + size.borderTopWidth,
6456
- right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
6457
- bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
6458
- };
6459
- };
6460
-
6461
- /**
6462
- * @param {Element} stamp
6463
- **/
6464
- proto._manageStamp = noop;
6465
-
6466
- /**
6467
- * get x/y position of element relative to container element
6468
- * @param {Element} elem
6469
- * @returns {Object} offset - has left, top, right, bottom
6470
- */
6471
- proto._getElementOffset = function( elem ) {
6472
- var boundingRect = elem.getBoundingClientRect();
6473
- var thisRect = this._boundingRect;
6474
- var size = getSize( elem );
6475
- var offset = {
6476
- left: boundingRect.left - thisRect.left - size.marginLeft,
6477
- top: boundingRect.top - thisRect.top - size.marginTop,
6478
- right: thisRect.right - boundingRect.right - size.marginRight,
6479
- bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
6480
- };
6481
- return offset;
6482
- };
6483
-
6484
- // -------------------------- resize -------------------------- //
6485
-
6486
- // enable event handlers for listeners
6487
- // i.e. resize -> onresize
6488
- proto.handleEvent = utils.handleEvent;
6489
-
6490
- /**
6491
- * Bind layout to window resizing
6492
- */
6493
- proto.bindResize = function() {
6494
- window.addEventListener( 'resize', this );
6495
- this.isResizeBound = true;
6496
- };
6497
-
6498
- /**
6499
- * Unbind layout to window resizing
6500
- */
6501
- proto.unbindResize = function() {
6502
- window.removeEventListener( 'resize', this );
6503
- this.isResizeBound = false;
6504
- };
6505
-
6506
- proto.onresize = function() {
6507
- this.resize();
6508
- };
6509
-
6510
- utils.debounceMethod( Outlayer, 'onresize', 100 );
6511
-
6512
- proto.resize = function() {
6513
- // don't trigger if size did not change
6514
- // or if resize was unbound. See #9
6515
- if ( !this.isResizeBound || !this.needsResizeLayout() ) {
6516
- return;
6517
- }
6518
-
6519
- this.layout();
6520
- };
6521
-
6522
- /**
6523
- * check if layout is needed post layout
6524
- * @returns Boolean
6525
- */
6526
- proto.needsResizeLayout = function() {
6527
- var size = getSize( this.element );
6528
- // check that this.size and size are there
6529
- // IE8 triggers resize on body size change, so they might not be
6530
- var hasSizes = this.size && size;
6531
- return hasSizes && size.innerWidth !== this.size.innerWidth;
6532
- };
6533
-
6534
- // -------------------------- methods -------------------------- //
6535
-
6536
- /**
6537
- * add items to Outlayer instance
6538
- * @param {Array or NodeList or Element} elems
6539
- * @returns {Array} items - Outlayer.Items
6540
- **/
6541
- proto.addItems = function( elems ) {
6542
- var items = this._itemize( elems );
6543
- // add items to collection
6544
- if ( items.length ) {
6545
- this.items = this.items.concat( items );
6546
- }
6547
- return items;
6548
- };
6549
-
6550
- /**
6551
- * Layout newly-appended item elements
6552
- * @param {Array or NodeList or Element} elems
6553
- */
6554
- proto.appended = function( elems ) {
6555
- var items = this.addItems( elems );
6556
- if ( !items.length ) {
6557
- return;
6558
- }
6559
- // layout and reveal just the new items
6560
- this.layoutItems( items, true );
6561
- this.reveal( items );
6562
- };
6563
-
6564
- /**
6565
- * Layout prepended elements
6566
- * @param {Array or NodeList or Element} elems
6567
- */
6568
- proto.prepended = function( elems ) {
6569
- var items = this._itemize( elems );
6570
- if ( !items.length ) {
6571
- return;
6572
- }
6573
- // add items to beginning of collection
6574
- var previousItems = this.items.slice(0);
6575
- this.items = items.concat( previousItems );
6576
- // start new layout
6577
- this._resetLayout();
6578
- this._manageStamps();
6579
- // layout new stuff without transition
6580
- this.layoutItems( items, true );
6581
- this.reveal( items );
6582
- // layout previous items
6583
- this.layoutItems( previousItems );
6584
- };
6585
-
6586
- /**
6587
- * reveal a collection of items
6588
- * @param {Array of Outlayer.Items} items
6589
- */
6590
- proto.reveal = function( items ) {
6591
- this._emitCompleteOnItems( 'reveal', items );
6592
- if ( !items || !items.length ) {
6593
- return;
6594
- }
6595
- var stagger = this.updateStagger();
6596
- items.forEach( function( item, i ) {
6597
- item.stagger( i * stagger );
6598
- item.reveal();
6599
- });
6600
- };
6601
-
6602
- /**
6603
- * hide a collection of items
6604
- * @param {Array of Outlayer.Items} items
6605
- */
6606
- proto.hide = function( items ) {
6607
- this._emitCompleteOnItems( 'hide', items );
6608
- if ( !items || !items.length ) {
6609
- return;
6610
- }
6611
- var stagger = this.updateStagger();
6612
- items.forEach( function( item, i ) {
6613
- item.stagger( i * stagger );
6614
- item.hide();
6615
- });
6616
- };
6617
-
6618
- /**
6619
- * reveal item elements
6620
- * @param {Array}, {Element}, {NodeList} items
6621
- */
6622
- proto.revealItemElements = function( elems ) {
6623
- var items = this.getItems( elems );
6624
- this.reveal( items );
6625
- };
6626
-
6627
- /**
6628
- * hide item elements
6629
- * @param {Array}, {Element}, {NodeList} items
6630
- */
6631
- proto.hideItemElements = function( elems ) {
6632
- var items = this.getItems( elems );
6633
- this.hide( items );
6634
- };
6635
-
6636
- /**
6637
- * get Outlayer.Item, given an Element
6638
- * @param {Element} elem
6639
- * @param {Function} callback
6640
- * @returns {Outlayer.Item} item
6641
- */
6642
- proto.getItem = function( elem ) {
6643
- // loop through items to get the one that matches
6644
- for ( var i=0; i < this.items.length; i++ ) {
6645
- var item = this.items[i];
6646
- if ( item.element == elem ) {
6647
- // return item
6648
- return item;
6649
- }
6650
- }
6651
- };
6652
-
6653
- /**
6654
- * get collection of Outlayer.Items, given Elements
6655
- * @param {Array} elems
6656
- * @returns {Array} items - Outlayer.Items
6657
- */
6658
- proto.getItems = function( elems ) {
6659
- elems = utils.makeArray( elems );
6660
- var items = [];
6661
- elems.forEach( function( elem ) {
6662
- var item = this.getItem( elem );
6663
- if ( item ) {
6664
- items.push( item );
6665
- }
6666
- }, this );
6667
-
6668
- return items;
6669
- };
6670
-
6671
- /**
6672
- * remove element(s) from instance and DOM
6673
- * @param {Array or NodeList or Element} elems
6674
- */
6675
- proto.remove = function( elems ) {
6676
- var removeItems = this.getItems( elems );
6677
-
6678
- this._emitCompleteOnItems( 'remove', removeItems );
6679
-
6680
- // bail if no items to remove
6681
- if ( !removeItems || !removeItems.length ) {
6682
- return;
6683
- }
6684
-
6685
- removeItems.forEach( function( item ) {
6686
- item.remove();
6687
- // remove item from collection
6688
- utils.removeFrom( this.items, item );
6689
- }, this );
6690
- };
6691
-
6692
- // ----- destroy ----- //
6693
-
6694
- // remove and disable Outlayer instance
6695
- proto.destroy = function() {
6696
- // clean up dynamic styles
6697
- var style = this.element.style;
6698
- style.height = '';
6699
- style.position = '';
6700
- style.width = '';
6701
- // destroy items
6702
- this.items.forEach( function( item ) {
6703
- item.destroy();
6704
- });
6705
-
6706
- this.unbindResize();
6707
-
6708
- var id = this.element.outlayerGUID;
6709
- delete instances[ id ]; // remove reference to instance by id
6710
- delete this.element.outlayerGUID;
6711
- // remove data for jQuery
6712
- if ( jQuery ) {
6713
- jQuery.removeData( this.element, this.constructor.namespace );
6714
- }
6715
-
6716
- };
6717
-
6718
- // -------------------------- data -------------------------- //
6719
-
6720
- /**
6721
- * get Outlayer instance from element
6722
- * @param {Element} elem
6723
- * @returns {Outlayer}
6724
- */
6725
- Outlayer.data = function( elem ) {
6726
- elem = utils.getQueryElement( elem );
6727
- var id = elem && elem.outlayerGUID;
6728
- return id && instances[ id ];
6729
- };
6730
-
6731
-
6732
- // -------------------------- create Outlayer class -------------------------- //
6733
-
6734
- /**
6735
- * create a layout class
6736
- * @param {String} namespace
6737
- */
6738
- Outlayer.create = function( namespace, options ) {
6739
- // sub-class Outlayer
6740
- var Layout = subclass( Outlayer );
6741
- // apply new options and compatOptions
6742
- Layout.defaults = utils.extend( {}, Outlayer.defaults );
6743
- utils.extend( Layout.defaults, options );
6744
- Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions );
6745
-
6746
- Layout.namespace = namespace;
6747
-
6748
- Layout.data = Outlayer.data;
6749
-
6750
- // sub-class Item
6751
- Layout.Item = subclass( Item );
6752
-
6753
- // -------------------------- declarative -------------------------- //
6754
-
6755
- utils.htmlInit( Layout, namespace );
6756
-
6757
- // -------------------------- jQuery bridge -------------------------- //
6758
-
6759
- // make into jQuery plugin
6760
- if ( jQuery && jQuery.bridget ) {
6761
- jQuery.bridget( namespace, Layout );
6762
- }
6763
-
6764
- return Layout;
6765
- };
6766
-
6767
- function subclass( Parent ) {
6768
- function SubClass() {
6769
- Parent.apply( this, arguments );
6770
- }
6771
-
6772
- SubClass.prototype = Object.create( Parent.prototype );
6773
- SubClass.prototype.constructor = SubClass;
6774
-
6775
- return SubClass;
6776
- }
6777
-
6778
- // ----- helpers ----- //
6779
-
6780
- // how many milliseconds are in each unit
6781
- var msUnits = {
6782
- ms: 1,
6783
- s: 1000
6784
- };
6785
-
6786
- // munge time-like parameter into millisecond number
6787
- // '0.4s' -> 40
6788
- function getMilliseconds( time ) {
6789
- if ( typeof time == 'number' ) {
6790
- return time;
6791
- }
6792
- var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
6793
- var num = matches && matches[1];
6794
- var unit = matches && matches[2];
6795
- if ( !num.length ) {
6796
- return 0;
6797
- }
6798
- num = parseFloat( num );
6799
- var mult = msUnits[ unit ] || 1;
6800
- return num * mult;
6801
- }
6802
-
6803
- // ----- fin ----- //
6804
-
6805
- // back in global
6806
- Outlayer.Item = Item;
6807
-
6808
- return Outlayer;
6809
-
6810
- }));
6811
-
6812
- /**
6813
- * Enviratope Item
6814
- **/
6815
-
6816
- ( function( window, factory ) {
6817
- // universal module definition
6818
- /* jshint strict: false */ /*globals define, module, require */
6819
- if ( typeof define == 'function' && define.amd ) {
6820
- // AMD
6821
- define( 'enviratope/item',[
6822
- 'outlayer/outlayer'
6823
- ],
6824
- factory );
6825
- } else if ( typeof module == 'object' && module.exports ) {
6826
- // CommonJS
6827
- module.exports = factory(
6828
- require('outlayer')
6829
- );
6830
- } else {
6831
- // browser global
6832
- window.Enviratope = window.Enviratope || {};
6833
- window.Enviratope.Item = factory(
6834
- window.Outlayer
6835
- );
6836
- }
6837
-
6838
- }( window, function factory( Outlayer ) {
6839
- 'use strict';
6840
-
6841
- // -------------------------- Item -------------------------- //
6842
-
6843
- // sub-class Outlayer Item
6844
- function Item() {
6845
- Outlayer.Item.apply( this, arguments );
6846
- }
6847
-
6848
- var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
6849
-
6850
- var _create = proto._create;
6851
- proto._create = function() {
6852
- // assign id, used for original-order sorting
6853
- this.id = this.layout.itemGUID++;
6854
- _create.call( this );
6855
- this.sortData = {};
6856
- };
6857
-
6858
- proto.updateSortData = function() {
6859
- if ( this.isIgnored ) {
6860
- return;
6861
- }
6862
- // default sorters
6863
- this.sortData.id = this.id;
6864
- // for backward compatibility
6865
- this.sortData['original-order'] = this.id;
6866
- this.sortData.random = Math.random();
6867
- // go thru getSortData obj and apply the sorters
6868
- var getSortData = this.layout.options.getSortData;
6869
- var sorters = this.layout._sorters;
6870
- for ( var key in getSortData ) {
6871
- var sorter = sorters[ key ];
6872
- this.sortData[ key ] = sorter( this.element, this );
6873
- }
6874
- };
6875
-
6876
- var _destroy = proto.destroy;
6877
- proto.destroy = function() {
6878
- // call super
6879
- _destroy.apply( this, arguments );
6880
- // reset display, #741
6881
- this.css({
6882
- display: ''
6883
- });
6884
- };
6885
-
6886
- return Item;
6887
-
6888
- }));
6889
-
6890
- /**
6891
- * Enviratope LayoutMode
6892
- */
6893
-
6894
- ( function( window, factory ) {
6895
- // universal module definition
6896
- /* jshint strict: false */ /*globals define, module, require */
6897
- if ( typeof define == 'function' && define.amd ) {
6898
- // AMD
6899
- define( 'enviratope/layout-mode',[
6900
- 'get-size/get-size',
6901
- 'outlayer/outlayer'
6902
- ],
6903
- factory );
6904
- } else if ( typeof module == 'object' && module.exports ) {
6905
- // CommonJS
6906
- module.exports = factory(
6907
- require('get-size'),
6908
- require('outlayer')
6909
- );
6910
- } else {
6911
- // browser global
6912
- window.Enviratope = window.Enviratope || {};
6913
- window.Enviratope.LayoutMode = factory(
6914
- window.getSize,
6915
- window.Outlayer
6916
- );
6917
- }
6918
-
6919
- }( window, function factory( getSize, Outlayer ) {
6920
- 'use strict';
6921
-
6922
- // layout mode class
6923
- function LayoutMode( enviratope ) {
6924
- this.enviratope = enviratope;
6925
- // link properties
6926
- if ( enviratope ) {
6927
- this.options = enviratope.options[ this.namespace ];
6928
- this.element = enviratope.element;
6929
- this.items = enviratope.filteredItems;
6930
- this.size = enviratope.size;
6931
- }
6932
- }
6933
-
6934
- var proto = LayoutMode.prototype;
6935
-
6936
- /**
6937
- * some methods should just defer to default Outlayer method
6938
- * and reference the Enviratope instance as `this`
6939
- **/
6940
- var facadeMethods = [
6941
- '_resetLayout',
6942
- '_getItemLayoutPosition',
6943
- '_manageStamp',
6944
- '_getContainerSize',
6945
- '_getElementOffset',
6946
- 'needsResizeLayout',
6947
- '_getOption'
6948
- ];
6949
-
6950
- facadeMethods.forEach( function( methodName ) {
6951
- proto[ methodName ] = function() {
6952
- return Outlayer.prototype[ methodName ].apply( this.enviratope, arguments );
6953
- };
6954
- });
6955
-
6956
- // ----- ----- //
6957
-
6958
- // for horizontal layout modes, check vertical size
6959
- proto.needsVerticalResizeLayout = function() {
6960
- // don't trigger if size did not change
6961
- var size = getSize( this.enviratope.element );
6962
- // check that this.size and size are there
6963
- // IE8 triggers resize on body size change, so they might not be
6964
- var hasSizes = this.enviratope.size && size;
6965
- return hasSizes && size.innerHeight != this.enviratope.size.innerHeight;
6966
- };
6967
-
6968
- // ----- measurements ----- //
6969
-
6970
- proto._getMeasurement = function() {
6971
- this.enviratope._getMeasurement.apply( this, arguments );
6972
- };
6973
-
6974
- proto.getColumnWidth = function() {
6975
- this.getSegmentSize( 'column', 'Width' );
6976
- };
6977
-
6978
- proto.getRowHeight = function() {
6979
- this.getSegmentSize( 'row', 'Height' );
6980
- };
6981
-
6982
- /**
6983
- * get columnWidth or rowHeight
6984
- * segment: 'column' or 'row'
6985
- * size 'Width' or 'Height'
6986
- **/
6987
- proto.getSegmentSize = function( segment, size ) {
6988
- var segmentName = segment + size;
6989
- var outerSize = 'outer' + size;
6990
- // columnWidth / outerWidth // rowHeight / outerHeight
6991
- this._getMeasurement( segmentName, outerSize );
6992
- // got rowHeight or columnWidth, we can chill
6993
- if ( this[ segmentName ] ) {
6994
- return;
6995
- }
6996
- // fall back to item of first element
6997
- var firstItemSize = this.getFirstItemSize();
6998
- this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
6999
- // or size of container
7000
- this.enviratope.size[ 'inner' + size ];
7001
- };
7002
-
7003
- proto.getFirstItemSize = function() {
7004
- var firstItem = this.enviratope.filteredItems[0];
7005
- return firstItem && firstItem.element && getSize( firstItem.element );
7006
- };
7007
-
7008
- // ----- methods that should reference enviratope ----- //
7009
-
7010
- proto.layout = function() {
7011
- this.enviratope.layout.apply( this.enviratope, arguments );
7012
- };
7013
-
7014
- proto.getSize = function() {
7015
- this.enviratope.getSize();
7016
- this.size = this.enviratope.size;
7017
- };
7018
-
7019
- // -------------------------- create -------------------------- //
7020
-
7021
- LayoutMode.modes = {};
7022
-
7023
- LayoutMode.create = function( namespace, options ) {
7024
-
7025
- function Mode() {
7026
- LayoutMode.apply( this, arguments );
7027
- }
7028
-
7029
- Mode.prototype = Object.create( proto );
7030
- Mode.prototype.constructor = Mode;
7031
-
7032
- // default options
7033
- if ( options ) {
7034
- Mode.options = options;
7035
- }
7036
-
7037
- Mode.prototype.namespace = namespace;
7038
- // register in Enviratope
7039
- LayoutMode.modes[ namespace ] = Mode;
7040
-
7041
- return Mode;
7042
- };
7043
-
7044
- return LayoutMode;
7045
-
7046
- }));
7047
-
7048
- /*!
7049
- * Masonry v4.1.0
7050
- * Cascading grid layout library
7051
- * http://masonry.desandro.com
7052
- * MIT License
7053
- * by David DeSandro
7054
- */
7055
-
7056
- ( function( window, factory ) {
7057
- // universal module definition
7058
- /* jshint strict: false */ /*globals define, module, require */
7059
- if ( typeof define == 'function' && define.amd ) {
7060
- // AMD
7061
- define( 'masonry/masonry',[
7062
- 'outlayer/outlayer',
7063
- 'get-size/get-size'
7064
- ],
7065
- factory );
7066
- } else if ( typeof module == 'object' && module.exports ) {
7067
- // CommonJS
7068
- module.exports = factory(
7069
- require('outlayer'),
7070
- require('get-size')
7071
- );
7072
- } else {
7073
- // browser global
7074
- window.Masonry = factory(
7075
- window.Outlayer,
7076
- window.getSize
7077
- );
7078
- }
7079
-
7080
- }( window, function factory( Outlayer, getSize ) {
7081
-
7082
-
7083
-
7084
- // -------------------------- masonryDefinition -------------------------- //
7085
-
7086
- // create an Outlayer layout class
7087
- var Masonry = Outlayer.create('masonry');
7088
- // isFitWidth -> fitWidth
7089
- Masonry.compatOptions.fitWidth = 'isFitWidth';
7090
-
7091
- Masonry.prototype._resetLayout = function() {
7092
- this.getSize();
7093
- this._getMeasurement( 'columnWidth', 'outerWidth' );
7094
- this._getMeasurement( 'gutter', 'outerWidth' );
7095
- this.measureColumns();
7096
-
7097
- // reset column Y
7098
- this.colYs = [];
7099
- for ( var i=0; i < this.cols; i++ ) {
7100
- this.colYs.push( 0 );
7101
- }
7102
-
7103
- this.maxY = 0;
7104
- };
7105
-
7106
- Masonry.prototype.measureColumns = function() {
7107
- this.getContainerWidth();
7108
- // if columnWidth is 0, default to outerWidth of first item
7109
- if ( !this.columnWidth ) {
7110
- var firstItem = this.items[0];
7111
- var firstItemElem = firstItem && firstItem.element;
7112
- // columnWidth fall back to item of first element
7113
- this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
7114
- // if first elem has no width, default to size of container
7115
- this.containerWidth;
7116
- }
7117
-
7118
- var columnWidth = this.columnWidth += this.gutter;
7119
-
7120
- // calculate columns
7121
- var containerWidth = this.containerWidth + this.gutter;
7122
- var cols = containerWidth / columnWidth;
7123
- // fix rounding errors, typically with gutters
7124
- var excess = columnWidth - containerWidth % columnWidth;
7125
- // if overshoot is less than a pixel, round up, otherwise floor it
7126
- var mathMethod = excess && excess < 1 ? 'round' : 'floor';
7127
- cols = Math[ mathMethod ]( cols );
7128
- this.cols = Math.max( cols, 1 );
7129
- };
7130
-
7131
- Masonry.prototype.getContainerWidth = function() {
7132
- // container is parent if fit width
7133
- var isFitWidth = this._getOption('fitWidth');
7134
- var container = isFitWidth ? this.element.parentNode : this.element;
7135
- // check that this.size and size are there
7136
- // IE8 triggers resize on body size change, so they might not be
7137
- var size = getSize( container );
7138
- this.containerWidth = size && size.innerWidth;
7139
- };
7140
-
7141
- Masonry.prototype._getItemLayoutPosition = function( item ) {
7142
- item.getSize();
7143
- // how many columns does this brick span
7144
- var remainder = item.size.outerWidth % this.columnWidth;
7145
- var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
7146
- // round if off by 1 pixel, otherwise use ceil
7147
- var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
7148
- colSpan = Math.min( colSpan, this.cols );
7149
-
7150
- var colGroup = this._getColGroup( colSpan );
7151
- // get the minimum Y value from the columns
7152
- var minimumY = Math.min.apply( Math, colGroup );
7153
- var shortColIndex = colGroup.indexOf( minimumY );
7154
-
7155
- // position the brick
7156
- var position = {
7157
- x: this.columnWidth * shortColIndex,
7158
- y: minimumY
7159
- };
7160
-
7161
- // apply setHeight to necessary columns
7162
- var setHeight = minimumY + item.size.outerHeight;
7163
- var setSpan = this.cols + 1 - colGroup.length;
7164
- for ( var i = 0; i < setSpan; i++ ) {
7165
- this.colYs[ shortColIndex + i ] = setHeight;
7166
- }
7167
-
7168
- return position;
7169
- };
7170
-
7171
- /**
7172
- * @param {Number} colSpan - number of columns the element spans
7173
- * @returns {Array} colGroup
7174
- */
7175
- Masonry.prototype._getColGroup = function( colSpan ) {
7176
- if ( colSpan < 2 ) {
7177
- // if brick spans only one column, use all the column Ys
7178
- return this.colYs;
7179
- }
7180
-
7181
- var colGroup = [];
7182
- // how many different places could this brick fit horizontally
7183
- var groupCount = this.cols + 1 - colSpan;
7184
- // for each group potential horizontal position
7185
- for ( var i = 0; i < groupCount; i++ ) {
7186
- // make an array of colY values for that one group
7187
- var groupColYs = this.colYs.slice( i, i + colSpan );
7188
- // and get the max value of the array
7189
- colGroup[i] = Math.max.apply( Math, groupColYs );
7190
- }
7191
- return colGroup;
7192
- };
7193
-
7194
- Masonry.prototype._manageStamp = function( stamp ) {
7195
- var stampSize = getSize( stamp );
7196
- var offset = this._getElementOffset( stamp );
7197
- // get the columns that this stamp affects
7198
- var isOriginLeft = this._getOption('originLeft');
7199
- var firstX = isOriginLeft ? offset.left : offset.right;
7200
- var lastX = firstX + stampSize.outerWidth;
7201
- var firstCol = Math.floor( firstX / this.columnWidth );
7202
- firstCol = Math.max( 0, firstCol );
7203
- var lastCol = Math.floor( lastX / this.columnWidth );
7204
- // lastCol should not go over if multiple of columnWidth #425
7205
- lastCol -= lastX % this.columnWidth ? 0 : 1;
7206
- lastCol = Math.min( this.cols - 1, lastCol );
7207
- // set colYs to bottom of the stamp
7208
-
7209
- var isOriginTop = this._getOption('originTop');
7210
- var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
7211
- stampSize.outerHeight;
7212
- for ( var i = firstCol; i <= lastCol; i++ ) {
7213
- this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
7214
- }
7215
- };
7216
-
7217
- Masonry.prototype._getContainerSize = function() {
7218
- this.maxY = Math.max.apply( Math, this.colYs );
7219
- var size = {
7220
- height: this.maxY
7221
- };
7222
-
7223
- if ( this._getOption('fitWidth') ) {
7224
- size.width = this._getContainerFitWidth();
7225
- }
7226
-
7227
- return size;
7228
- };
7229
-
7230
- Masonry.prototype._getContainerFitWidth = function() {
7231
- var unusedCols = 0;
7232
- // count unused columns
7233
- var i = this.cols;
7234
- while ( --i ) {
7235
- if ( this.colYs[i] !== 0 ) {
7236
- break;
7237
- }
7238
- unusedCols++;
7239
- }
7240
- // fit container to columns that have been used
7241
- return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
7242
- };
7243
-
7244
- Masonry.prototype.needsResizeLayout = function() {
7245
- var previousWidth = this.containerWidth;
7246
- this.getContainerWidth();
7247
- return previousWidth != this.containerWidth;
7248
- };
7249
-
7250
- return Masonry;
7251
-
7252
- }));
7253
-
7254
- /*!
7255
- * Masonry layout mode
7256
- * sub-classes Masonry
7257
- * http://masonry.desandro.com
7258
- */
7259
-
7260
- ( function( window, factory ) {
7261
- // universal module definition
7262
- /* jshint strict: false */ /*globals define, module, require */
7263
- if ( typeof define == 'function' && define.amd ) {
7264
- // AMD
7265
- define( 'enviratope/layout-modes/masonry',[
7266
- '../layout-mode',
7267
- 'masonry/masonry'
7268
- ],
7269
- factory );
7270
- } else if ( typeof module == 'object' && module.exports ) {
7271
- // CommonJS
7272
- module.exports = factory(
7273
- require('../layout-mode'),
7274
- require('masonry-layout')
7275
- );
7276
- } else {
7277
- // browser global
7278
- factory(
7279
- window.Enviratope.LayoutMode,
7280
- window.Masonry
7281
- );
7282
- }
7283
-
7284
- }( window, function factory( LayoutMode, Masonry ) {
7285
- 'use strict';
7286
-
7287
- // -------------------------- masonryDefinition -------------------------- //
7288
-
7289
- // create an Outlayer layout class
7290
- var MasonryMode = LayoutMode.create('masonry');
7291
-
7292
- var proto = MasonryMode.prototype;
7293
-
7294
- var keepModeMethods = {
7295
- _getElementOffset: true,
7296
- layout: true,
7297
- _getMeasurement: true
7298
- };
7299
-
7300
- // inherit Masonry prototype
7301
- for ( var method in Masonry.prototype ) {
7302
- // do not inherit mode methods
7303
- if ( !keepModeMethods[ method ] ) {
7304
- proto[ method ] = Masonry.prototype[ method ];
7305
- }
7306
- }
7307
-
7308
- var measureColumns = proto.measureColumns;
7309
- proto.measureColumns = function() {
7310
- // set items, used if measuring first item
7311
- this.items = this.enviratope.filteredItems;
7312
- measureColumns.call( this );
7313
- };
7314
-
7315
- // point to mode options for fitWidth
7316
- var _getOption = proto._getOption;
7317
- proto._getOption = function( option ) {
7318
- if ( option == 'fitWidth' ) {
7319
- return this.options.isFitWidth !== undefined ?
7320
- this.options.isFitWidth : this.options.fitWidth;
7321
- }
7322
- return _getOption.apply( this.enviratope, arguments );
7323
- };
7324
-
7325
- return MasonryMode;
7326
-
7327
- }));
7328
-
7329
- /**
7330
- * fitRows layout mode
7331
- */
7332
-
7333
- ( function( window, factory ) {
7334
- // universal module definition
7335
- /* jshint strict: false */ /*globals define, module, require */
7336
- if ( typeof define == 'function' && define.amd ) {
7337
- // AMD
7338
- define( 'enviratope/layout-modes/fit-rows',[
7339
- '../layout-mode'
7340
- ],
7341
- factory );
7342
- } else if ( typeof exports == 'object' ) {
7343
- // CommonJS
7344
- module.exports = factory(
7345
- require('../layout-mode')
7346
- );
7347
- } else {
7348
- // browser global
7349
- factory(
7350
- window.Enviratope.LayoutMode
7351
- );
7352
- }
7353
-
7354
- }( window, function factory( LayoutMode ) {
7355
- 'use strict';
7356
-
7357
- var FitRows = LayoutMode.create('fitRows');
7358
-
7359
- var proto = FitRows.prototype;
7360
-
7361
- proto._resetLayout = function() {
7362
- this.x = 0;
7363
- this.y = 0;
7364
- this.maxY = 0;
7365
- this._getMeasurement( 'gutter', 'outerWidth' );
7366
- };
7367
-
7368
- proto._getItemLayoutPosition = function( item ) {
7369
- item.getSize();
7370
-
7371
- var itemWidth = item.size.outerWidth + this.gutter;
7372
- // if this element cannot fit in the current row
7373
- var containerWidth = this.enviratope.size.innerWidth + this.gutter;
7374
- if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
7375
- this.x = 0;
7376
- this.y = this.maxY;
7377
- }
7378
-
7379
- var position = {
7380
- x: this.x,
7381
- y: this.y
7382
- };
7383
-
7384
- this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
7385
- this.x += itemWidth;
7386
-
7387
- return position;
7388
- };
7389
-
7390
- proto._getContainerSize = function() {
7391
- return { height: this.maxY };
7392
- };
7393
-
7394
- return FitRows;
7395
-
7396
- }));
7397
-
7398
- /**
7399
- * vertical layout mode
7400
- */
7401
-
7402
- ( function( window, factory ) {
7403
- // universal module definition
7404
- /* jshint strict: false */ /*globals define, module, require */
7405
- if ( typeof define == 'function' && define.amd ) {
7406
- // AMD
7407
- define( 'enviratope/layout-modes/vertical',[
7408
- '../layout-mode'
7409
- ],
7410
- factory );
7411
- } else if ( typeof module == 'object' && module.exports ) {
7412
- // CommonJS
7413
- module.exports = factory(
7414
- require('../layout-mode')
7415
- );
7416
- } else {
7417
- // browser global
7418
- factory(
7419
- window.Enviratope.LayoutMode
7420
- );
7421
- }
7422
-
7423
- }( window, function factory( LayoutMode ) {
7424
- 'use strict';
7425
-
7426
- var Vertical = LayoutMode.create( 'vertical', {
7427
- horizontalAlignment: 0
7428
- });
7429
-
7430
- var proto = Vertical.prototype;
7431
-
7432
- proto._resetLayout = function() {
7433
- this.y = 0;
7434
- };
7435
-
7436
- proto._getItemLayoutPosition = function( item ) {
7437
- item.getSize();
7438
- var x = ( this.enviratope.size.innerWidth - item.size.outerWidth ) *
7439
- this.options.horizontalAlignment;
7440
- var y = this.y;
7441
- this.y += item.size.outerHeight;
7442
- return { x: x, y: y };
7443
- };
7444
-
7445
- proto._getContainerSize = function() {
7446
- return { height: this.y };
7447
- };
7448
-
7449
- return Vertical;
7450
-
7451
- }));
7452
-
7453
- /*!
7454
- * Enviratope v3.0.0
7455
- *
7456
- * Licensed GPLv3 for open source use
7457
- * or Enviratope Commercial License for commercial use
7458
- *
7459
- * http://enviratope.metafizzy.co
7460
- * Copyright 2016 Metafizzy
7461
- */
7462
-
7463
- ( function( window, factory ) {
7464
- // universal module definition
7465
- /* jshint strict: false */ /*globals define, module, require */
7466
- if ( typeof define == 'function' && define.amd ) {
7467
- // AMD
7468
- define( [
7469
- 'outlayer/outlayer',
7470
- 'get-size/get-size',
7471
- 'desandro-matches-selector/matches-selector',
7472
- 'fizzy-ui-utils/utils',
7473
- './item',
7474
- './layout-mode',
7475
- // include default layout modes
7476
- './layout-modes/masonry',
7477
- './layout-modes/fit-rows',
7478
- './layout-modes/vertical'
7479
- ],
7480
- function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
7481
- return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
7482
- });
7483
- } else if ( typeof module == 'object' && module.exports ) {
7484
- // CommonJS
7485
- module.exports = factory(
7486
- window,
7487
- require('outlayer'),
7488
- require('get-size'),
7489
- require('desandro-matches-selector'),
7490
- require('fizzy-ui-utils'),
7491
- require('./item'),
7492
- require('./layout-mode'),
7493
- // include default layout modes
7494
- require('./layout-modes/masonry'),
7495
- require('./layout-modes/fit-rows'),
7496
- require('./layout-modes/vertical')
7497
- );
7498
- } else {
7499
- // browser global
7500
- window.Enviratope = factory(
7501
- window,
7502
- window.Outlayer,
7503
- window.getSize,
7504
- window.matchesSelector,
7505
- window.fizzyUIUtils,
7506
- window.Enviratope.Item,
7507
- window.Enviratope.LayoutMode
7508
- );
7509
- }
7510
-
7511
- }( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
7512
- Item, LayoutMode ) {
7513
-
7514
-
7515
-
7516
- // -------------------------- vars -------------------------- //
7517
-
7518
- var jQuery = window.jQuery;
7519
-
7520
- // -------------------------- helpers -------------------------- //
7521
-
7522
- var trim = String.prototype.trim ?
7523
- function( str ) {
7524
- return str.trim();
7525
- } :
7526
- function( str ) {
7527
- return str.replace( /^\s+|\s+$/g, '' );
7528
- };
7529
-
7530
- // -------------------------- enviratopeDefinition -------------------------- //
7531
-
7532
- // create an Outlayer layout class
7533
- var Enviratope = Outlayer.create( 'enviratope', {
7534
- layoutMode: 'masonry',
7535
- isJQueryFiltering: true,
7536
- sortAscending: true
7537
- });
7538
-
7539
- Enviratope.Item = Item;
7540
- Enviratope.LayoutMode = LayoutMode;
7541
-
7542
- var proto = Enviratope.prototype;
7543
-
7544
- proto._create = function() {
7545
- this.itemGUID = 0;
7546
- // functions that sort items
7547
- this._sorters = {};
7548
- this._getSorters();
7549
- // call super
7550
- Outlayer.prototype._create.call( this );
7551
-
7552
- // create layout modes
7553
- this.modes = {};
7554
- // start filteredItems with all items
7555
- this.filteredItems = this.items;
7556
- // keep of track of sortBys
7557
- this.sortHistory = [ 'original-order' ];
7558
- // create from registered layout modes
7559
- for ( var name in LayoutMode.modes ) {
7560
- this._initLayoutMode( name );
7561
- }
7562
- };
7563
-
7564
- proto.reloadItems = function() {
7565
- // reset item ID counter
7566
- this.itemGUID = 0;
7567
- // call super
7568
- Outlayer.prototype.reloadItems.call( this );
7569
- };
7570
-
7571
- proto._itemize = function() {
7572
- var items = Outlayer.prototype._itemize.apply( this, arguments );
7573
- // assign ID for original-order
7574
- for ( var i=0; i < items.length; i++ ) {
7575
- var item = items[i];
7576
- item.id = this.itemGUID++;
7577
- }
7578
- this._updateItemsSortData( items );
7579
- return items;
7580
- };
7581
-
7582
-
7583
- // -------------------------- layout -------------------------- //
7584
-
7585
- proto._initLayoutMode = function( name ) {
7586
- var Mode = LayoutMode.modes[ name ];
7587
- // set mode options
7588
- // HACK extend initial options, back-fill in default options
7589
- var initialOpts = this.options[ name ] || {};
7590
- this.options[ name ] = Mode.options ?
7591
- utils.extend( Mode.options, initialOpts ) : initialOpts;
7592
- // init layout mode instance
7593
- this.modes[ name ] = new Mode( this );
7594
- };
7595
-
7596
-
7597
- proto.layout = function() {
7598
- // if first time doing layout, do all magic
7599
- if ( !this._isLayoutInited && this._getOption('initLayout') ) {
7600
- this.arrange();
7601
- return;
7602
- }
7603
- this._layout();
7604
- };
7605
-
7606
- // private method to be used in layout() & magic()
7607
- proto._layout = function() {
7608
- // don't animate first layout
7609
- var isInstant = this._getIsInstant();
7610
- // layout flow
7611
- this._resetLayout();
7612
- this._manageStamps();
7613
- this.layoutItems( this.filteredItems, isInstant );
7614
-
7615
- // flag for initalized
7616
- this._isLayoutInited = true;
7617
- };
7618
-
7619
- // filter + sort + layout
7620
- proto.arrange = function( opts ) {
7621
- // set any options pass
7622
- this.option( opts );
7623
- this._getIsInstant();
7624
- // filter, sort, and layout
7625
-
7626
- // filter
7627
- var filtered = this._filter( this.items );
7628
- this.filteredItems = filtered.matches;
7629
-
7630
- this._bindArrangeComplete();
7631
-
7632
- if ( this._isInstant ) {
7633
- this._noTransition( this._hideReveal, [ filtered ] );
7634
- } else {
7635
- this._hideReveal( filtered );
7636
- }
7637
-
7638
- this._sort();
7639
- this._layout();
7640
- };
7641
- // alias to _init for main plugin method
7642
- proto._init = proto.arrange;
7643
-
7644
- proto._hideReveal = function( filtered ) {
7645
- this.reveal( filtered.needReveal );
7646
- this.hide( filtered.needHide );
7647
- };
7648
-
7649
- // HACK
7650
- // Don't animate/transition first layout
7651
- // Or don't animate/transition other layouts
7652
- proto._getIsInstant = function() {
7653
- var isLayoutInstant = this._getOption('layoutInstant');
7654
- var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
7655
- !this._isLayoutInited;
7656
- this._isInstant = isInstant;
7657
- return isInstant;
7658
- };
7659
-
7660
- // listen for layoutComplete, hideComplete and revealComplete
7661
- // to trigger arrangeComplete
7662
- proto._bindArrangeComplete = function() {
7663
- // listen for 3 events to trigger arrangeComplete
7664
- var isLayoutComplete, isHideComplete, isRevealComplete;
7665
- var _this = this;
7666
- function arrangeParallelCallback() {
7667
- if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
7668
- _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
7669
- }
7670
- }
7671
- this.once( 'layoutComplete', function() {
7672
- isLayoutComplete = true;
7673
- arrangeParallelCallback();
7674
- });
7675
- this.once( 'hideComplete', function() {
7676
- isHideComplete = true;
7677
- arrangeParallelCallback();
7678
- });
7679
- this.once( 'revealComplete', function() {
7680
- isRevealComplete = true;
7681
- arrangeParallelCallback();
7682
- });
7683
- };
7684
-
7685
- // -------------------------- filter -------------------------- //
7686
-
7687
- proto._filter = function( items ) {
7688
- var filter = this.options.filter;
7689
- filter = filter || '*';
7690
- var matches = [];
7691
- var hiddenMatched = [];
7692
- var visibleUnmatched = [];
7693
-
7694
- var test = this._getFilterTest( filter );
7695
-
7696
- // test each item
7697
- for ( var i=0; i < items.length; i++ ) {
7698
- var item = items[i];
7699
- if ( item.isIgnored ) {
7700
- continue;
7701
- }
7702
- // add item to either matched or unmatched group
7703
- var isMatched = test( item );
7704
- // item.isFilterMatched = isMatched;
7705
- // add to matches if its a match
7706
- if ( isMatched ) {
7707
- matches.push( item );
7708
- }
7709
- // add to additional group if item needs to be hidden or revealed
7710
- if ( isMatched && item.isHidden ) {
7711
- hiddenMatched.push( item );
7712
- } else if ( !isMatched && !item.isHidden ) {
7713
- visibleUnmatched.push( item );
7714
- }
7715
- }
7716
-
7717
- // return collections of items to be manipulated
7718
- return {
7719
- matches: matches,
7720
- needReveal: hiddenMatched,
7721
- needHide: visibleUnmatched
7722
- };
7723
- };
7724
-
7725
- // get a jQuery, function, or a matchesSelector test given the filter
7726
- proto._getFilterTest = function( filter ) {
7727
- if ( jQuery && this.options.isJQueryFiltering ) {
7728
- // use jQuery
7729
- return function( item ) {
7730
- return jQuery( item.element ).is( filter );
7731
- };
7732
- }
7733
- if ( typeof filter == 'function' ) {
7734
- // use filter as function
7735
- return function( item ) {
7736
- return filter( item.element );
7737
- };
7738
- }
7739
- // default, use filter as selector string
7740
- return function( item ) {
7741
- return matchesSelector( item.element, filter );
7742
- };
7743
- };
7744
-
7745
- // -------------------------- sorting -------------------------- //
7746
-
7747
- /**
7748
- * @params {Array} elems
7749
- * @public
7750
- */
7751
- proto.updateSortData = function( elems ) {
7752
- // get items
7753
- var items;
7754
- if ( elems ) {
7755
- elems = utils.makeArray( elems );
7756
- items = this.getItems( elems );
7757
- } else {
7758
- // update all items if no elems provided
7759
- items = this.items;
7760
- }
7761
-
7762
- this._getSorters();
7763
- this._updateItemsSortData( items );
7764
- };
7765
-
7766
- proto._getSorters = function() {
7767
- var getSortData = this.options.getSortData;
7768
- for ( var key in getSortData ) {
7769
- var sorter = getSortData[ key ];
7770
- this._sorters[ key ] = mungeSorter( sorter );
7771
- }
7772
- };
7773
-
7774
- /**
7775
- * @params {Array} items - of Enviratope.Items
7776
- * @private
7777
- */
7778
- proto._updateItemsSortData = function( items ) {
7779
- // do not update if no items
7780
- var len = items && items.length;
7781
-
7782
- for ( var i=0; len && i < len; i++ ) {
7783
- var item = items[i];
7784
- item.updateSortData();
7785
- }
7786
- };
7787
-
7788
- // ----- munge sorter ----- //
7789
-
7790
- // encapsulate this, as we just need mungeSorter
7791
- // other functions in here are just for munging
7792
- var mungeSorter = ( function() {
7793
- // add a magic layer to sorters for convienent shorthands
7794
- // `.foo-bar` will use the text of .foo-bar querySelector
7795
- // `[foo-bar]` will use attribute
7796
- // you can also add parser
7797
- // `.foo-bar parseInt` will parse that as a number
7798
- function mungeSorter( sorter ) {
7799
- // if not a string, return function or whatever it is
7800
- if ( typeof sorter != 'string' ) {
7801
- return sorter;
7802
- }
7803
- // parse the sorter string
7804
- var args = trim( sorter ).split(' ');
7805
- var query = args[0];
7806
- // check if query looks like [an-attribute]
7807
- var attrMatch = query.match( /^\[(.+)\]$/ );
7808
- var attr = attrMatch && attrMatch[1];
7809
- var getValue = getValueGetter( attr, query );
7810
- // use second argument as a parser
7811
- var parser = Enviratope.sortDataParsers[ args[1] ];
7812
- // parse the value, if there was a parser
7813
- sorter = parser ? function( elem ) {
7814
- return elem && parser( getValue( elem ) );
7815
- } :
7816
- // otherwise just return value
7817
- function( elem ) {
7818
- return elem && getValue( elem );
7819
- };
7820
-
7821
- return sorter;
7822
- }
7823
-
7824
- // get an attribute getter, or get text of the querySelector
7825
- function getValueGetter( attr, query ) {
7826
- // if query looks like [foo-bar], get attribute
7827
- if ( attr ) {
7828
- return function getAttribute( elem ) {
7829
- return elem.getAttribute( attr );
7830
- };
7831
- }
7832
-
7833
- // otherwise, assume its a querySelector, and get its text
7834
- return function getChildText( elem ) {
7835
- var child = elem.querySelector( query );
7836
- return child && child.textContent;
7837
- };
7838
- }
7839
-
7840
- return mungeSorter;
7841
- })();
7842
-
7843
- // parsers used in getSortData shortcut strings
7844
- Enviratope.sortDataParsers = {
7845
- 'parseInt': function( val ) {
7846
- return parseInt( val, 10 );
7847
- },
7848
- 'parseFloat': function( val ) {
7849
- return parseFloat( val );
7850
- }
7851
- };
7852
-
7853
- // ----- sort method ----- //
7854
-
7855
- // sort filteredItem order
7856
- proto._sort = function() {
7857
- var sortByOpt = this.options.sortBy;
7858
- if ( !sortByOpt ) {
7859
- return;
7860
- }
7861
- // concat all sortBy and sortHistory
7862
- var sortBys = [].concat.apply( sortByOpt, this.sortHistory );
7863
- // sort magic
7864
- var itemSorter = getItemSorter( sortBys, this.options.sortAscending );
7865
- this.filteredItems.sort( itemSorter );
7866
- // keep track of sortBy History
7867
- if ( sortByOpt != this.sortHistory[0] ) {
7868
- // add to front, oldest goes in last
7869
- this.sortHistory.unshift( sortByOpt );
7870
- }
7871
- };
7872
-
7873
- // returns a function used for sorting
7874
- function getItemSorter( sortBys, sortAsc ) {
7875
- return function sorter( itemA, itemB ) {
7876
- // cycle through all sortKeys
7877
- for ( var i = 0; i < sortBys.length; i++ ) {
7878
- var sortBy = sortBys[i];
7879
- var a = itemA.sortData[ sortBy ];
7880
- var b = itemB.sortData[ sortBy ];
7881
- if ( a > b || a < b ) {
7882
- // if sortAsc is an object, use the value given the sortBy key
7883
- var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
7884
- var direction = isAscending ? 1 : -1;
7885
- return ( a > b ? 1 : -1 ) * direction;
7886
- }
7887
- }
7888
- return 0;
7889
- };
7890
- }
7891
-
7892
- // -------------------------- methods -------------------------- //
7893
-
7894
- // get layout mode
7895
- proto._mode = function() {
7896
- var layoutMode = this.options.layoutMode;
7897
- var mode = this.modes[ layoutMode ];
7898
- if ( !mode ) {
7899
- // TODO console.error
7900
- throw new Error( 'No layout mode: ' + layoutMode );
7901
- }
7902
- // HACK sync mode's options
7903
- // any options set after init for layout mode need to be synced
7904
- mode.options = this.options[ layoutMode ];
7905
- return mode;
7906
- };
7907
-
7908
- proto._resetLayout = function() {
7909
- // trigger original reset layout
7910
- Outlayer.prototype._resetLayout.call( this );
7911
- this._mode()._resetLayout();
7912
- };
7913
-
7914
- proto._getItemLayoutPosition = function( item ) {
7915
- return this._mode()._getItemLayoutPosition( item );
7916
- };
7917
-
7918
- proto._manageStamp = function( stamp ) {
7919
- this._mode()._manageStamp( stamp );
7920
- };
7921
-
7922
- proto._getContainerSize = function() {
7923
- return this._mode()._getContainerSize();
7924
- };
7925
-
7926
- proto.needsResizeLayout = function() {
7927
- return this._mode().needsResizeLayout();
7928
- };
7929
-
7930
- // -------------------------- adding & removing -------------------------- //
7931
-
7932
- // HEADS UP overwrites default Outlayer appended
7933
- proto.appended = function( elems ) {
7934
- var items = this.addItems( elems );
7935
- if ( !items.length ) {
7936
- return;
7937
- }
7938
- // filter, layout, reveal new items
7939
- var filteredItems = this._filterRevealAdded( items );
7940
- // add to filteredItems
7941
- this.filteredItems = this.filteredItems.concat( filteredItems );
7942
- };
7943
-
7944
- // HEADS UP overwrites default Outlayer prepended
7945
- proto.prepended = function( elems ) {
7946
- var items = this._itemize( elems );
7947
- if ( !items.length ) {
7948
- return;
7949
- }
7950
- // start new layout
7951
- this._resetLayout();
7952
- this._manageStamps();
7953
- // filter, layout, reveal new items
7954
- var filteredItems = this._filterRevealAdded( items );
7955
- // layout previous items
7956
- this.layoutItems( this.filteredItems );
7957
- // add to items and filteredItems
7958
- this.filteredItems = filteredItems.concat( this.filteredItems );
7959
- this.items = items.concat( this.items );
7960
- };
7961
-
7962
- proto._filterRevealAdded = function( items ) {
7963
- var filtered = this._filter( items );
7964
- this.hide( filtered.needHide );
7965
- // reveal all new items
7966
- this.reveal( filtered.matches );
7967
- // layout new items, no transition
7968
- this.layoutItems( filtered.matches, true );
7969
- return filtered.matches;
7970
- };
7971
-
7972
- /**
7973
- * Filter, sort, and layout newly-appended item elements
7974
- * @param {Array or NodeList or Element} elems
7975
- */
7976
- proto.insert = function( elems ) {
7977
- var items = this.addItems( elems );
7978
- if ( !items.length ) {
7979
- return;
7980
- }
7981
- // append item elements
7982
- var i, item;
7983
- var len = items.length;
7984
- for ( i=0; i < len; i++ ) {
7985
- item = items[i];
7986
- this.element.appendChild( item.element );
7987
- }
7988
- // filter new stuff
7989
- var filteredInsertItems = this._filter( items ).matches;
7990
- // set flag
7991
- for ( i=0; i < len; i++ ) {
7992
- items[i].isLayoutInstant = true;
7993
- }
7994
- this.arrange();
7995
- // reset flag
7996
- for ( i=0; i < len; i++ ) {
7997
- delete items[i].isLayoutInstant;
7998
- }
7999
- this.reveal( filteredInsertItems );
8000
- };
8001
-
8002
- var _remove = proto.remove;
8003
- proto.remove = function( elems ) {
8004
- elems = utils.makeArray( elems );
8005
- var removeItems = this.getItems( elems );
8006
- // do regular thing
8007
- _remove.call( this, elems );
8008
- // bail if no items to remove
8009
- var len = removeItems && removeItems.length;
8010
- // remove elems from filteredItems
8011
- for ( var i=0; len && i < len; i++ ) {
8012
- var item = removeItems[i];
8013
- // remove item from collection
8014
- utils.removeFrom( this.filteredItems, item );
8015
- }
8016
- };
8017
-
8018
- proto.shuffle = function() {
8019
- // update random sortData
8020
- for ( var i=0; i < this.items.length; i++ ) {
8021
- var item = this.items[i];
8022
- item.sortData.random = Math.random();
8023
- }
8024
- this.options.sortBy = 'random';
8025
- this._sort();
8026
- this._layout();
8027
- };
8028
-
8029
- /**
8030
- * trigger fn without transition
8031
- * kind of hacky to have this in the first place
8032
- * @param {Function} fn
8033
- * @param {Array} args
8034
- * @returns ret
8035
- * @private
8036
- */
8037
- proto._noTransition = function( fn, args ) {
8038
- // save transitionDuration before disabling
8039
- var transitionDuration = this.options.transitionDuration;
8040
- // disable transition
8041
- this.options.transitionDuration = 0;
8042
- // do it
8043
- var returnValue = fn.apply( this, args );
8044
- // re-enable transition for reveal
8045
- this.options.transitionDuration = transitionDuration;
8046
- return returnValue;
8047
- };
8048
-
8049
- // ----- helper methods ----- //
8050
-
8051
- /**
8052
- * getter method for getting filtered item elements
8053
- * @returns {Array} elems - collection of item elements
8054
- */
8055
- proto.getFilteredItemElements = function() {
8056
- return this.filteredItems.map( function( item ) {
8057
- return item.element;
8058
- });
8059
- };
8060
-
8061
- // ----- ----- //
8062
-
8063
- return Enviratope;
8064
-
8065
- }));
8066
-
8067
- // Envirabox 2.1.5
8068
- ;(function (window, document, $, undefined) {
8069
- "use strict";
8070
-
8071
- var H = $("html"),
8072
- W = $(window),
8073
- D = $(document),
8074
- F = $.envirabox = function () {
8075
- F.open.apply( this, arguments );
8076
- },
8077
- IE = navigator.userAgent.match(/msie/i),
8078
- didUpdate = null,
8079
- isTouch = document.createTouch !== undefined,
8080
-
8081
- isQuery = function(obj) {
8082
- return obj && obj.hasOwnProperty && obj instanceof $;
8083
- },
8084
- isString = function(str) {
8085
- return str && $.type(str) === "string";
8086
- },
8087
- isPercentage = function(str) {
8088
- return isString(str) && str.indexOf('%') > 0;
8089
- },
8090
- isScrollable = function(el) {
8091
- return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));
8092
- },
8093
- getScalar = function(orig, dim) {
8094
- var value = parseInt(orig, 10) || 0;
8095
-
8096
- if (dim && isPercentage(orig)) {
8097
- value = F.getViewport()[ dim ] / 100 * value;
8098
- }
8099
-
8100
- return Math.ceil(value);
8101
- },
8102
- getValue = function(value, dim) {
8103
- return getScalar(value, dim) + 'px';
8104
- };
8105
-
8106
- $.extend(F, {
8107
- // The current version of envirabox
8108
- version: '2.1.5',
8109
-
8110
- defaults: {
8111
- padding : 15,
8112
- margin : 40,
8113
-
8114
- width : 800,
8115
- height : 600,
8116
- minWidth : 100,
8117
- minHeight : 100,
8118
- maxWidth : 9999,
8119
- maxHeight : 9999,
8120
- pixelRatio: 1, // Set to 2 for retina display support
8121
-
8122
- autoSize : true,
8123
- autoHeight : false,
8124
- autoWidth : false,
8125
-
8126
- autoResize : true,
8127
- autoCenter : !isTouch,
8128
- fitToView : true,
8129
- aspectRatio : false,
8130
- topRatio : 0.5,
8131
- leftRatio : 0.5,
8132
-
8133
- scrolling : 'auto', // 'auto', 'yes' or 'no'
8134
- wrapCSS : '',
8135
-
8136
- arrows : true,
8137
- closeBtn : true,
8138
- closeClick : false,
8139
- nextClick : false,
8140
- mouseWheel : true,
8141
- autoPlay : false,
8142
- playSpeed : 3000,
8143
- preload : 3,
8144
- modal : false,
8145
- loop : true,
8146
-
8147
- ajax : {
8148
- dataType : 'html',
8149
- headers : { 'X-envirabox': true }
8150
- },
8151
- iframe : {
8152
- scrolling : 'auto',
8153
- preload : true
8154
- },
8155
- swf : {
8156
- wmode: 'transparent',
8157
- allowfullscreen : 'true',
8158
- allowscriptaccess : 'always'
8159
- },
8160
-
8161
- keys : {
8162
- next : {
8163
- 13 : 'left', // enter
8164
- 34 : 'up', // page down
8165
- 39 : 'left', // right arrow
8166
- 40 : 'up' // down arrow
8167
- },
8168
- prev : {
8169
- 8 : 'right', // backspace
8170
- 33 : 'down', // page up
8171
- 37 : 'right', // left arrow
8172
- 38 : 'down' // up arrow
8173
- },
8174
- close : [27], // escape key
8175
- play : [32], // space - start/stop slideshow
8176
- toggle : [70] // letter "f" - toggle fullscreen
8177
- },
8178
-
8179
- direction : {
8180
- next : 'left',
8181
- prev : 'right'
8182
- },
8183
-
8184
- scrollOutside : true,
8185
-
8186
- // Override some properties
8187
- index : 0,
8188
- type : null,
8189
- href : null,
8190
- content : null,
8191
- title : null,
8192
-
8193
- // HTML templates
8194
- tpl: {
8195
- wrap : '<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin"><div class="envirabox-outer"><div class="envirabox-inner"></div></div></div></div>',
8196
- image : '<img class="envirabox-image" src="{href}" />',
8197
- iframe : '<iframe id="envirabox-frame{rnd}" name="envirabox-frame{rnd}" class="envirabox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',
8198
- error : '<p class="envirabox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
8199
- closeBtn : '<a title="Close" class="envirabox-item envirabox-close" href="javascript:;"></a>',
8200
- next : '<a title="Next" class="envirabox-nav envirabox-next" href="javascript:;"><span></span></a>',
8201
- prev : '<a title="Previous" class="envirabox-nav envirabox-prev" href="javascript:;"><span></span></a>'
8202
- },
8203
-
8204
- // Properties for each animation type
8205
- // Opening envirabox
8206
- openEffect : 'fade', // 'elastic', 'fade' or 'none'
8207
- openSpeed : 250,
8208
- openEasing : 'swing',
8209
- openOpacity : true,
8210
- openMethod : 'zoomIn',
8211
-
8212
- // Closing envirabox
8213
- closeEffect : 'fade', // 'elastic', 'fade' or 'none'
8214
- closeSpeed : 250,
8215
- closeEasing : 'swing',
8216
- closeOpacity : true,
8217
- closeMethod : 'zoomOut',
8218
-
8219
- // Changing next gallery item
8220
- nextEffect : 'elastic', // 'elastic', 'fade' or 'none'
8221
- nextSpeed : 250,
8222
- nextEasing : 'swing',
8223
- nextMethod : 'changeIn',
8224
-
8225
- // Changing previous gallery item
8226
- prevEffect : 'elastic', // 'elastic', 'fade' or 'none'
8227
- prevSpeed : 250,
8228
- prevEasing : 'swing',
8229
- prevMethod : 'changeOut',
8230
-
8231
- // Enable default helpers
8232
- helpers : {
8233
- overlay : true,
8234
- title : true
8235
- },
8236
-
8237
- // Callbacks
8238
- onCancel : $.noop, // If canceling
8239
- beforeLoad : $.noop, // Before loading
8240
- afterLoad : $.noop, // After loading
8241
- beforeShow : $.noop, // Before changing in current item
8242
- afterShow : $.noop, // After opening
8243
- beforeChange : $.noop, // Before changing gallery item
8244
- beforeClose : $.noop, // Before closing
8245
- afterClose : $.noop // After closing
8246
- },
8247
-
8248
- //Current state
8249
- group : {}, // Selected group
8250
- opts : {}, // Group options
8251
- previous : null, // Previous element
8252
- coming : null, // Element being loaded
8253
- current : null, // Currently loaded element
8254
- isActive : false, // Is activated
8255
- isOpen : false, // Is currently open
8256
- isOpened : false, // Have been fully opened at least once
8257
-
8258
- wrap : null,
8259
- skin : null,
8260
- outer : null,
8261
- inner : null,
8262
-
8263
- player : {
8264
- timer : null,
8265
- isActive : false
8266
- },
8267
-
8268
- // Loaders
8269
- ajaxLoad : null,
8270
- imgPreload : null,
8271
-
8272
- // Some collections
8273
- transitions : {},
8274
- helpers : {},
8275
-
8276
- /*
8277
- * Static methods
8278
- */
8279
-
8280
- open: function (group, opts) {
8281
- if (!group) {
8282
- return;
8283
- }
8284
-
8285
- if (!$.isPlainObject(opts)) {
8286
- opts = {};
8287
- }
8288
-
8289
- // Close if already active
8290
- if (false === F.close(true)) {
8291
- return;
8292
- }
8293
-
8294
- // Normalize group
8295
- if (!$.isArray(group)) {
8296
- group = isQuery(group) ? $(group).get() : [group];
8297
- }
8298
-
8299
- // Recheck if the type of each element is `object` and set content type (image, ajax, etc)
8300
- $.each(group, function(i, element) {
8301
- var obj = {},
8302
- href,
8303
- title,
8304
- content,
8305
- type,
8306
- rez,
8307
- hrefParts,
8308
- selector;
8309
-
8310
- if ($.type(element) === "object") {
8311
- // Check if is DOM element
8312
- if (element.nodeType) {
8313
- element = $(element);
8314
- }
8315
-
8316
- if (isQuery(element)) {
8317
- obj = {
8318
- href : element.data('envirabox-href') || element.attr('href'),
8319
- title : $('<div/>').text( element.data('envirabox-title') || element.attr('title') ).html(),
8320
- isDom : true,
8321
- element : element
8322
- };
8323
-
8324
- if ($.metadata) {
8325
- $.extend(true, obj, element.metadata());
8326
- }
8327
-
8328
- } else {
8329
- obj = element;
8330
- }
8331
- }
8332
-
8333
- href = opts.href || obj.href || (isString(element) ? element : null);
8334
- title = opts.title !== undefined ? opts.title : obj.title || '';
8335
-
8336
- content = opts.content || obj.content;
8337
- type = content ? 'html' : (opts.type || obj.type);
8338
-
8339
- if (!type && obj.isDom) {
8340
- type = element.data('envirabox-type');
8341
-
8342
- if (!type) {
8343
- rez = element.prop('class').match(/envirabox\.(\w+)/);
8344
- type = rez ? rez[1] : null;
8345
- }
8346
- }
8347
-
8348
- if (isString(href)) {
8349
- // Try to guess the content type
8350
- if (!type) {
8351
- if (F.isImage(href)) {
8352
- type = 'image';
8353
-
8354
- } else if (F.isSWF(href)) {
8355
- type = 'swf';
8356
-
8357
- } else if (href.charAt(0) === '#') {
8358
- type = 'inline';
8359
-
8360
- } else if (isString(element)) {
8361
- type = 'html';
8362
- content = element;
8363
- }
8364
- }
8365
-
8366
- // Split url into two pieces with source url and content selector, e.g,
8367
- // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"
8368
- if (type === 'ajax') {
8369
- hrefParts = href.split(/\s+/, 2);
8370
- href = hrefParts.shift();
8371
- selector = hrefParts.shift();
8372
- }
8373
- }
8374
-
8375
- if (!content) {
8376
- if (type === 'inline') {
8377
- if (href) {
8378
- content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
8379
-
8380
- } else if (obj.isDom) {
8381
- content = element;
8382
- }
8383
-
8384
- } else if (type === 'html') {
8385
- content = href;
8386
-
8387
- } else if (!type && !href && obj.isDom) {
8388
- type = 'inline';
8389
- content = element;
8390
- }
8391
- }
8392
-
8393
- $.extend(obj, {
8394
- href : href,
8395
- type : type,
8396
- content : content,
8397
- title : title,
8398
- selector : selector
8399
- });
8400
-
8401
- group[ i ] = obj;
8402
- });
8403
-
8404
- // Extend the defaults
8405
- F.opts = $.extend(true, {}, F.defaults, opts);
8406
-
8407
- // All options are merged recursive except keys
8408
- if (opts.keys !== undefined) {
8409
- F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
8410
- }
8411
-
8412
- F.group = group;
8413
-
8414
- return F._start(F.opts.index);
8415
- },
8416
-
8417
- // Cancel image loading or abort ajax request
8418
- cancel: function () {
8419
- var coming = F.coming;
8420
-
8421
- if (coming && false === F.trigger('onCancel')) {
8422
- return;
8423
- }
8424
-
8425
- F.hideLoading();
8426
-
8427
- if (!coming) {
8428
- return;
8429
- }
8430
-
8431
- if (F.ajaxLoad) {
8432
- F.ajaxLoad.abort();
8433
- }
8434
-
8435
- F.ajaxLoad = null;
8436
-
8437
- if (F.imgPreload) {
8438
- F.imgPreload.onload = F.imgPreload.onerror = null;
8439
- }
8440
-
8441
- if (coming.wrap) {
8442
- coming.wrap.stop(true, true).trigger('onReset').remove();
8443
- }
8444
-
8445
- F.coming = null;
8446
-
8447
- // If the first item has been canceled, then clear everything
8448
- if (!F.current) {
8449
- F._afterZoomOut( coming );
8450
- }
8451
- },
8452
-
8453
- // Start closing animation if is open; remove immediately if opening/closing
8454
- close: function (event) {
8455
- F.cancel();
8456
-
8457
- if (false === F.trigger('beforeClose')) {
8458
- return;
8459
- }
8460
-
8461
- F.unbindEvents();
8462
-
8463
- if (!F.isActive) {
8464
- return;
8465
- }
8466
-
8467
- if (!F.isOpen || event === true) {
8468
- $('.envirabox-wrap').stop(true).trigger('onReset').remove();
8469
-
8470
- F._afterZoomOut();
8471
-
8472
- } else {
8473
- F.isOpen = F.isOpened = false;
8474
- F.isClosing = true;
8475
-
8476
- $('.envirabox-item, .envirabox-nav').remove();
8477
-
8478
- F.wrap.stop(true, true).removeClass('envirabox-opened');
8479
-
8480
- F.transitions[ F.current.closeMethod ]();
8481
- }
8482
- },
8483
-
8484
- // Manage slideshow:
8485
- // $.envirabox.play(); - toggle slideshow
8486
- // $.envirabox.play( true ); - start
8487
- // $.envirabox.play( false ); - stop
8488
- play: function ( action ) {
8489
- var clear = function () {
8490
- clearTimeout(F.player.timer);
8491
- },
8492
- set = function () {
8493
- clear();
8494
-
8495
- if (F.current && F.player.isActive) {
8496
- F.player.timer = setTimeout(F.next, F.current.playSpeed);
8497
- }
8498
- },
8499
- stop = function () {
8500
- clear();
8501
-
8502
- D.unbind('.player');
8503
-
8504
- F.player.isActive = false;
8505
-
8506
- F.trigger('onPlayEnd');
8507
- },
8508
- start = function () {
8509
- if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
8510
- F.player.isActive = true;
8511
-
8512
- D.bind({
8513
- 'onCancel.player beforeClose.player' : stop,
8514
- 'onUpdate.player' : set,
8515
- 'beforeLoad.player' : clear
8516
- });
8517
-
8518
- set();
8519
-
8520
- F.trigger('onPlayStart');
8521
- }
8522
- };
8523
-
8524
- if (action === true || (!F.player.isActive && action !== false)) {
8525
- start();
8526
- } else {
8527
- stop();
8528
- }
8529
- },
8530
-
8531
- // Navigate to next gallery item
8532
- next: function ( direction ) {
8533
- var current = F.current;
8534
-
8535
- if (current) {
8536
- if (!isString(direction)) {
8537
- direction = current.direction.next;
8538
- }
8539
-
8540
- F.jumpto(current.index + 1, direction, 'next');
8541
- }
8542
- },
8543
-
8544
- // Navigate to previous gallery item
8545
- prev: function ( direction ) {
8546
- var current = F.current;
8547
-
8548
- if (current) {
8549
- if (!isString(direction)) {
8550
- direction = current.direction.prev;
8551
- }
8552
-
8553
- F.jumpto(current.index - 1, direction, 'prev');
8554
- }
8555
- },
8556
-
8557
- // Navigate to gallery item by index
8558
- jumpto: function ( index, direction, router ) {
8559
- var current = F.current;
8560
-
8561
- if (!current) {
8562
- return;
8563
- }
8564
-
8565
- index = getScalar(index);
8566
-
8567
- F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];
8568
- F.router = router || 'jumpto';
8569
-
8570
- if (current.loop) {
8571
- if (index < 0) {
8572
- index = current.group.length + (index % current.group.length);
8573
- }
8574
-
8575
- index = index % current.group.length;
8576
- }
8577
-
8578
- if (current.group[ index ] !== undefined) {
8579
- F.cancel();
8580
-
8581
- F._start(index);
8582
- }
8583
- },
8584
-
8585
- // Center inside viewport and toggle position type to fixed or absolute if needed
8586
- reposition: function (e, onlyAbsolute) {
8587
- var current = F.current,
8588
- wrap = current ? current.wrap : null,
8589
- pos;
8590
-
8591
- if (wrap) {
8592
- pos = F._getPosition(onlyAbsolute);
8593
-
8594
- if (e && e.type === 'scroll') {
8595
- delete pos.position;
8596
-
8597
- wrap.stop(true, true).animate(pos, 200);
8598
-
8599
- } else {
8600
- wrap.css(pos);
8601
-
8602
- current.pos = $.extend({}, current.dim, pos);
8603
- }
8604
- }
8605
- },
8606
-
8607
- update: function (e) {
8608
- var type = (e && e.originalEvent && e.originalEvent.type),
8609
- anyway = !type || type === 'orientationchange';
8610
-
8611
- if (anyway) {
8612
- clearTimeout(didUpdate);
8613
-
8614
- didUpdate = null;
8615
- }
8616
-
8617
- if (!F.isOpen || didUpdate) {
8618
- return;
8619
- }
8620
-
8621
- didUpdate = setTimeout(function() {
8622
- var current = F.current;
8623
-
8624
- if (!current || F.isClosing) {
8625
- return;
8626
- }
8627
-
8628
- F.wrap.removeClass('envirabox-tmp');
8629
-
8630
- if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) {
8631
- F._setDimension();
8632
- }
8633
-
8634
- if (!(type === 'scroll' && current.canShrink)) {
8635
- F.reposition(e);
8636
- }
8637
-
8638
- F.trigger('onUpdate');
8639
-
8640
- didUpdate = null;
8641
-
8642
- }, (anyway && !isTouch ? 0 : 300));
8643
- },
8644
-
8645
- // Shrink content to fit inside viewport or restore if resized
8646
- toggle: function ( action ) {
8647
- if (F.isOpen) {
8648
- F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
8649
-
8650
- // Help browser to restore document dimensions
8651
- if (isTouch) {
8652
- F.wrap.removeAttr('style').addClass('envirabox-tmp');
8653
-
8654
- F.trigger('onUpdate');
8655
- }
8656
-
8657
- F.update();
8658
- }
8659
- },
8660
-
8661
- hideLoading: function () {
8662
- D.unbind('.loading');
8663
-
8664
- $('#envirabox-loading').remove();
8665
- },
8666
-
8667
- showLoading: function () {
8668
- var el, viewport;
8669
-
8670
- F.hideLoading();
8671
-
8672
- el = $('<div id="envirabox-loading"><div></div></div>').click(F.cancel).appendTo('body');
8673
-
8674
- // If user will press the escape-button, the request will be canceled
8675
- D.bind('keydown.loading', function(e) {
8676
- if ((e.which || e.keyCode) === 27) {
8677
- e.preventDefault();
8678
-
8679
- F.cancel();
8680
- }
8681
- });
8682
-
8683
- if (!F.defaults.fixed) {
8684
- viewport = F.getViewport();
8685
-
8686
- el.css({
8687
- position : 'absolute',
8688
- top : (viewport.h * 0.5) + viewport.y,
8689
- left : (viewport.w * 0.5) + viewport.x
8690
- });
8691
- }
8692
-
8693
- F.trigger('onLoading');
8694
- },
8695
-
8696
- getViewport: function () {
8697
- var locked = (F.current && F.current.locked) || false,
8698
- rez = {
8699
- x: W.scrollLeft(),
8700
- y: W.scrollTop()
8701
- };
8702
-
8703
- if (locked && locked.length) {
8704
- rez.w = locked[0].clientWidth;
8705
- rez.h = locked[0].clientHeight;
8706
-
8707
- } else {
8708
- // See http://bugs.jquery.com/ticket/6724
8709
- rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width();
8710
- rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();
8711
- }
8712
-
8713
- return rez;
8714
- },
8715
-
8716
- // Unbind the keyboard / clicking actions
8717
- unbindEvents: function () {
8718
- if (F.wrap && isQuery(F.wrap)) {
8719
- F.wrap.unbind('.fb');
8720
- }
8721
-
8722
- D.unbind('.fb');
8723
- W.unbind('.fb');
8724
- },
8725
-
8726
- bindEvents: function () {
8727
- var current = F.current,
8728
- keys;
8729
-
8730
- if (!current) {
8731
- return;
8732
- }
8733
-
8734
- // Changing document height on iOS devices triggers a 'resize' event,
8735
- // that can change document height... repeating infinitely
8736
- W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
8737
-
8738
- keys = current.keys;
8739
-
8740
- if (keys) {
8741
- D.bind('keydown.fb', function (e) {
8742
- var code = e.which || e.keyCode,
8743
- target = e.target || e.srcElement;
8744
-
8745
- // Skip esc key if loading, because showLoading will cancel preloading
8746
- if (code === 27 && F.coming) {
8747
- return false;
8748
- }
8749
-
8750
- // Ignore key combinations and key events within form elements
8751
- if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
8752
- $.each(keys, function(i, val) {
8753
- if (current.group.length > 1 && val[ code ] !== undefined) {
8754
- F[ i ]( val[ code ] );
8755
-
8756
- e.preventDefault();
8757
- return false;
8758
- }
8759
-
8760
- if ($.inArray(code, val) > -1) {
8761
- F[ i ] ();
8762
-
8763
- e.preventDefault();
8764
- return false;
8765
- }
8766
- });
8767
- }
8768
- });
8769
- }
8770
-
8771
- if ($.fn.mousewheel && current.mouseWheel) {
8772
- F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {
8773
- var target = e.target || null,
8774
- parent = $(target),
8775
- canScroll = false;
8776
-
8777
- while (parent.length) {
8778
- if (canScroll || parent.is('.envirabox-skin') || parent.is('.envirabox-wrap')) {
8779
- break;
8780
- }
8781
-
8782
- canScroll = isScrollable( parent[0] );
8783
- parent = $(parent).parent();
8784
- }
8785
-
8786
- if (delta !== 0 && !canScroll) {
8787
- if (F.group.length > 1 && !current.canShrink) {
8788
- if (deltaY > 0 || deltaX > 0) {
8789
- F.prev( deltaY > 0 ? 'down' : 'left' );
8790
-
8791
- } else if (deltaY < 0 || deltaX < 0) {
8792
- F.next( deltaY < 0 ? 'up' : 'right' );
8793
- }
8794
-
8795
- e.preventDefault();
8796
- }
8797
- }
8798
- });
8799
- }
8800
- },
8801
-
8802
- trigger: function (event, o) {
8803
- var ret, obj = o || F.coming || F.current;
8804
-
8805
- if (obj) {
8806
- if ($.isFunction( obj[event] )) {
8807
- ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
8808
- }
8809
-
8810
- if (ret === false) {
8811
- return false;
8812
- }
8813
-
8814
- if (obj.helpers) {
8815
- $.each(obj.helpers, function (helper, opts) {
8816
- if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {
8817
- F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);
8818
- }
8819
- });
8820
- }
8821
- }
8822
-
8823
- D.trigger(event);
8824
- },
8825
-
8826
- isImage: function (str) {
8827
- return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
8828
- },
8829
-
8830
- isSWF: function (str) {
8831
- return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i);
8832
- },
8833
-
8834
- _start: function (index) {
8835
- var coming = {},
8836
- obj,
8837
- href,
8838
- type,
8839
- margin,
8840
- padding;
8841
-
8842
- index = getScalar( index );
8843
- obj = F.group[ index ] || null;
8844
-
8845
- if (!obj) {
8846
- return false;
8847
- }
8848
-
8849
- coming = $.extend(true, {}, F.opts, obj);
8850
-
8851
- // Convert margin and padding properties to array - top, right, bottom, left
8852
- margin = coming.margin;
8853
- padding = coming.padding;
8854
-
8855
- if ($.type(margin) === 'number') {
8856
- coming.margin = [margin, margin, margin, margin];
8857
- }
8858
-
8859
- if ($.type(padding) === 'number') {
8860
- coming.padding = [padding, padding, padding, padding];
8861
- }
8862
-
8863
- // 'modal' propery is just a shortcut
8864
- if (coming.modal) {
8865
- $.extend(true, coming, {
8866
- closeBtn : false,
8867
- closeClick : false,
8868
- nextClick : false,
8869
- arrows : false,
8870
- mouseWheel : false,
8871
- keys : null,
8872
- helpers: {
8873
- overlay : {
8874
- closeClick : false
8875
- }
8876
- }
8877
- });
8878
- }
8879
-
8880
- // 'autoSize' property is a shortcut, too
8881
- if (coming.autoSize) {
8882
- coming.autoWidth = coming.autoHeight = true;
8883
- }
8884
-
8885
- if (coming.width === 'auto') {
8886
- coming.autoWidth = true;
8887
- }
8888
-
8889
- if (coming.height === 'auto') {
8890
- coming.autoHeight = true;
8891
- }
8892
-
8893
- /*
8894
- * Add reference to the group, so it`s possible to access from callbacks, example:
8895
- * afterLoad : function() {
8896
- * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
8897
- * }
8898
- */
8899
-
8900
- coming.group = F.group;
8901
- coming.index = index;
8902
-
8903
- // Give a chance for callback or helpers to update coming item (type, title, etc)
8904
- F.coming = coming;
8905
-
8906
- if (false === F.trigger('beforeLoad')) {
8907
- F.coming = null;
8908
-
8909
- return;
8910
- }
8911
-
8912
- type = coming.type;
8913
- href = coming.href;
8914
-
8915
- if (!type) {
8916
- F.coming = null;
8917
-
8918
- //If we can not determine content type then drop silently or display next/prev item if looping through gallery
8919
- if (F.current && F.router && F.router !== 'jumpto') {
8920
- F.current.index = index;
8921
-
8922
- return F[ F.router ]( F.direction );
8923
- }
8924
-
8925
- return false;
8926
- }
8927
-
8928
- F.isActive = true;
8929
-
8930
- if (type === 'image' || type === 'swf') {
8931
- coming.autoHeight = coming.autoWidth = false;
8932
- coming.scrolling = 'visible';
8933
- }
8934
-
8935
- if (type === 'image') {
8936
- coming.aspectRatio = true;
8937
- }
8938
-
8939
- if (type === 'iframe' && isTouch) {
8940
- coming.scrolling = 'scroll';
8941
- }
8942
-
8943
- // Build the neccessary markup
8944
- coming.wrap = $(coming.tpl.wrap).addClass('envirabox-' + (isTouch ? 'mobile' : 'desktop') + ' envirabox-type-' + type + ' envirabox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' );
8945
-
8946
- $.extend(coming, {
8947
- skin : $('.envirabox-skin', coming.wrap),
8948
- outer : $('.envirabox-outer', coming.wrap),
8949
- inner : $('.envirabox-inner', coming.wrap)
8950
- });
8951
-
8952
- $.each(["Top", "Right", "Bottom", "Left"], function(i, v) {
8953
- coming.skin.css('padding' + v, getValue(coming.padding[ i ]));
8954
- });
8955
-
8956
- F.trigger('onReady');
8957
-
8958
- // Check before try to load; 'inline' and 'html' types need content, others - href
8959
- if (type === 'inline' || type === 'html') {
8960
- if (!coming.content || !coming.content.length) {
8961
- return F._error( 'content' );
8962
- }
8963
-
8964
- } else if (!href) {
8965
- return F._error( 'href' );
8966
- }
8967
-
8968
- if (type === 'image') {
8969
- F._loadImage();
8970
-
8971
- } else if (type === 'ajax') {
8972
- F._loadAjax();
8973
-
8974
- } else if (type === 'iframe') {
8975
- F._loadIframe();
8976
-
8977
- } else {
8978
- F._afterLoad();
8979
- }
8980
- },
8981
-
8982
- _error: function ( type ) {
8983
- $.extend(F.coming, {
8984
- type : 'html',
8985
- autoWidth : true,
8986
- autoHeight : true,
8987
- minWidth : 0,
8988
- minHeight : 0,
8989
- scrolling : 'no',
8990
- hasError : type,
8991
- content : F.coming.tpl.error
8992
- });
8993
-
8994
- F._afterLoad();
8995
- },
8996
-
8997
- _loadImage: function () {
8998
- // Reset preload image so it is later possible to check "complete" property
8999
- var img = F.imgPreload = new Image();
9000
-
9001
- img.onload = function () {
9002
- this.onload = this.onerror = null;
9003
-
9004
- F.coming.width = this.width / F.opts.pixelRatio;
9005
- F.coming.height = this.height / F.opts.pixelRatio;
9006
-
9007
- F._afterLoad();
9008
- };
9009
-
9010
- img.onerror = function () {
9011
- this.onload = this.onerror = null;
9012
-
9013
- F._error( 'image' );
9014
- };
9015
-
9016
- img.src = F.coming.href;
9017
-
9018
- if (img.complete !== true) {
9019
- F.showLoading();
9020
- }
9021
- },
9022
-
9023
- _loadAjax: function () {
9024
- var coming = F.coming;
9025
-
9026
- F.showLoading();
9027
-
9028
- F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
9029
- url: coming.href,
9030
- error: function (jqXHR, textStatus) {
9031
- if (F.coming && textStatus !== 'abort') {
9032
- F._error( 'ajax', jqXHR );
9033
-
9034
- } else {
9035
- F.hideLoading();
9036
- }
9037
- },
9038
- success: function (data, textStatus) {
9039
- if (textStatus === 'success') {
9040
- coming.content = data;
9041
-
9042
- F._afterLoad();
9043
- }
9044
- }
9045
- }));
9046
- },
9047
-
9048
- _loadIframe: function() {
9049
- var coming = F.coming,
9050
- iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))
9051
- .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling)
9052
- .attr('src', coming.href);
9053
-
9054
- // This helps IE
9055
- $(coming.wrap).bind('onReset', function () {
9056
- try {
9057
- $(this).find('iframe').hide().attr('src', '//about:blank').end().empty();
9058
- } catch (e) {}
9059
- });
9060
-
9061
- if (coming.iframe.preload) {
9062
- F.showLoading();
9063
-
9064
- iframe.one('load', function() {
9065
- $(this).data('ready', 1);
9066
-
9067
- // iOS will lose scrolling if we resize
9068
- if (!isTouch) {
9069
- $(this).bind('load.fb', F.update);
9070
- }
9071
-
9072
- // Without this trick:
9073
- // - iframe won't scroll on iOS devices
9074
- // - IE7 sometimes displays empty iframe
9075
- $(this).parents('.envirabox-wrap').width('100%').removeClass('envirabox-tmp').show();
9076
-
9077
- F._afterLoad();
9078
- });
9079
- }
9080
-
9081
- coming.content = iframe.appendTo( coming.inner );
9082
-
9083
- if (!coming.iframe.preload) {
9084
- F._afterLoad();
9085
- }
9086
- },
9087
-
9088
- _preloadImages: function() {
9089
- var group = F.group,
9090
- current = F.current,
9091
- len = group.length,
9092
- cnt = current.preload ? Math.min(current.preload, len - 1) : 0,
9093
- item,
9094
- i;
9095
-
9096
- for (i = 1; i <= cnt; i += 1) {
9097
- item = group[ (current.index + i ) % len ];
9098
-
9099
- if (item.type === 'image' && item.href) {
9100
- new Image().src = item.href;
9101
- }
9102
- }
9103
- },
9104
-
9105
- _afterLoad: function () {
9106
- var coming = F.coming,
9107
- previous = F.current,
9108
- placeholder = 'envirabox-placeholder',
9109
- current,
9110
- content,
9111
- type,
9112
- scrolling,
9113
- href,
9114
- embed;
9115
-
9116
- F.hideLoading();
9117
-
9118
- if (!coming || F.isActive === false) {
9119
- return;
9120
- }
9121
-
9122
- if (false === F.trigger('afterLoad', coming, previous)) {
9123
- coming.wrap.stop(true).trigger('onReset').remove();
9124
-
9125
- F.coming = null;
9126
-
9127
- return;
9128
- }
9129
-
9130
- if (previous) {
9131
- F.trigger('beforeChange', previous);
9132
-
9133
- previous.wrap.stop(true).removeClass('envirabox-opened')
9134
- .find('.envirabox-item, .envirabox-nav')
9135
- .remove();
9136
- }
9137
-
9138
- F.unbindEvents();
9139
-
9140
- current = coming;
9141
- content = coming.content;
9142
- type = coming.type;
9143
- scrolling = coming.scrolling;
9144
-
9145
- $.extend(F, {
9146
- wrap : current.wrap,
9147
- skin : current.skin,
9148
- outer : current.outer,
9149
- inner : current.inner,
9150
- current : current,
9151
- previous : previous
9152
- });
9153
-
9154
- href = current.href;
9155
-
9156
- switch (type) {
9157
- case 'inline':
9158
- case 'ajax':
9159
- case 'html':
9160
- if (current.selector) {
9161
- content = $('<div>').html(content).find(current.selector);
9162
-
9163
- } else if (isQuery(content)) {
9164
- if (!content.data(placeholder)) {
9165
- content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() );
9166
- }
9167
-
9168
- content = content.show().detach();
9169
-
9170
- current.wrap.bind('onReset', function () {
9171
- if ($(this).find(content).length) {
9172
- content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false);
9173
- }
9174
- });
9175
- }
9176
- break;
9177
-
9178
- case 'image':
9179
- content = current.tpl.image.replace(/\{href\}/g, href);
9180
- break;
9181
-
9182
- case 'swf':
9183
- content = '<object id="envirabox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>';
9184
- embed = '';
9185
-
9186
- $.each(current.swf, function(name, val) {
9187
- content += '<param name="' + name + '" value="' + val + '"></param>';
9188
- embed += ' ' + name + '="' + val + '"';
9189
- });
9190
-
9191
- content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>';
9192
- break;
9193
- }
9194
-
9195
- if (!(isQuery(content) && content.parent().is(current.inner))) {
9196
- current.inner.append( content );
9197
- }
9198
-
9199
- // Give a chance for helpers or callbacks to update elements
9200
- F.trigger('beforeShow');
9201
-
9202
- // Set scrolling before calculating dimensions
9203
- current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));
9204
-
9205
- // Set initial dimensions and start position
9206
- F._setDimension();
9207
-
9208
- F.reposition();
9209
-
9210
- F.isOpen = false;
9211
- F.coming = null;
9212
-
9213
- F.bindEvents();
9214
-
9215
- if (!F.isOpened) {
9216
- $('.envirabox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();
9217
-
9218
- } else if (previous.prevMethod) {
9219
- F.transitions[ previous.prevMethod ]();
9220
- }
9221
-
9222
- F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();
9223
-
9224
- F._preloadImages();
9225
- },
9226
-
9227
- _setDimension: function () {
9228
- var viewport = F.getViewport(),
9229
- steps = 0,
9230
- canShrink = false,
9231
- canExpand = false,
9232
- wrap = F.wrap,
9233
- skin = F.skin,
9234
- inner = F.inner,
9235
- current = F.current,
9236
- width = current.width,
9237
- height = current.height,
9238
- minWidth = current.minWidth,
9239
- minHeight = current.minHeight,
9240
- maxWidth = current.maxWidth,
9241
- maxHeight = current.maxHeight,
9242
- scrolling = current.scrolling,
9243
- scrollOut = current.scrollOutside ? current.scrollbarWidth : 0,
9244
- margin = current.margin,
9245
- wMargin = getScalar(margin[1] + margin[3]),
9246
- hMargin = getScalar(margin[0] + margin[2]),
9247
- wPadding,
9248
- hPadding,
9249
- wSpace,
9250
- hSpace,
9251
- origWidth,
9252
- origHeight,
9253
- origMaxWidth,
9254
- origMaxHeight,
9255
- ratio,
9256
- width_,
9257
- height_,
9258
- maxWidth_,
9259
- maxHeight_,
9260
- iframe,
9261
- body;
9262
-
9263
- // Reset dimensions so we could re-check actual size
9264
- wrap.add(skin).add(inner).width('auto').height('auto').removeClass('envirabox-tmp');
9265
-
9266
- wPadding = getScalar(skin.outerWidth(true) - skin.width());
9267
- hPadding = getScalar(skin.outerHeight(true) - skin.height());
9268
-
9269
- // Any space between content and viewport (margin, padding, border, title)
9270
- wSpace = wMargin + wPadding;
9271
- hSpace = hMargin + hPadding;
9272
-
9273
- origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width;
9274
- origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;
9275
-
9276
- // console.log ( "origWidth = " + origWidth );
9277
- // console.log ( "origHeight = " + origWidth );
9278
- // console.log ( "width = " + width );
9279
- // console.log ( "height = " + height );
9280
- // console.log ( "isPercentage(width) = " + isPercentage(width) );
9281
- // console.log ( "isPercentage(height) = " + isPercentage(height) );
9282
-
9283
- if (current.type === 'iframe') {
9284
- iframe = current.content;
9285
-
9286
- if (current.autoHeight && iframe.data('ready') === 1) {
9287
- try {
9288
- if (iframe[0].contentWindow.document.location) {
9289
- inner.width( origWidth ).height(9999);
9290
-
9291
- body = iframe.contents().find('body');
9292
-
9293
- if (scrollOut) {
9294
- body.css('overflow-x', 'hidden');
9295
- }
9296
-
9297
- origHeight = body.outerHeight(true);
9298
- }
9299
-
9300
- } catch (e) {}
9301
- }
9302
-
9303
- } else if (current.autoWidth || current.autoHeight) {
9304
- inner.addClass( 'envirabox-tmp' );
9305
-
9306
- // Set width or height in case we need to calculate only one dimension
9307
- if (!current.autoWidth) {
9308
- inner.width( origWidth );
9309
- }
9310
-
9311
- if (!current.autoHeight) {
9312
- inner.height( origHeight );
9313
- }
9314
-
9315
- if (current.autoWidth) {
9316
- origWidth = inner.width();
9317
- }
9318
-
9319
- if (current.autoHeight) {
9320
- origHeight = inner.height();
9321
- }
9322
-
9323
- inner.removeClass( 'envirabox-tmp' );
9324
- }
9325
-
9326
- width = getScalar( origWidth );
9327
- height = getScalar( origHeight );
9328
-
9329
- // console.log ( "width = " + width );
9330
- // console.log ( "height = " + height );
9331
-
9332
- ratio = origWidth / origHeight;
9333
-
9334
- // Calculations for the content
9335
- minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);
9336
- maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);
9337
-
9338
- minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);
9339
- maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);
9340
-
9341
- // These will be used to determine if wrap can fit in the viewport
9342
- origMaxWidth = maxWidth;
9343
- origMaxHeight = maxHeight;
9344
-
9345
- if (current.fitToView) {
9346
- maxWidth = Math.min(viewport.w - wSpace, maxWidth);
9347
- maxHeight = Math.min(viewport.h - hSpace, maxHeight);
9348
- }
9349
-
9350
- maxWidth_ = viewport.w - wMargin;
9351
- maxHeight_ = viewport.h - hMargin;
9352
-
9353
- if (current.aspectRatio) {
9354
- if (width > maxWidth) {
9355
- width = maxWidth;
9356
- height = getScalar(width / ratio);
9357
- }
9358
-
9359
- if (height > maxHeight) {
9360
- height = maxHeight;
9361
- width = getScalar(height * ratio);
9362
- }
9363
-
9364
- if (width < minWidth) {
9365
- width = minWidth;
9366
- height = getScalar(width / ratio);
9367
- }
9368
-
9369
- if (height < minHeight) {
9370
- height = minHeight;
9371
- width = getScalar(height * ratio);
9372
- }
9373
-
9374
- } else {
9375
- width = Math.max(minWidth, Math.min(width, maxWidth));
9376
-
9377
- if (current.autoHeight && current.type !== 'iframe') {
9378
- inner.width( width );
9379
-
9380
- height = inner.height();
9381
- }
9382
-
9383
- height = Math.max(minHeight, Math.min(height, maxHeight));
9384
- }
9385
-
9386
- // Try to fit inside viewport (including the title)
9387
- if (current.fitToView) {
9388
- inner.width( width ).height( height );
9389
-
9390
- wrap.width( width + wPadding );
9391
-
9392
- // Real wrap dimensions
9393
- width_ = wrap.width();
9394
- height_ = wrap.height();
9395
-
9396
- if (current.aspectRatio) {
9397
- while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
9398
- if (steps++ > 19) {
9399
- break;
9400
- }
9401
-
9402
- height = Math.max(minHeight, Math.min(maxHeight, height - 10));
9403
- width = getScalar(height * ratio);
9404
-
9405
- if (width < minWidth) {
9406
- width = minWidth;
9407
- height = getScalar(width / ratio);
9408
- }
9409
-
9410
- if (width > maxWidth) {
9411
- width = maxWidth;
9412
- height = getScalar(width / ratio);
9413
- }
9414
-
9415
- inner.width( width ).height( height );
9416
-
9417
- wrap.width( width + wPadding );
9418
-
9419
- width_ = wrap.width();
9420
- height_ = wrap.height();
9421
- }
9422
-
9423
- } else {
9424
- width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_)));
9425
- height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));
9426
- }
9427
- }
9428
-
9429
- if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {
9430
- width += scrollOut;
9431
- }
9432
-
9433
- // console.log( "before width: " + width);
9434
- // console.log( "before height: " + height);
9435
-
9436
- // width = width - (width * 0.01);
9437
- // height = height - (height * 0.01);
9438
-
9439
- // console.log( "after width: " + width);
9440
- // console.log( "after height: " + height);
9441
-
9442
- inner.width( width ).height( height );
9443
-
9444
- wrap.width( width + wPadding );
9445
-
9446
- width_ = wrap.width();
9447
- height_ = wrap.height();
9448
-
9449
- canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
9450
- canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));
9451
-
9452
- $.extend(current, {
9453
- dim : {
9454
- width : getValue( width_ ),
9455
- height : getValue( height_ )
9456
- },
9457
- origWidth : origWidth,
9458
- origHeight : origHeight,
9459
- canShrink : canShrink,
9460
- canExpand : canExpand,
9461
- wPadding : wPadding,
9462
- hPadding : hPadding,
9463
- wrapSpace : height_ - skin.outerHeight(true),
9464
- skinSpace : skin.height() - height
9465
- });
9466
-
9467
- if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
9468
- inner.height('auto');
9469
- }
9470
- },
9471
-
9472
- _getPosition: function (onlyAbsolute) {
9473
- var current = F.current,
9474
- viewport = F.getViewport(),
9475
- margin = current.margin,
9476
- width = F.wrap.width() + margin[1] + margin[3],
9477
- height = F.wrap.height() + margin[0] + margin[2],
9478
- rez = {
9479
- position: 'absolute',
9480
- top : margin[0],
9481
- left : margin[3]
9482
- };
9483
-
9484
- // Check for floating title and adjust height.
9485
- if (current.helpers.title.type && 'float' == current.helpers.title.type) {
9486
- height = height + $('.envirabox-skin .envirabox-title').height();
9487
- }
9488
-
9489
- if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {
9490
- rez.position = 'fixed';
9491
-
9492
- } else if (!current.locked) {
9493
- rez.top += viewport.y;
9494
- rez.left += viewport.x;
9495
- }
9496
-
9497
- rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio)));
9498
- rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio)));
9499
-
9500
- return rez;
9501
- },
9502
-
9503
- _afterZoomIn: function () {
9504
- var current = F.current;
9505
-
9506
- if (!current) {
9507
- return;
9508
- }
9509
-
9510
- F.isOpen = F.isOpened = true;
9511
-
9512
- F.wrap.css('overflow', 'visible').addClass('envirabox-opened').hide().show(0);
9513
-
9514
- F.update();
9515
-
9516
- // Assign a click event
9517
- if ( current.closeClick || (current.nextClick && F.group.length > 1) ) {
9518
- F.inner.css('cursor', 'pointer').bind('click.fb', function(e) {
9519
- if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {
9520
- e.preventDefault();
9521
-
9522
- F[ current.closeClick ? 'close' : 'next' ]();
9523
- }
9524
- });
9525
- }
9526
-
9527
- // Create a close button
9528
- if (current.closeBtn) {
9529
- $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) {
9530
- e.preventDefault();
9531
-
9532
- F.close();
9533
- });
9534
- }
9535
-
9536
- // Create navigation arrows
9537
- if (current.arrows && F.group.length > 1) {
9538
- if (current.loop || current.index > 0) {
9539
- $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);
9540
- }
9541
-
9542
- if (current.loop || current.index < F.group.length - 1) {
9543
- $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);
9544
- }
9545
- }
9546
-
9547
- F.trigger('afterShow');
9548
-
9549
- // Stop the slideshow if this is the last item
9550
- if (!current.loop && current.index === current.group.length - 1) {
9551
-
9552
- F.play( false );
9553
-
9554
- } else if (F.opts.autoPlay && !F.player.isActive) {
9555
- F.opts.autoPlay = false;
9556
-
9557
- F.play(true);
9558
- }
9559
- },
9560
-
9561
- _afterZoomOut: function ( obj ) {
9562
- obj = obj || F.current;
9563
-
9564
- $('.envirabox-wrap').trigger('onReset').remove();
9565
-
9566
- $.extend(F, {
9567
- group : {},
9568
- opts : {},
9569
- router : false,
9570
- current : null,
9571
- isActive : false,
9572
- isOpened : false,
9573
- isOpen : false,
9574
- isClosing : false,
9575
- wrap : null,
9576
- skin : null,
9577
- outer : null,
9578
- inner : null
9579
- });
9580
-
9581
- F.trigger('afterClose', obj);
9582
- }
9583
- });
9584
-
9585
- /*
9586
- * Default transitions
9587
- */
9588
-
9589
- F.transitions = {
9590
- getOrigPosition: function () {
9591
- var current = F.current,
9592
- element = current.element,
9593
- orig = current.orig,
9594
- pos = {},
9595
- width = 50,
9596
- height = 50,
9597
- hPadding = current.hPadding,
9598
- wPadding = current.wPadding,
9599
- viewport = F.getViewport();
9600
-
9601
- if (!orig && current.isDom && element.is(':visible')) {
9602
- orig = element.find('img:first');
9603
-
9604
- if (!orig.length) {
9605
- orig = element;
9606
- }
9607
- }
9608
-
9609
- if (isQuery(orig)) {
9610
- pos = orig.offset();
9611
-
9612
- if (orig.is('img')) {
9613
- width = orig.outerWidth();
9614
- height = orig.outerHeight();
9615
- }
9616
-
9617
- } else {
9618
- pos.top = viewport.y + (viewport.h - height) * current.topRatio;
9619
- pos.left = viewport.x + (viewport.w - width) * current.leftRatio;
9620
- }
9621
-
9622
- if (F.wrap.css('position') === 'fixed' || current.locked) {
9623
- pos.top -= viewport.y;
9624
- pos.left -= viewport.x;
9625
- }
9626
-
9627
- pos = {
9628
- top : getValue(pos.top - hPadding * current.topRatio),
9629
- left : getValue(pos.left - wPadding * current.leftRatio),
9630
- width : getValue(width + wPadding),
9631
- height : getValue(height + hPadding)
9632
- };
9633
-
9634
- return pos;
9635
- },
9636
-
9637
- step: function (now, fx) {
9638
- var ratio,
9639
- padding,
9640
- value,
9641
- prop = fx.prop,
9642
- current = F.current,
9643
- wrapSpace = current.wrapSpace,
9644
- skinSpace = current.skinSpace;
9645
-
9646
- if (prop === 'width' || prop === 'height') {
9647
- ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);
9648
-
9649
- if (F.isClosing) {
9650
- ratio = 1 - ratio;
9651
- }
9652
-
9653
- padding = prop === 'width' ? current.wPadding : current.hPadding;
9654
- value = now - padding;
9655
-
9656
- F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) );
9657
- F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );
9658
- }
9659
- },
9660
-
9661
- zoomIn: function () {
9662
- var current = F.current,
9663
- startPos = current.pos,
9664
- effect = current.openEffect,
9665
- elastic = effect === 'elastic',
9666
- endPos = $.extend({opacity : 1}, startPos);
9667
-
9668
- // Remove "position" property that breaks older IE
9669
- delete endPos.position;
9670
-
9671
- if (elastic) {
9672
- startPos = this.getOrigPosition();
9673
-
9674
- if (current.openOpacity) {
9675
- startPos.opacity = 0.1;
9676
- }
9677
-
9678
- } else if (effect === 'fade') {
9679
- startPos.opacity = 0.1;
9680
- }
9681
-
9682
- F.wrap.css(startPos).animate(endPos, {
9683
- duration : effect === 'none' ? 0 : current.openSpeed,
9684
- easing : current.openEasing,
9685
- step : elastic ? this.step : null,
9686
- complete : F._afterZoomIn
9687
- });
9688
- },
9689
-
9690
- zoomOut: function () {
9691
- var current = F.current,
9692
- effect = current.closeEffect,
9693
- elastic = effect === 'elastic',
9694
- endPos = {opacity : 0.1};
9695
-
9696
- if (elastic) {
9697
- endPos = this.getOrigPosition();
9698
-
9699
- if (current.closeOpacity) {
9700
- endPos.opacity = 0.1;
9701
- }
9702
- }
9703
-
9704
- F.wrap.animate(endPos, {
9705
- duration : effect === 'none' ? 0 : current.closeSpeed,
9706
- easing : current.closeEasing,
9707
- step : elastic ? this.step : null,
9708
- complete : F._afterZoomOut
9709
- });
9710
- },
9711
-
9712
- changeIn: function () {
9713
- var current = F.current,
9714
- effect = current.nextEffect,
9715
- startPos = current.pos,
9716
- endPos = { opacity : 1 },
9717
- direction = F.direction,
9718
- distance = 200,
9719
- field;
9720
-
9721
- startPos.opacity = 0.1;
9722
-
9723
- if (effect === 'elastic') {
9724
- field = direction === 'down' || direction === 'up' ? 'top' : 'left';
9725
-
9726
- if (direction === 'down' || direction === 'right') {
9727
- startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);
9728
- endPos[ field ] = '+=' + distance + 'px';
9729
-
9730
- } else {
9731
- startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);
9732
- endPos[ field ] = '-=' + distance + 'px';
9733
- }
9734
- }
9735
-
9736
- // Workaround for http://bugs.jquery.com/ticket/12273
9737
- if (effect === 'none') {
9738
- F._afterZoomIn();
9739
-
9740
- } else {
9741
- F.wrap.css(startPos).animate(endPos, {
9742
- duration : current.nextSpeed,
9743
- easing : current.nextEasing,
9744
- complete : F._afterZoomIn
9745
- });
9746
- }
9747
- },
9748
-
9749
- changeOut: function () {
9750
- var previous = F.previous,
9751
- effect = previous.prevEffect,
9752
- endPos = { opacity : 0.1 },
9753
- direction = F.direction,
9754
- distance = 200;
9755
-
9756
- if (effect === 'elastic') {
9757
- endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';
9758
- }
9759
-
9760
- previous.wrap.animate(endPos, {
9761
- duration : effect === 'none' ? 0 : previous.prevSpeed,
9762
- easing : previous.prevEasing,
9763
- complete : function () {
9764
- $(this).trigger('onReset').remove();
9765
- }
9766
- });
9767
- }
9768
- };
9769
-
9770
- /*
9771
- * Overlay helper
9772
- */
9773
-
9774
- F.helpers.overlay = {
9775
- defaults : {
9776
- closeClick : true, // if true, envirabox will be closed when user clicks on the overlay
9777
- speedOut : 200, // duration of fadeOut animation
9778
- showEarly : true, // indicates if should be opened immediately or wait until the content is ready
9779
- css : {}, // custom CSS properties
9780
- locked : !isTouch, // if true, the content will be locked into overlay
9781
- fixed : true // if false, the overlay CSS position property will not be set to "fixed"
9782
- },
9783
-
9784
- overlay : null, // current handle
9785
- fixed : false, // indicates if the overlay has position "fixed"
9786
- el : $('html'), // element that contains "the lock"
9787
-
9788
- // Public methods
9789
- create : function(opts) {
9790
- var parent;
9791
-
9792
- opts = $.extend({}, this.defaults, opts);
9793
-
9794
- if (this.overlay) {
9795
- this.close();
9796
- }
9797
-
9798
- parent = F.coming ? F.coming.parent : opts.parent;
9799
-
9800
- this.overlay = $('<div class="envirabox-overlay"></div>').appendTo( parent && parent.lenth ? parent : 'body' );
9801
- this.fixed = false;
9802
-
9803
- if (opts.fixed && F.defaults.fixed) {
9804
- this.overlay.addClass('envirabox-overlay-fixed');
9805
-
9806
- this.fixed = true;
9807
- }
9808
- },
9809
-
9810
- open : function(opts) {
9811
- var that = this;
9812
-
9813
- opts = $.extend({}, this.defaults, opts);
9814
-
9815
- if (this.overlay) {
9816
- this.overlay.unbind('.overlay').width('auto').height('auto');
9817
-
9818
- } else {
9819
- this.create(opts);
9820
- }
9821
-
9822
- if (!this.fixed) {
9823
- W.bind('resize.overlay', $.proxy( this.update, this) );
9824
-
9825
- this.update();
9826
- }
9827
-
9828
- if (opts.closeClick) {
9829
- this.overlay.bind('click.overlay', function(e) {
9830
- if ($(e.target).hasClass('envirabox-overlay')) {
9831
- if (F.isActive) {
9832
- F.close();
9833
- } else {
9834
- that.close();
9835
- }
9836
-
9837
- return false;
9838
- }
9839
- });
9840
- }
9841
-
9842
- this.overlay.css( opts.css ).show();
9843
- },
9844
-
9845
- close : function() {
9846
- W.unbind('resize.overlay');
9847
-
9848
- if (this.el.hasClass('envirabox-lock')) {
9849
- $('.envirabox-margin').removeClass('envirabox-margin');
9850
-
9851
- this.el.removeClass('envirabox-lock');
9852
-
9853
- W.scrollTop( this.scrollV ).scrollLeft( this.scrollH );
9854
- }
9855
-
9856
- $('.envirabox-overlay').remove().hide();
9857
-
9858
- $.extend(this, {
9859
- overlay : null,
9860
- fixed : false
9861
- });
9862
- },
9863
-
9864
- // Private, callbacks
9865
-
9866
- update : function () {
9867
- var width = '100%', offsetWidth;
9868
-
9869
- // Reset width/height so it will not mess
9870
- this.overlay.width(width).height('100%');
9871
-
9872
- // jQuery does not return reliable result for IE
9873
- if (IE) {
9874
- offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
9875
-
9876
- if (D.width() > offsetWidth) {
9877
- width = D.width();
9878
- }
9879
-
9880
- } else if (D.width() > W.width()) {
9881
- width = D.width();
9882
- }
9883
-
9884
-
9885
- this.overlay.width(width).height(D.height());
9886
- },
9887
-
9888
- // This is where we can manipulate DOM, because later it would cause iframes to reload
9889
- onReady : function (opts, obj) {
9890
- var overlay = this.overlay;
9891
-
9892
- $('.envirabox-overlay').stop(true, true);
9893
-
9894
- if (!overlay) {
9895
- this.create(opts);
9896
- }
9897
-
9898
- if (opts.locked && this.fixed && obj.fixed) {
9899
- obj.locked = this.overlay.append( obj.wrap );
9900
- obj.fixed = false;
9901
- }
9902
-
9903
- if (opts.showEarly === true) {
9904
- this.beforeShow.apply(this, arguments);
9905
- }
9906
- },
9907
-
9908
- beforeShow : function(opts, obj) {
9909
- if (obj.locked && !this.el.hasClass('envirabox-lock')) {
9910
- if (this.fixPosition !== false) {
9911
- $('*').filter(function(){
9912
- return ($(this).css('position') === 'fixed' && !$(this).hasClass("envirabox-overlay") && !$(this).hasClass("envirabox-wrap") );
9913
- }).addClass('envirabox-margin');
9914
- }
9915
-
9916
- this.el.addClass('envirabox-margin');
9917
-
9918
- this.scrollV = W.scrollTop();
9919
- this.scrollH = W.scrollLeft();
9920
-
9921
- this.el.addClass('envirabox-lock');
9922
-
9923
- W.scrollTop( this.scrollV ).scrollLeft( this.scrollH );
9924
- }
9925
-
9926
- this.open(opts);
9927
- },
9928
-
9929
- onUpdate : function() {
9930
- if (!this.fixed) {
9931
- this.update();
9932
- }
9933
- },
9934
-
9935
- afterClose: function (opts) {
9936
- // Remove overlay if exists and envirabox is not opening
9937
- // (e.g., it is not being open using afterClose callback)
9938
- if (this.overlay && !F.coming) {
9939
- this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this ));
9940
- }
9941
- }
9942
- };
9943
-
9944
- /*
9945
- * Title helper
9946
- */
9947
-
9948
- F.helpers.title = {
9949
- defaults : {
9950
- type : 'float', // 'float', 'inside', 'outside' or 'over',
9951
- position : 'bottom' // 'top' or 'bottom'
9952
- },
9953
-
9954
- beforeShow: function (opts) {
9955
- var current = F.current,
9956
- text = current.title,
9957
- type = opts.type,
9958
- title,
9959
- target;
9960
-
9961
- if ($.isFunction(text)) {
9962
- text = text.call(current.element, current);
9963
- }
9964
-
9965
- if (!isString(text) || $.trim(text) === '') {
9966
- return;
9967
- }
9968
-
9969
- title = $('<div class="envirabox-title envirabox-title-' + type + '-wrap">' + text + '</div>');
9970
-
9971
- switch (type) {
9972
- case 'inside':
9973
- target = F.skin;
9974
- break;
9975
-
9976
- case 'outside':
9977
- target = F.wrap;
9978
- break;
9979
-
9980
- case 'over':
9981
- target = F.inner;
9982
- break;
9983
-
9984
- default: // 'float'
9985
- target = F.skin;
9986
-
9987
- title.appendTo('body');
9988
-
9989
- if (IE) {
9990
- title.width( title.width() );
9991
- }
9992
-
9993
- title.wrapInner('<span class="child"></span>');
9994
-
9995
- //Increase bottom margin so this title will also fit into viewport
9996
- F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );
9997
- break;
9998
- }
9999
-
10000
- title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target);
10001
- }
10002
- };
10003
-
10004
- // jQuery plugin initialization
10005
- $.fn.envirabox = function (options) {
10006
- var index,
10007
- that = $(this),
10008
- selector = this.selector || '',
10009
- run = function(e) {
10010
- var what = $(this).blur(),
10011
- idx = index,
10012
- relType,
10013
- relVal;
10014
-
10015
- if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.envirabox-wrap')) {
10016
- relType = options.groupAttr || 'data-envirabox-group';
10017
- relVal = what.attr(relType);
10018
-
10019
- if (!relVal) {
10020
- relType = 'rel';
10021
- relVal = what.get(0)[ relType ];
10022
- }
10023
-
10024
- if (relVal && relVal !== '' && relVal !== 'nofollow') {
10025
- what = selector.length ? $(selector) : that;
10026
- what = what.filter('[' + relType + '="' + relVal + '"]');
10027
- idx = what.index(this);
10028
- }
10029
-
10030
- options.index = idx;
10031
-
10032
- // Stop an event from bubbling if everything is fine
10033
- if (F.open(what, options) !== false) {
10034
- e.preventDefault();
10035
- }
10036
- }
10037
- };
10038
-
10039
- options = options || {};
10040
- index = options.index || 0;
10041
-
10042
- if (!selector || options.live === false) {
10043
- that.unbind('click.fb-start').bind('click.fb-start', run);
10044
-
10045
- } else {
10046
- D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.envirabox-item, .envirabox-nav')", 'click.fb-start', run);
10047
- }
10048
-
10049
- this.filter('[data-envirabox-start=1]').trigger('click');
10050
-
10051
- return this;
10052
- };
10053
-
10054
- // Tests that need a body at doc ready
10055
- D.ready(function() {
10056
- var w1, w2;
10057
-
10058
- if ( $.scrollbarWidth === undefined ) {
10059
- // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth
10060
- $.scrollbarWidth = function() {
10061
- var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),
10062
- child = parent.children(),
10063
- width = child.innerWidth() - child.height( 99 ).innerWidth();
10064
-
10065
- parent.remove();
10066
-
10067
- return width;
10068
- };
10069
- }
10070
-
10071
- if ( $.support.fixedPosition === undefined ) {
10072
- $.support.fixedPosition = (function() {
10073
- var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'),
10074
- fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );
10075
-
10076
- elem.remove();
10077
-
10078
- return fixed;
10079
- }());
10080
- }
10081
-
10082
- $.extend(F.defaults, {
10083
- scrollbarWidth : $.scrollbarWidth(),
10084
- fixed : $.support.fixedPosition,
10085
- parent : $('body')
10086
- });
10087
-
10088
- //Get real width of page scroll-bar
10089
- w1 = $(window).width();
10090
-
10091
- H.addClass('envirabox-lock-test');
10092
-
10093
- w2 = $(window).width();
10094
-
10095
- H.removeClass('envirabox-lock-test');
10096
-
10097
- $("<style type='text/css'>.envirabox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head");
10098
- });
10099
-
10100
- }(window, document, jQuery));
10101
-
10102
- /*!
10103
- * Buttons helper for envirabox
10104
- * version: 1.0.5 (Mon, 15 Oct 2012)
10105
- * @requires envirabox v2.0 or later
10106
- *
10107
- * Usage:
10108
- * $(".envirabox").envirabox({
10109
- * helpers : {
10110
- * buttons: {
10111
- * position : 'top'
10112
- * }
10113
- * }
10114
- * });
10115
- *
10116
- */
10117
- ;(function ($) {
10118
- //Shortcut for envirabox object
10119
- var F = $.envirabox;
10120
-
10121
- //Add helper object
10122
- F.helpers.buttons = {
10123
- defaults : {
10124
- skipSingle : false, // disables if gallery contains single image
10125
- position : 'top', // 'top' or 'bottom'
10126
- inline : false, // if true, positioned to scroll with the content (typically set by the Comments helper)
10127
- tpl : '<div id="envirabox-buttons"><ul><li><a class="btnPrev" title="Previous" href="javascript:;"></a></li><li><a class="btnPlay" title="Start slideshow" href="javascript:;"></a></li><li><a class="btnNext" title="Next" href="javascript:;"></a></li><li><a class="btnToggle" title="Toggle size" href="javascript:;"></a></li><li><a class="btnClose" title="Close" href="javascript:;"></a></li></ul></div>'
10128
- },
10129
-
10130
- list : null,
10131
- buttons: null,
10132
-
10133
- beforeLoad: function (opts, obj) {
10134
- //Remove self if gallery do not have at least two items
10135
-
10136
- if (opts.skipSingle && obj.group.length < 2) {
10137
- obj.helpers.buttons = false;
10138
- obj.closeBtn = true;
10139
-
10140
- return;
10141
- }
10142
-
10143
- //Increase top margin to give space for buttons
10144
- obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30;
10145
-
10146
- // If both buttons and thumbnails are set to display at the top, add a CSS class to thumbnails to adjust their position.
10147
- if ( obj.helpers.thumbs != undefined && opts.position == 'top' && obj.helpers.thumbs.position == 'top' ) {
10148
- obj.helpers.thumbs.position = 'top has-other-content';
10149
- }
10150
-
10151
- // If both buttons and thumbnails are set to display at the bottom, add a CSS class to thumbnails to adjust their position.
10152
- if ( obj.helpers.thumbs != undefined && opts.position == 'bottom' && obj.helpers.thumbs.position == 'bottom' ) {
10153
- obj.helpers.thumbs.position = 'bottom has-other-content';
10154
- }
10155
- },
10156
-
10157
- onPlayStart: function () {
10158
- if (this.buttons) {
10159
- this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn');
10160
- }
10161
- },
10162
-
10163
- onPlayEnd: function () {
10164
- if (this.buttons) {
10165
- this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn');
10166
- }
10167
- },
10168
-
10169
- afterShow: function (opts, obj) {
10170
- var buttons = this.buttons;
10171
-
10172
- if (!buttons) {
10173
- this.list = $(opts.tpl).addClass(opts.position).appendTo('body');
10174
-
10175
- // If set to inline, add a class now
10176
- if ( opts.inline ) {
10177
- this.list.addClass( 'inline' );
10178
- }
10179
-
10180
- buttons = {
10181
- prev : this.list.find('.btnPrev').click( F.prev ),
10182
- next : this.list.find('.btnNext').click( F.next ),
10183
- play : this.list.find('.btnPlay').click( F.play ),
10184
- toggle : this.list.find('.btnToggle').click( F.toggle ),
10185
- close : this.list.find('.btnClose').click( F.close )
10186
- }
10187
- }
10188
-
10189
- //Prev
10190
- if (obj.index > 0 || obj.loop) {
10191
- buttons.prev.removeClass('btnDisabled');
10192
- } else {
10193
- buttons.prev.addClass('btnDisabled');
10194
- }
10195
-
10196
- //Next / Play
10197
- if (obj.loop || obj.index < obj.group.length - 1) {
10198
- buttons.next.removeClass('btnDisabled');
10199
- buttons.play.removeClass('btnDisabled');
10200
-
10201
- } else {
10202
- buttons.next.addClass('btnDisabled');
10203
- buttons.play.addClass('btnDisabled');
10204
- }
10205
-
10206
- this.buttons = buttons;
10207
-
10208
- this.onUpdate(opts, obj);
10209
- },
10210
-
10211
- onUpdate: function (opts, obj) {
10212
- var toggle;
10213
-
10214
- if (!this.buttons) {
10215
- return;
10216
- }
10217
-
10218
- toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn');
10219
-
10220
- //Size toggle button
10221
- if (obj.canShrink) {
10222
- toggle.addClass('btnToggleOn');
10223
-
10224
- } else if (!obj.canExpand) {
10225
- toggle.addClass('btnDisabled');
10226
- }
10227
- },
10228
-
10229
- beforeClose: function () {
10230
- if (this.list) {
10231
- this.list.remove();
10232
- }
10233
-
10234
- this.list = null;
10235
- this.buttons = null;
10236
- }
10237
- };
10238
-
10239
- }(jQuery));
10240
-
10241
- /*!
10242
- * Media helper for envirabox
10243
- * version: 1.0.6 (Fri, 14 Jun 2013)
10244
- * @requires envirabox v2.0 or later
10245
- *
10246
- * Usage:
10247
- * $(".envirabox").envirabox({
10248
- * helpers : {
10249
- * media: true
10250
- * }
10251
- * });
10252
- *
10253
- * Set custom URL parameters:
10254
- * $(".envirabox").envirabox({
10255
- * helpers : {
10256
- * media: {
10257
- * youtube : {
10258
- * params : {
10259
- * autoplay : 0
10260
- * }
10261
- * }
10262
- * }
10263
- * }
10264
- * });
10265
- *
10266
- * Or:
10267
- * $(".envirabox").envirabox({,
10268
- * helpers : {
10269
- * media: true
10270
- * },
10271
- * youtube : {
10272
- * autoplay: 0
10273
- * }
10274
- * });
10275
- *
10276
- * Supports:
10277
- *
10278
- * Youtube
10279
- * http://www.youtube.com/watch?v=opj24KnzrWo
10280
- * http://www.youtube.com/embed/opj24KnzrWo
10281
- * http://youtu.be/opj24KnzrWo
10282
- * http://www.youtube-nocookie.com/embed/opj24KnzrWo
10283
- * Vimeo
10284
- * http://vimeo.com/40648169
10285
- * http://vimeo.com/channels/staffpicks/38843628
10286
- * http://vimeo.com/groups/surrealism/videos/36516384
10287
- * http://player.vimeo.com/video/45074303
10288
- * Metacafe
10289
- * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/
10290
- * http://www.metacafe.com/watch/7635964/
10291
- * Dailymotion
10292
- * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people
10293
- * Twitvid
10294
- * http://twitvid.com/QY7MD
10295
- * Twitpic
10296
- * http://twitpic.com/7p93st
10297
- * Instagram
10298
- * http://instagr.am/p/IejkuUGxQn/
10299
- * http://instagram.com/p/IejkuUGxQn/
10300
- * Google maps
10301
- * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17
10302
- * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
10303
- * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56
10304
- */
10305
- ;(function ($) {
10306
- "use strict";
10307
-
10308
- //Shortcut for envirabox object
10309
- var F = $.envirabox,
10310
- format = function( url, rez, params ) {
10311
- params = params || '';
10312
-
10313
- if ( $.type( params ) === "object" ) {
10314
- params = $.param(params, true);
10315
- }
10316
-
10317
- $.each(rez, function(key, value) {
10318
- url = url.replace( '$' + key, value || '' );
10319
- });
10320
-
10321
- if (params.length) {
10322
- url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params;
10323
- }
10324
-
10325
- return url;
10326
- };
10327
-
10328
- //Add helper object
10329
- F.helpers.media = {
10330
- defaults : {
10331
- youtube : {
10332
- matcher : /(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i,
10333
- params : {
10334
- autoplay : 1,
10335
- autohide : 1,
10336
- fs : 1,
10337
- rel : 0,
10338
- hd : 1,
10339
- wmode : 'opaque',
10340
- enablejsapi : 1
10341
- },
10342
- type : 'iframe',
10343
- url : '//www.youtube.com/embed/$3'
10344
- },
10345
- vimeo : {
10346
- matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/,
10347
- params : {
10348
- autoplay : 1,
10349
- hd : 1,
10350
- show_title : 1,
10351
- show_byline : 1,
10352
- show_portrait : 0,
10353
- fullscreen : 1
10354
- },
10355
- type : 'iframe',
10356
- url : '//player.vimeo.com/video/$1'
10357
- },
10358
- metacafe : {
10359
- matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/,
10360
- params : {
10361
- autoPlay : 'yes'
10362
- },
10363
- type : 'swf',
10364
- url : function( rez, params, obj ) {
10365
- obj.swf.flashVars = 'playerVars=' + $.param( params, true );
10366
-
10367
- return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf';
10368
- }
10369
- },
10370
- dailymotion : {
10371
- matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
10372
- params : {
10373
- additionalInfos : 0,
10374
- autoStart : 1
10375
- },
10376
- type : 'swf',
10377
- url : '//www.dailymotion.com/swf/video/$1'
10378
- },
10379
- twitvid : {
10380
- matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i,
10381
- params : {
10382
- autoplay : 0
10383
- },
10384
- type : 'iframe',
10385
- url : '//www.twitvid.com/embed.php?guid=$1'
10386
- },
10387
- twitpic : {
10388
- matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i,
10389
- type : 'image',
10390
- url : '//twitpic.com/show/full/$1/'
10391
- },
10392
- instagram : {
10393
- matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
10394
- type : 'image',
10395
- url : '//$1/p/$2/media/?size=l'
10396
- },
10397
- google_maps : {
10398
- matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i,
10399
- type : 'iframe',
10400
- url : function( rez ) {
10401
- return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed');
10402
- }
10403
- }
10404
- },
10405
-
10406
- beforeLoad : function(opts, obj) {
10407
- var url = obj.href || '',
10408
- type = false,
10409
- what,
10410
- item,
10411
- rez,
10412
- params;
10413
-
10414
- for (what in opts) {
10415
- if (opts.hasOwnProperty(what)) {
10416
- item = opts[ what ];
10417
- rez = url.match( item.matcher );
10418
-
10419
- if (rez) {
10420
- type = item.type;
10421
- params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null));
10422
-
10423
- url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params );
10424
-
10425
- break;
10426
- }
10427
- }
10428
- }
10429
-
10430
- if (type) {
10431
- obj.href = url;
10432
- obj.type = type;
10433
-
10434
- obj.autoHeight = false;
10435
- }
10436
- }
10437
- };
10438
-
10439
- }(jQuery));
10440
-
10441
- /*!
10442
- * Thumbnail helper for envirabox
10443
- * version: 1.0.7 (Mon, 01 Oct 2012)
10444
- * @requires envirabox v2.0 or later
10445
- *
10446
- * Usage:
10447
- * $(".envirabox").envirabox({
10448
- * helpers : {
10449
- * thumbs: {
10450
- * width : 50,
10451
- * height : 50
10452
- * }
10453
- * }
10454
- * });
10455
- *
10456
- */
10457
- ;(function ($) {
10458
- //Shortcut for envirabox object
10459
- var F = $.envirabox;
10460
-
10461
- //Add helper object
10462
- F.helpers.thumbs = {
10463
- defaults : {
10464
- width : 50, // thumbnail width
10465
- height : 50, // thumbnail height
10466
- position : 'bottom', // 'top' or 'bottom'
10467
- inline : false, // if true, positioned to scroll with the content (typically set by the Comments helper)
10468
- source : function ( item ) { // function to obtain the URL of the thumbnail image
10469
- var href;
10470
-
10471
- if (item.element) {
10472
- href = $(item.element).find('img').attr('src');
10473
- }
10474
-
10475
- if (!href && item.type === 'image' && item.href) {
10476
- href = item.href;
10477
- }
10478
-
10479
- return href;
10480
- }
10481
- },
10482
-
10483
- wrap : null,
10484
- list : null,
10485
- width : 0,
10486
-
10487
- init: function (opts, obj) {
10488
- var that = this,
10489
- list,
10490
- thumbWidth = opts.width,
10491
- thumbHeight = opts.height,
10492
- thumbSource = opts.source;
10493
-
10494
- //Build list structure
10495
- list = '';
10496
-
10497
- for (var n = 0; n < obj.group.length; n++) {
10498
- list += '<li><a style="width:' + thumbWidth + 'px;height:' + thumbHeight + 'px;" href="javascript:jQuery.envirabox.jumpto(' + n + ');"></a></li>';
10499
- }
10500
-
10501
- this.wrap = $('<div id="envirabox-thumbs"></div>').addClass(opts.position).appendTo('body');
10502
- this.list = $('<ul>' + list + '</ul>').appendTo(this.wrap);
10503
-
10504
- //Load each thumbnail
10505
- $.each(obj.group, function (i) {
10506
- var el = obj.group[ i ],
10507
- href = thumbSource( el );
10508
-
10509
- if (!href) {
10510
- return;
10511
- }
10512
-
10513
- $("<img />").load(function () {
10514
- var width = this.width,
10515
- height = this.height,
10516
- widthRatio, heightRatio, parent;
10517
-
10518
- if (!that.list || !width || !height) {
10519
- return;
10520
- }
10521
-
10522
- //Calculate thumbnail width/height and center it
10523
- widthRatio = width / thumbWidth;
10524
- heightRatio = height / thumbHeight;
10525
-
10526
- parent = that.list.children().eq(i).find('a');
10527
-
10528
- if (widthRatio >= 1 && heightRatio >= 1) {
10529
- if (widthRatio > heightRatio) {
10530
- width = Math.floor(width / heightRatio);
10531
- height = thumbHeight;
10532
-
10533
- } else {
10534
- width = thumbWidth;
10535
- height = Math.floor(height / widthRatio);
10536
- }
10537
- }
10538
-
10539
- $(this).css({
10540
- width : width,
10541
- height : height,
10542
- top : Math.floor(thumbHeight / 2 - height / 2),
10543
- left : Math.floor(thumbWidth / 2 - width / 2)
10544
- });
10545
-
10546
- parent.width(thumbWidth).height(thumbHeight);
10547
-
10548
- $(this).hide().appendTo(parent).fadeIn(300);
10549
-
10550
- })
10551
- .attr('src', href)
10552
- .attr('title', el.title);
10553
- });
10554
-
10555
- //Set initial width
10556
- // outerWidth(true) doesn't include border width, so we calculate a single thumbnail's width manually
10557
- // Old code is commented out.
10558
- var thumb = this.list.children().eq(0),
10559
- thumb_link = $('a', $(thumb));
10560
-
10561
- // Link left border + link right border + li left margin + li right margin + li width = thumbnail width
10562
- this.width = parseInt( thumb_link.css('border-left-width') ) + parseInt( thumb_link.css('border-left-width') ) + parseInt( thumb.css('margin-left') ) + parseInt( thumb.css('margin-right') ) + parseInt( thumb.css('width') );
10563
-
10564
- /*
10565
- // Debug
10566
- console.log( parseInt( thumb_link.css('border-left-width') ) );
10567
- console.log( parseInt( thumb_link.css('border-right-width') ) );
10568
- console.log( parseInt( thumb.css('margin-left') ) );
10569
- console.log( parseInt( thumb.css('margin-right') ) );
10570
- console.log( parseInt( thumb.css('width') ) );
10571
- console.log( this.width );
10572
- */
10573
-
10574
- this.list.width(this.width * obj.group.length).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)));
10575
-
10576
- //this.width = this.list.children().eq(0).outerWidth(true);
10577
- //this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)));
10578
- },
10579
-
10580
- beforeLoad: function (opts, obj) {
10581
- //Remove self if gallery do not have at least two items
10582
- if (obj.group.length < 2) {
10583
- obj.helpers.thumbs = false;
10584
-
10585
- return;
10586
- }
10587
-
10588
- //Increase bottom margin to give space for thumbs
10589
- obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15);
10590
- },
10591
-
10592
- afterShow: function (opts, obj) {
10593
- //Check if exists and create or update list
10594
- if (this.list) {
10595
- this.onUpdate(opts, obj);
10596
-
10597
- } else {
10598
- this.init(opts, obj);
10599
- }
10600
-
10601
- // If set to inline, add a class now
10602
- if ( opts.inline ) {
10603
- this.wrap.addClass( 'inline' );
10604
- }
10605
-
10606
- //Set active element
10607
- this.list.children().removeClass('active').eq(obj.index).addClass('active');
10608
- },
10609
-
10610
- //Center list
10611
- onUpdate: function (opts, obj) {
10612
- if (this.list) {
10613
- this.list.stop(true).animate({
10614
- 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))
10615
- }, 150);
10616
- }
10617
- },
10618
-
10619
- beforeClose: function () {
10620
- if (this.wrap) {
10621
- this.wrap.remove();
10622
- }
10623
-
10624
- this.wrap = null;
10625
- this.list = null;
10626
- this.width = 0;
10627
- }
10628
- }
10629
-
10630
- }(jQuery));
10631
-
1
+ function jg_effect_desaturate(t){var e=!!document.createElement("canvas").getContext;if(e){var i=document.createElement("canvas"),n=i.getContext("2d"),o,r,s,a=0,h,l=new Image;for(l.src=t,i.width=l.width,i.height=l.height,n.drawImage(l,0,0),o=n.getImageData(0,0,i.width,i.height),r=o.data,s=r.length;s>a;a+=4)h=.3*r[a]+.59*r[a+1]+.11*r[a+2],r[a]=r[a+1]=r[a+2]=h;return n.putImageData(o,0,0),i.toDataURL()}return t}function jg_effect_threshold(t){var e=!!document.createElement("canvas").getContext;if(e){var i=document.createElement("canvas"),n=i.getContext("2d"),o,r,s,a=0,h,l=new Image;l.src=t,i.width=l.width,i.height=l.height,n.drawImage(l,0,0),o=n.getImageData(0,0,i.width,i.height),r=o.data,s=r.length,threshold=120;for(var a=0;s>a;a+=4){var u=r[a],d=r[a+1],c=r[a+2],p=.2126*u+.7152*d+.0722*c>=threshold?255:0;r[a]=r[a+1]=r[a+2]=p}return n.putImageData(o,0,0),i.toDataURL()}return t}function jg_effect_blur(t){var e=!!document.createElement("canvas").getContext;if(e){var i=document.createElement("canvas"),n=i.getContext("2d"),o,r,s,a=0,h,l=0,u=0,d=30,c=1;img=new Image,img.src=t,i.width=img.width,i.height=img.height,n.drawImage(img,0,0);var o,p=img.width,f=img.height;o=n.getImageData(l,u,p,f);for(var g=o.data,m,v,y,w,b,x,a,S,I,E,_,C,T,R,z=p-1,j=f-1,O=p*f,L=d+1,k=[],M=[],D=[],H=mul_table[d],W=shg_table[d],A=[],P=[];c-- >0;){for(T=C=0,x=0;f>x;x++){for(m=g[T]*L,v=g[T+1]*L,y=g[T+2]*L,a=1;d>=a;a++)S=T+((a>z?z:a)<<2),m+=g[S++],v+=g[S++],y+=g[S++];for(b=0;p>b;b++)k[C]=m,M[C]=v,D[C]=y,0==x&&(A[b]=((S=b+L)<z?S:z)<<2,P[b]=(S=b-d)>0?S<<2:0),I=T+A[b],E=T+P[b],m+=g[I++]-g[E++],v+=g[I++]-g[E++],y+=g[I++]-g[E++],C++;T+=p<<2}for(b=0;p>b;b++){for(_=b,m=k[_]*L,v=M[_]*L,y=D[_]*L,a=1;d>=a;a++)_+=a>j?0:p,m+=k[_],v+=M[_],y+=D[_];for(C=b<<2,x=0;f>x;x++)g[C]=m*H>>>W,g[C+1]=v*H>>>W,g[C+2]=y*H>>>W,0==b&&(A[x]=((S=x+L)<j?S:j)*p,P[x]=(S=x-d)>0?S*p:0),I=b+A[x],E=b+P[x],m+=k[I]-k[E],v+=M[I]-M[E],y+=D[I]-D[E],C+=p<<2}}return n.putImageData(o,l,u),i.toDataURL()}return t}function jg_effect_vintage(t){var e={onError:function(){alert("ERROR")}},i={vignette:1,sepia:!0,noise:50,desaturate:.2,lighten:.1};new VintageJS(t,e,i)}function boxBlurImage(t,e,i,n,o){var r=document.getElementById(t),s=r.naturalWidth,a=r.naturalHeight,h=document.getElementById(e);h.style.width=s+"px",h.style.height=a+"px",h.width=s,h.height=a;var l=h.getContext("2d");l.clearRect(0,0,s,a),l.drawImage(r,0,0),isNaN(i)||1>i||(n?boxBlurCanvasRGBA(e,0,0,s,a,i,o):boxBlurCanvasRGB(e,0,0,s,a,i,o))}function boxBlurCanvasRGBA(t,e,i,n,o,r,s){if(!(isNaN(r)||1>r)){r|=0,isNaN(s)&&(s=1),s|=0,s>3&&(s=3),1>s&&(s=1);var a=document.getElementById(t),h=a.getContext("2d"),l;try{try{l=h.getImageData(e,i,n,o)}catch(u){try{netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"),l=h.getImageData(e,i,n,o)}catch(u){throw alert("Cannot access local image"),new Error("unable to access local image data: "+u);return}}}catch(u){throw alert("Cannot access image"),new Error("unable to access image data: "+u);return}for(var d=l.data,c,p,f,g,m,v,y,w,b,x,S,I,E,_,C,T=n-1,R=o-1,z=n*o,j=r+1,O=mul_table[r],L=shg_table[r],k=[],M=[],D=[],H=[],W=[],A=[];s-- >0;){for(E=I=0,v=0;o>v;v++){for(c=d[E]*j,p=d[E+1]*j,f=d[E+2]*j,g=d[E+3]*j,y=1;r>=y;y++)w=E+((y>T?T:y)<<2),c+=d[w++],p+=d[w++],f+=d[w++],g+=d[w];for(m=0;n>m;m++)k[I]=c,M[I]=p,D[I]=f,H[I]=g,0==v&&(W[m]=((w=m+j)<T?w:T)<<2,A[m]=(w=m-r)>0?w<<2:0),b=E+W[m],x=E+A[m],c+=d[b++]-d[x++],p+=d[b++]-d[x++],f+=d[b++]-d[x++],g+=d[b]-d[x],I++;E+=n<<2}for(m=0;n>m;m++){for(S=m,c=k[S]*j,p=M[S]*j,f=D[S]*j,g=H[S]*j,y=1;r>=y;y++)S+=y>R?0:n,c+=k[S],p+=M[S],f+=D[S],g+=H[S];for(I=m<<2,v=0;o>v;v++)d[I+3]=C=g*O>>>L,C>0?(C=255/C,d[I]=(c*O>>>L)*C,d[I+1]=(p*O>>>L)*C,d[I+2]=(f*O>>>L)*C):d[I]=d[I+1]=d[I+2]=0,0==m&&(W[v]=((w=v+j)<R?w:R)*n,A[v]=(w=v-r)>0?w*n:0),b=m+W[v],x=m+A[v],c+=k[b]-k[x],p+=M[b]-M[x],f+=D[b]-D[x],g+=H[b]-H[x],I+=n<<2}}h.putImageData(l,e,i)}}function boxBlurCanvasRGB(t,e,i,n,o,r,s){if(!(isNaN(r)||1>r)){r|=0,isNaN(s)&&(s=1),s|=0,s>3&&(s=3),1>s&&(s=1);var a=t,h=a.getContext("2d"),l;try{try{l=h.getImageData(e,i,n,o)}catch(u){try{netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"),l=h.getImageData(e,i,n,o)}catch(u){throw alert("Cannot access local image"),new Error("unable to access local image data: "+u);return}}}catch(u){throw alert("Cannot access image"),new Error("unable to access image data: "+u);return}for(var d=l.data,c,p,f,g,m,v,y,w,b,x,S,I,E,_,C=n-1,T=o-1,R=n*o,z=r+1,j=[],O=[],L=[],k=mul_table[r],M=shg_table[r],D=[],H=[];s-- >0;){for(E=I=0,v=0;o>v;v++){for(c=d[E]*z,p=d[E+1]*z,f=d[E+2]*z,y=1;r>=y;y++)w=E+((y>C?C:y)<<2),c+=d[w++],p+=d[w++],f+=d[w++];for(m=0;n>m;m++)j[I]=c,O[I]=p,L[I]=f,0==v&&(D[m]=((w=m+z)<C?w:C)<<2,H[m]=(w=m-r)>0?w<<2:0),b=E+D[m],x=E+H[m],c+=d[b++]-d[x++],p+=d[b++]-d[x++],f+=d[b++]-d[x++],I++;E+=n<<2}for(m=0;n>m;m++){for(S=m,c=j[S]*z,p=O[S]*z,f=L[S]*z,y=1;r>=y;y++)S+=y>T?0:n,c+=j[S],p+=O[S],f+=L[S];for(I=m<<2,v=0;o>v;v++)d[I]=c*k>>>M,d[I+1]=p*k>>>M,d[I+2]=f*k>>>M,0==m&&(D[v]=((w=v+z)<T?w:T)*n,H[v]=(w=v-r)>0?w*n:0),b=m+D[v],x=m+H[v],c+=j[b]-j[x],p+=O[b]-O[x],f+=L[b]-L[x],I+=n<<2}}h.putImageData(l,e,i)}}jQuery(document).ready(function($){$("body").on("click",'div.envirabox-title a[href*="#"]:not([href="#"])',function(t){return location.pathname.replace(/^\//,"")==this.pathname.replace(/^\//,"")&&location.hostname==this.hostname?($.envirabox.close(),!1):void 0})}),function($){function t(){return $("body").height()>$(window).height()}var e=function(t,e){this.settings=e,this.checkSettings(),this.imgAnalyzerTimeout=null,this.entries=null,this.buildingRow={entriesBuff:[],width:0,height:0,aspectRatio:0},this.lastAnalyzedIndex=-1,this["yield"]={every:2,flushed:0},this.border=e.border>=0?e.border:e.margins,this.maxRowHeight=this.retrieveMaxRowHeight(),this.suffixRanges=this.retrieveSuffixRanges(),this.offY=this.border,this.rows=0,this.spinner={phase:0,timeSlot:150,$el:$('<div class="spinner"><span></span><span></span><span></span></div>'),intervalId:null},this.checkWidthIntervalId=null,this.galleryWidth=t.width(),this.$gallery=t};e.prototype.getSuffix=function(t,e){var i,n;for(i=t>e?t:e,n=0;n<this.suffixRanges.length;n++)if(i<=this.suffixRanges[n])return this.settings.sizeRangeSuffixes[this.suffixRanges[n]];return this.settings.sizeRangeSuffixes[this.suffixRanges[n-1]]},e.prototype.removeSuffix=function(t,e){return t.substring(0,t.length-e.length)},e.prototype.endsWith=function(t,e){return-1!==t.indexOf(e,t.length-e.length)},e.prototype.getUsedSuffix=function(t){for(var e in this.settings.sizeRangeSuffixes)if(this.settings.sizeRangeSuffixes.hasOwnProperty(e)){if(0===this.settings.sizeRangeSuffixes[e].length)continue;if(this.endsWith(t,this.settings.sizeRangeSuffixes[e]))return this.settings.sizeRangeSuffixes[e]}return""},e.prototype.newSrc=function(t,e,i){var n;if(this.settings.thumbnailPath)n=this.settings.thumbnailPath(t,e,i);else{var o=t.match(this.settings.extension),r=null!==o?o[0]:"";n=t.replace(this.settings.extension,""),n=this.removeSuffix(n,this.getUsedSuffix(n)),n+=this.getSuffix(e,i)+r}return n},e.prototype.showImg=function(t,e){this.settings.cssAnimation?(t.addClass("entry-visible"),e&&e()):t.stop().fadeTo(this.settings.imagesAnimationDuration,1,e)},e.prototype.extractImgSrcFromImage=function(t){var e="undefined"!=typeof t.data("safe-src")?t.data("safe-src"):t.attr("src");return t.data("jg.originalSrc",e),e},e.prototype.imgFromEntry=function(t){var e=t.find("> img");return 0===e.length&&(e=t.find("> a > img")),0===e.length?null:e},e.prototype.captionFromEntry=function(t){var e=t.find("> .caption");return 0===e.length?null:e},e.prototype.displayEntry=function(t,e,i,n,o,r){t.width(n),t.height(r),t.css("top",i),t.css("left",e);var s=this.imgFromEntry(t);if(null!==s){s.css("width",n),s.css("height",o),s.css("margin-left",-n/2),s.css("margin-top",-o/2);var a=s.attr("src"),h=this.newSrc(a,n,o);s.one("error",function(){s.attr("src",s.data("jg.originalSrc"))});var l=function(){a!==h&&s.attr("src",h)};"skipped"===t.data("jg.loaded")?this.onImageEvent(a,$.proxy(function(){this.showImg(t,l),t.data("jg.loaded",!0)},this)):this.showImg(t,l)}else this.showImg(t);this.displayEntryCaption(t)},e.prototype.displayEntryCaption=function(t){var e=this.imgFromEntry(t);if(null!==e&&this.settings.captions){var i=this.captionFromEntry(t);if(null===i){var n=e.attr("alt");this.isValidCaption(n)||(n=t.attr("title")),this.isValidCaption(n)&&(i=$('<div class="caption">'+n+"</div>"),t.append(i),t.data("jg.createdCaption",!0))}null!==i&&(this.settings.cssAnimation||i.stop().fadeTo(0,this.settings.captionSettings.nonVisibleOpacity),this.addCaptionEventsHandlers(t))}else this.removeCaptionEventsHandlers(t)},e.prototype.isValidCaption=function(t){return"undefined"!=typeof t&&t.length>0},e.prototype.onEntryMouseEnterForCaption=function(t){var e=this.captionFromEntry($(t.currentTarget));this.settings.cssAnimation?e.addClass("caption-visible").removeClass("caption-hidden"):e.stop().fadeTo(this.settings.captionSettings.animationDuration,this.settings.captionSettings.visibleOpacity)},e.prototype.onEntryMouseLeaveForCaption=function(t){var e=this.captionFromEntry($(t.currentTarget));this.settings.cssAnimation?e.removeClass("caption-visible").removeClass("caption-hidden"):e.stop().fadeTo(this.settings.captionSettings.animationDuration,this.settings.captionSettings.nonVisibleOpacity)},e.prototype.addCaptionEventsHandlers=function(t){var e=t.data("jg.captionMouseEvents");"undefined"==typeof e&&(e={mouseenter:$.proxy(this.onEntryMouseEnterForCaption,this),mouseleave:$.proxy(this.onEntryMouseLeaveForCaption,this)},t.on("mouseenter",void 0,void 0,e.mouseenter),t.on("mouseleave",void 0,void 0,e.mouseleave),t.data("jg.captionMouseEvents",e))},e.prototype.removeCaptionEventsHandlers=function(t){var e=t.data("jg.captionMouseEvents");"undefined"!=typeof e&&(t.off("mouseenter",void 0,e.mouseenter),t.off("mouseleave",void 0,e.mouseleave),t.removeData("jg.captionMouseEvents"))},e.prototype.prepareBuildingRow=function(t){var e,i,n,o,r,s=!0,a=0,h=this.galleryWidth-2*this.border-(this.buildingRow.entriesBuff.length-1)*this.settings.margins,l=h/this.buildingRow.aspectRatio,u=this.settings.rowHeight,d=this.buildingRow.width/h>this.settings.justifyThreshold;if(t&&"hide"===this.settings.lastRow&&!d){for(e=0;e<this.buildingRow.entriesBuff.length;e++)i=this.buildingRow.entriesBuff[e],this.settings.cssAnimation?i.removeClass("entry-visible"):i.stop().fadeTo(0,0);return-1}for(t&&!d&&"justify"!==this.settings.lastRow&&"hide"!==this.settings.lastRow&&(s=!1,this.rows>0&&(u=(this.offY-this.border-this.settings.margins*this.rows)/this.rows,s=u*this.buildingRow.aspectRatio/h>this.settings.justifyThreshold)),e=0;e<this.buildingRow.entriesBuff.length;e++)i=this.buildingRow.entriesBuff[e],n=i.data("jg.width")/i.data("jg.height"),s?(o=e===this.buildingRow.entriesBuff.length-1?h:l*n,r=l):(o=u*n,r=u),h-=Math.round(o),i.data("jg.jwidth",Math.round(o)),i.data("jg.jheight",Math.ceil(r)),(0===e||a>r)&&(a=r);return this.settings.fixedHeight&&a>this.settings.rowHeight&&(a=this.settings.rowHeight),this.buildingRow.height=a,s},e.prototype.clearBuildingRow=function(){this.buildingRow.entriesBuff=[],this.buildingRow.aspectRatio=0,this.buildingRow.width=0},e.prototype.flushRow=function(t){var e=this.settings,i,n,o=this.border,r;if(n=this.prepareBuildingRow(t),t&&"hide"===e.lastRow&&-1===n)return void this.clearBuildingRow();if(this.maxRowHeight.isPercentage?this.maxRowHeight.value*e.rowHeight<this.buildingRow.height&&(this.buildingRow.height=this.maxRowHeight.value*e.rowHeight):this.maxRowHeight.value>0&&this.maxRowHeight.value<this.buildingRow.height&&(this.buildingRow.height=this.maxRowHeight.value),"center"===e.lastRow||"right"===e.lastRow){var s=this.galleryWidth-2*this.border-(this.buildingRow.entriesBuff.length-1)*e.margins;for(r=0;r<this.buildingRow.entriesBuff.length;r++)i=this.buildingRow.entriesBuff[r],s-=i.data("jg.jwidth");"center"===e.lastRow?o+=s/2:"right"===e.lastRow&&(o+=s)}for(r=0;r<this.buildingRow.entriesBuff.length;r++)i=this.buildingRow.entriesBuff[r],this.displayEntry(i,o,this.offY,i.data("jg.jwidth"),i.data("jg.jheight"),this.buildingRow.height),o+=i.data("jg.jwidth")+e.margins;this.galleryHeightToSet=this.offY+this.buildingRow.height+this.border,this.$gallery.height(this.galleryHeightToSet+this.getSpinnerHeight()),(!t||this.buildingRow.height<=e.rowHeight&&n)&&(this.offY+=this.buildingRow.height+e.margins,this.rows+=1,this.clearBuildingRow(),this.$gallery.trigger("jg.rowflush"))};var i=!1;e.prototype.checkWidth=function(){this.checkWidthIntervalId=setInterval($.proxy(function(){var e=parseFloat(this.$gallery.width());t()===i?Math.abs(e-this.galleryWidth)>this.settings.refreshSensitivity&&(this.galleryWidth=e,this.rewind(),this.startImgAnalyzer(!0)):(i=t(),this.galleryWidth=e)},this),this.settings.refreshTime)},e.prototype.isSpinnerActive=function(){return null!==this.spinner.intervalId},e.prototype.getSpinnerHeight=function(){return this.spinner.$el.innerHeight()},e.prototype.stopLoadingSpinnerAnimation=function(){clearInterval(this.spinner.intervalId),this.spinner.intervalId=null,this.$gallery.height(this.$gallery.height()-this.getSpinnerHeight()),this.spinner.$el.detach()},e.prototype.startLoadingSpinnerAnimation=function(){var t=this.spinner,e=t.$el.find("span");clearInterval(t.intervalId),this.$gallery.append(t.$el),this.$gallery.height(this.offY+this.buildingRow.height+this.getSpinnerHeight()),t.intervalId=setInterval(function(){t.phase<e.length?e.eq(t.phase).fadeTo(t.timeSlot,1):e.eq(t.phase-e.length).fadeTo(t.timeSlot,0),t.phase=(t.phase+1)%(2*e.length)},t.timeSlot)},e.prototype.rewind=function(){this.lastAnalyzedIndex=-1,this.offY=this.border,this.rows=0,this.clearBuildingRow()},e.prototype.updateEntries=function(t){return this.entries=this.$gallery.find(this.settings.selector).toArray(),0===this.entries.length?!1:(this.settings.filter?this.modifyEntries(this.filterArray,t):this.modifyEntries(this.resetFilters,t),$.isFunction(this.settings.sort)?this.modifyEntries(this.sortArray,t):this.settings.randomize&&this.modifyEntries(this.shuffleArray,t),!0)},e.prototype.insertToGallery=function(t){var e=this;$.each(t,function(){$(this).appendTo(e.$gallery)})},e.prototype.shuffleArray=function(t){var e,i,n;for(e=t.length-1;e>0;e--)i=Math.floor(Math.random()*(e+1)),n=t[e],t[e]=t[i],t[i]=n;return this.insertToGallery(t),t},e.prototype.sortArray=function(t){return t.sort(this.settings.sort),this.insertToGallery(t),t},e.prototype.resetFilters=function(t){for(var e=0;e<t.length;e++)$(t[e]).removeClass("jg-filtered");return t},e.prototype.filterArray=function(t){var e=this.settings;return"string"===$.type(e.filter)?t.filter(function(t){var i=$(t);return i.is(e.filter)?(i.removeClass("jg-filtered"),!0):(i.addClass("jg-filtered"),!1)}):$.isFunction(e.filter)?t.filter(e.filter):void 0},e.prototype.modifyEntries=function(t,e){var i=e?this.entries.splice(this.lastAnalyzedIndex+1,this.entries.length-this.lastAnalyzedIndex-1):this.entries;i=t.call(this,i),this.entries=e?this.entries.concat(i):i},e.prototype.destroy=function(){clearInterval(this.checkWidthIntervalId),$.each(this.entries,$.proxy(function(t,e){var i=$(e);i.css("width",""),i.css("height",""),i.css("top",""),i.css("left",""),i.data("jg.loaded",void 0),i.removeClass("jg-entry");var n=this.imgFromEntry(i);n.css("width",""),n.css("height",""),n.css("margin-left",""),n.css("margin-top",""),n.attr("src",n.data("jg.originalSrc")),n.data("jg.originalSrc",void 0),this.removeCaptionEventsHandlers(i);var o=this.captionFromEntry(i);i.data("jg.createdCaption")?(i.data("jg.createdCaption",void 0),null!==o&&o.remove()):null!==o&&o.fadeTo(0,1)},this)),this.$gallery.css("height",""),this.$gallery.removeClass("justified-gallery"),this.$gallery.data("jg.controller",void 0)},e.prototype.analyzeImages=function(t){for(var e=this.lastAnalyzedIndex+1;e<this.entries.length;e++){var i=$(this.entries[e]);if(i.data("jg.loaded")===!0||"skipped"===i.data("jg.loaded")){var n=this.galleryWidth-2*this.border-(this.buildingRow.entriesBuff.length-1)*this.settings.margins,o=i.data("jg.width")/i.data("jg.height");if(n/(this.buildingRow.aspectRatio+o)<this.settings.rowHeight&&(this.flushRow(!1),++this["yield"].flushed>=this["yield"].every))return void this.startImgAnalyzer(t);this.buildingRow.entriesBuff.push(i),this.buildingRow.aspectRatio+=o,this.buildingRow.width+=o*this.settings.rowHeight,this.lastAnalyzedIndex=e}else if("error"!==i.data("jg.loaded"))return}this.buildingRow.entriesBuff.length>0&&this.flushRow(!0),this.isSpinnerActive()&&this.stopLoadingSpinnerAnimation(),this.stopImgAnalyzerStarter(),this.$gallery.trigger(t?"jg.resize":"jg.complete"),this.$gallery.height(this.galleryHeightToSet)},e.prototype.stopImgAnalyzerStarter=function(){this["yield"].flushed=0,null!==this.imgAnalyzerTimeout&&clearTimeout(this.imgAnalyzerTimeout)},e.prototype.startImgAnalyzer=function(t){var e=this;this.stopImgAnalyzerStarter(),this.imgAnalyzerTimeout=setTimeout(function(){e.analyzeImages(t)},.001)},e.prototype.onImageEvent=function(t,e,i){if(e||i){var n=new Image,o=$(n);e&&o.one("load",function(){o.off("load error"),e(n)}),i&&o.one("error",function(){o.off("load error"),i(n)}),n.src=t}},e.prototype.init=function(){var t=!1,e=!1,i=this;$.each(this.entries,function(n,o){var r=$(o),s=i.imgFromEntry(r);if(r.addClass("jg-entry"),r.data("jg.loaded")!==!0&&"skipped"!==r.data("jg.loaded"))if(null!==i.settings.rel&&r.attr("rel",i.settings.rel),null!==i.settings.target&&r.attr("target",i.settings.target),null!==s){var a=i.extractImgSrcFromImage(s);if(s.attr("src",a),i.settings.waitThumbnailsLoad===!1){var h=parseFloat(s.attr("width")),l=parseFloat(s.attr("height"));if(!isNaN(h)&&!isNaN(l))return r.data("jg.width",h),r.data("jg.height",l),r.data("jg.loaded","skipped"),e=!0,i.startImgAnalyzer(!1),!0}r.data("jg.loaded",!1),t=!0,i.isSpinnerActive()||i.startLoadingSpinnerAnimation(),i.onImageEvent(a,function(t){r.data("jg.width",t.width),r.data("jg.height",t.height),r.data("jg.loaded",!0),i.startImgAnalyzer(!1)},function(){r.data("jg.loaded","error"),i.startImgAnalyzer(!1)})}else r.data("jg.loaded",!0),r.data("jg.width",r.width()|parseFloat(r.css("width"))|1),r.data("jg.height",r.height()|parseFloat(r.css("height"))|1)}),t||e||this.startImgAnalyzer(!1),this.checkWidth()},e.prototype.checkOrConvertNumber=function(t,e){if("string"===$.type(t[e])&&(t[e]=parseFloat(t[e])),"number"!==$.type(t[e]))throw e+" must be a number";if(isNaN(t[e]))throw"invalid number for "+e},e.prototype.checkSizeRangesSuffixes=function(){if("object"!==$.type(this.settings.sizeRangeSuffixes))throw"sizeRangeSuffixes must be defined and must be an object";var t=[];for(var e in this.settings.sizeRangeSuffixes)this.settings.sizeRangeSuffixes.hasOwnProperty(e)&&t.push(e);for(var i={0:""},n=0;n<t.length;n++)if("string"===$.type(t[n]))try{var o=parseInt(t[n].replace(/^[a-z]+/,""),10);i[o]=this.settings.sizeRangeSuffixes[t[n]]}catch(r){throw"sizeRangeSuffixes keys must contains correct numbers ("+r+")"}else i[t[n]]=this.settings.sizeRangeSuffixes[t[n]];this.settings.sizeRangeSuffixes=i},e.prototype.retrieveMaxRowHeight=function(){var t={};if("string"===$.type(this.settings.maxRowHeight))this.settings.maxRowHeight.match(/^[0-9]+%$/)?(t.value=parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1])/100,t.isPercentage=!1):(t.value=parseFloat(this.settings.maxRowHeight),t.isPercentage=!0);else{if("number"!==$.type(this.settings.maxRowHeight))throw"maxRowHeight must be a number or a percentage";t.value=this.settings.maxRowHeight,t.isPercentage=!1}if(isNaN(t.value))throw"invalid number for maxRowHeight";return t.isPercentage?t.value<100&&(t.value=100):t.value>0&&t.value<this.settings.rowHeight&&(t.value=this.settings.rowHeight),t},e.prototype.checkSettings=function(){this.checkSizeRangesSuffixes(),this.checkOrConvertNumber(this.settings,"rowHeight"),this.checkOrConvertNumber(this.settings,"margins"),this.checkOrConvertNumber(this.settings,"border");var t=["justify","nojustify","left","center","right","hide"];if(-1===t.indexOf(this.settings.lastRow))throw"lastRow must be one of: "+t.join(", ");if(this.checkOrConvertNumber(this.settings,"justifyThreshold"),this.settings.justifyThreshold<0||this.settings.justifyThreshold>1)throw"justifyThreshold must be in the interval [0,1]";if("boolean"!==$.type(this.settings.cssAnimation))throw"cssAnimation must be a boolean";if("boolean"!==$.type(this.settings.captions))throw"captions must be a boolean";if(this.checkOrConvertNumber(this.settings.captionSettings,"animationDuration"),this.checkOrConvertNumber(this.settings.captionSettings,"visibleOpacity"),this.settings.captionSettings.visibleOpacity<0||this.settings.captionSettings.visibleOpacity>1)throw"captionSettings.visibleOpacity must be in the interval [0, 1]";if(this.checkOrConvertNumber(this.settings.captionSettings,"nonVisibleOpacity"),this.settings.captionSettings.nonVisibleOpacity<0||this.settings.captionSettings.nonVisibleOpacity>1)throw"captionSettings.nonVisibleOpacity must be in the interval [0, 1]";if("boolean"!==$.type(this.settings.fixedHeight))throw"fixedHeight must be a boolean";if(this.checkOrConvertNumber(this.settings,"imagesAnimationDuration"),this.checkOrConvertNumber(this.settings,"refreshTime"),this.checkOrConvertNumber(this.settings,"refreshSensitivity"),"boolean"!==$.type(this.settings.randomize))throw"randomize must be a boolean";if("string"!==$.type(this.settings.selector))throw"selector must be a string";if(this.settings.sort!==!1&&!$.isFunction(this.settings.sort))throw"sort must be false or a comparison function";if(this.settings.filter!==!1&&!$.isFunction(this.settings.filter)&&"string"!==$.type(this.settings.filter))throw"filter must be false, a string or a filter function"},e.prototype.retrieveSuffixRanges=function(){var t=[];for(var e in this.settings.sizeRangeSuffixes)this.settings.sizeRangeSuffixes.hasOwnProperty(e)&&t.push(parseInt(e,10));return t.sort(function(t,e){return t>e?1:e>t?-1:0}),t},e.prototype.updateSettings=function(t){this.settings=$.extend({},this.settings,t),this.checkSettings(),this.border=this.settings.border>=0?this.settings.border:this.settings.margins,this.maxRowHeight=this.retrieveMaxRowHeight(),this.suffixRanges=this.retrieveSuffixRanges()},$.fn.justifiedGallery=function(t){return this.each(function(i,n){var o=$(n);o.addClass("justified-gallery");var r=o.data("jg.controller");if("undefined"==typeof r){if("undefined"!=typeof t&&null!==t&&"object"!==$.type(t)){if("destroy"===t)return;throw"The argument must be an object"}r=new e(o,$.extend({},$.fn.justifiedGallery.defaults,t)),o.data("jg.controller",r)}else if("norewind"===t);else{if("destroy"===t)return void r.destroy();r.updateSettings(t),r.rewind()}r.updateEntries("norewind"===t)&&r.init()})},$.fn.justifiedGallery.defaults={sizeRangeSuffixes:{},thumbnailPath:void 0,rowHeight:120,maxRowHeight:-1,margins:1,border:-1,lastRow:"nojustify",justifyThreshold:.9,fixedHeight:!1,waitThumbnailsLoad:!0,captions:!0,cssAnimation:!1,imagesAnimationDuration:500,captionSettings:{animationDuration:500,visibleOpacity:.7,nonVisibleOpacity:0},rel:null,target:null,extension:/\.[^.\\/]+$/,refreshTime:200,refreshSensitivity:0,randomize:!1,sort:!1,filter:!1,selector:"> a, > div:not(.spinner)"}}(jQuery),function($){var t=$.fn.justifiedGallery,e={};$.fn.enviraJustifiedGallery=function(){var i=t.apply(this,arguments);return e=i.data("jg.controller"),e.displayEntryCaption=function(t){var e=this.imgFromEntry(t);if(null!==e&&this.settings.captions){var i=this.captionFromEntry(t);if(null===i){var n=e.data("envira-caption");this.isValidCaption(n)&&(i=$('<div class="caption">'+n+"</div>"),t.append(i),t.data("jg.createdCaption",!0))}null!==i&&(this.settings.cssAnimation||i.stop().fadeTo(0,this.settings.captionSettings.nonVisibleOpacity),this.addCaptionEventsHandlers(t))}else this.removeCaptionEventsHandlers(t)},e}}(jQuery),/*!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  * vintageJS
3
  * Add a retro/vintage effect to images using the HTML5 canvas element
4
  *
6
  * @author Robert Fleischmann <rendro87@gmail.com>
7
  * @version 1.1.5
8
  */
9
+ !function(t,e){"function"==typeof define&&define.amd?define("vintagejs",["jquery"],function(i){return t.VintageJS=e(i)}):"object"==typeof exports?module.exports=e(require("jquery")):t.VintageJS=e(jQuery)}(this,function(t){var e=function(t,e,i){if(0==t instanceof HTMLImageElement)throw"The element (1st parameter) must be an instance of HTMLImageElement";var n,o,r,s,a,h,l,u,d,c=new Image,p=new Image,f=document.createElement("canvas"),g=f.getContext("2d"),m={onStart:function(){},onStop:function(){},onError:function(){},mime:"image/jpeg"},v={curves:!1,screen:!1,desaturate:!1,vignette:!1,lighten:!1,noise:!1,viewFinder:!1,sepia:!1,brightness:!1,contrast:!1};c.onerror=m.onError,c.onload=function(){h=f.width=c.width,l=f.height=c.height,n()},p.onerror=m.onError,p.onload=function(){g.clearRect(0,0,h,l),g.drawImage(p,0,0,h,l),(window.vjsImageCache||(window.vjsImageCache={}))[d]=g.getImageData(0,0,h,l).data,n()},o=function(t){m.onStart(),u={};for(var e in v)u[e]=t[e]||v[e];s=[],u.viewFinder&&s.push(u.viewFinder),c.src==a?n():c.src=a},n=function(){if(0===s.length)return r();var t=s.pop();return d=[h,l,t].join("-"),window.vjsImageCache&&window.vjsImageCache[d]?n():void(p.src=t)},r=function(){var e,i,n;g.clearRect(0,0,h,l),g.drawImage(c,0,0,h,l),(u.vignette||u.lighten)&&(e=Math.sqrt(Math.pow(h/2,2)+Math.pow(l/2,2))),u.vignette&&(g.globalCompositeOperation="source-over",i=g.createRadialGradient(h/2,l/2,0,h/2,l/2,e),i.addColorStop(0,"rgba(0,0,0,0)"),i.addColorStop(.5,"rgba(0,0,0,0)"),i.addColorStop(1,["rgba(0,0,0,",u.vignette,")"].join("")),g.fillStyle=i,g.fillRect(0,0,h,l)),u.lighten&&(g.globalCompositeOperation="lighter",i=g.createRadialGradient(h/2,l/2,0,h/2,l/2,e),i.addColorStop(0,["rgba(255,255,255,",u.lighten,")"].join("")),i.addColorStop(.5,"rgba(255,255,255,0)"),i.addColorStop(1,"rgba(0,0,0,0)"),g.fillStyle=i,g.fillRect(0,0,h,l)),n=g.getImageData(0,0,h,l);var o,r,s,a,d,p,f,v,y,w=n.data;u.contrast&&(y=259*(u.contrast+255)/(255*(259-u.contrast))),u.viewFinder&&(v=window.vjsImageCache[[h,l,u.viewFinder].join("-")]);for(var b=h*l;b>=0;--b)for(o=b<<2,u.curves&&(w[o]=u.curves.r[w[o]],w[o+1]=u.curves.g[w[o+1]],w[o+2]=u.curves.b[w[o+2]]),u.contrast&&(w[o]=y*(w[o]-128)+128,w[o+1]=y*(w[o+1]-128)+128,w[o+2]=y*(w[o+2]-128)+128),u.brightness&&(w[o]+=u.brightness,w[o+1]+=u.brightness,w[o+2]+=u.brightness),u.screen&&(w[o]=255-(255-w[o])*(255-u.screen.r*u.screen.a)/255,w[o+1]=255-(255-w[o+1])*(255-u.screen.g*u.screen.a)/255,w[o+2]=255-(255-w[o+2])*(255-u.screen.b*u.screen.a)/255),u.noise&&(f=u.noise-Math.random()*u.noise/2,w[o]+=f,w[o+1]+=f,w[o+2]+=f),u.viewFinder&&(w[o]=w[o]*v[o]/255,w[o+1]=w[o+1]*v[o+1]/255,w[o+2]=w[o+2]*v[o+2]/255),u.sepia&&(s=w[o],a=w[o+1],d=w[o+2],w[o]=.393*s+.769*a+.189*d,w[o+1]=.349*s+.686*a+.168*d,w[o+2]=.272*s+.534*a+.131*d),u.desaturate&&(p=(w[o]+w[o+1]+w[o+2])/3,w[o]+=(p-w[o])*u.desaturate,w[o+1]+=(p-w[o+1])*u.desaturate,w[o+2]+=(p-w[o+2])*u.desaturate),r=2;r>=0;--r)w[o+r]=~~(w[o+r]>255?255:w[o+r]<0?0:w[o+r]);g.putImageData(n,0,0),t.src=g.canvas.toDataURL(m.mime),m.onStop()},a=t.src,e=e||{};for(var y in m)m[y]=e[y]||m[y];return i&&o(i),{apply:function(){a=t.src},reset:function(){t.src=a},vintage:o}};return t.fn.vintage=function(i,n){return this.each(function(){t.data(this,"vintageJS")||t.data(this,"vintageJS",new e(this,i,n))})},e});var mul_table=[1,57,41,21,203,34,97,73,227,91,149,62,105,45,39,137,241,107,3,173,39,71,65,238,219,101,187,87,81,151,141,133,249,117,221,209,197,187,177,169,5,153,73,139,133,127,243,233,223,107,103,99,191,23,177,171,165,159,77,149,9,139,135,131,253,245,119,231,224,109,211,103,25,195,189,23,45,175,171,83,81,79,155,151,147,9,141,137,67,131,129,251,123,30,235,115,113,221,217,53,13,51,50,49,193,189,185,91,179,175,43,169,83,163,5,79,155,19,75,147,145,143,35,69,17,67,33,65,255,251,247,243,239,59,29,229,113,111,219,27,213,105,207,51,201,199,49,193,191,47,93,183,181,179,11,87,43,85,167,165,163,161,159,157,155,77,19,75,37,73,145,143,141,35,138,137,135,67,33,131,129,255,63,250,247,61,121,239,237,117,29,229,227,225,111,55,109,216,213,211,209,207,205,203,201,199,197,195,193,48,190,47,93,185,183,181,179,178,176,175,173,171,85,21,167,165,41,163,161,5,79,157,78,154,153,19,75,149,74,147,73,144,143,71,141,140,139,137,17,135,134,133,66,131,65,129,1],shg_table=[0,9,10,10,14,12,14,14,16,15,16,15,16,15,15,17,18,17,12,18,16,17,17,19,19,18,19,18,18,19,19,19,20,19,20,20,20,20,20,20,15,20,19,20,20,20,21,21,21,20,20,20,21,18,21,21,21,21,20,21,17,21,21,21,22,22,21,22,22,21,22,21,19,22,22,19,20,22,22,21,21,21,22,22,22,18,22,22,21,22,22,23,22,20,23,22,22,23,23,21,19,21,21,21,23,23,23,22,23,23,21,23,22,23,18,22,23,20,22,23,23,23,21,22,20,22,21,22,24,24,24,24,24,22,21,24,23,23,24,21,24,23,24,22,24,24,22,24,24,22,23,24,24,24,20,23,22,23,24,24,24,24,24,24,24,23,21,23,22,23,24,24,24,22,24,24,24,23,22,24,24,25,23,25,25,23,24,25,25,24,22,25,25,25,24,23,24,25,25,25,25,25,25,25,25,25,25,25,25,23,25,23,24,25,25,25,25,25,25,25,25,25,24,22,25,25,23,25,25,20,24,25,24,25,25,22,24,25,24,25,24,25,25,24,25,25,25,25,22,25,25,25,24,25,24,25,18];!function(t){"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],t):t(jQuery)}(function($){"use strict";function t(t){return!t||void 0!==t.allowPageScroll||void 0===t.swipe&&void 0===t.swipeStatus||(t.allowPageScroll=h),void 0!==t.click&&void 0===t.tap&&(t.tap=t.click),t||(t={}),t=$.extend({},$.fn.swipe.defaults,t),this.each(function(){var i=$(this),n=i.data(T);n||(n=new e(this,t),i.data(T,n))})}function e(t,e){function g(t){if(!(lt()||$(t.target).closest(e.excludedElements,$t).length>0)){var i=t.originalEvent?t.originalEvent:t,n,o=E?i.touches[0]:i;return Vt=b,E?Ut=i.touches.length:t.preventDefault(),Dt=0,Ht=null,qt=null,Wt=0,At=0,Pt=0,Bt=1,Ft=0,Yt=ft(),Nt=vt(),at(),!E||Ut===e.fingers||e.fingers===y||q()?(dt(0,o),Qt=Ct(),2==Ut&&(dt(1,i.touches[1]),At=Pt=bt(Yt[0].start,Yt[1].start)),(e.swipeStatus||e.pinchStatus)&&(n=M(i,Vt))):n=!1,n===!1?(Vt=I,M(i,Vt),n):(e.hold&&(te=setTimeout($.proxy(function(){$t.trigger("hold",[i.target]),e.hold&&(n=e.hold.call($t,i,i.target))},this),e.longTapThreshold)),ut(!0),null)}}function R(t){var i=t.originalEvent?t.originalEvent:t;if(Vt!==S&&Vt!==I&&!ht()){var n,o=E?i.touches[0]:i,r=ct(o);if(Gt=Ct(),E&&(Ut=i.touches.length),e.hold&&clearTimeout(te),Vt=x,2==Ut&&(0==At?(dt(1,i.touches[1]),At=Pt=bt(Yt[0].start,Yt[1].start)):(ct(i.touches[1]),Pt=bt(Yt[0].end,Yt[1].end),qt=St(Yt[0].end,Yt[1].end)),Bt=xt(At,Pt),Ft=Math.abs(At-Pt)),Ut===e.fingers||e.fingers===y||!E||q()){if(Ht=_t(r.start,r.end),B(t,Ht),Dt=It(r.start,r.end),Wt=wt(),gt(Ht,Dt),(e.swipeStatus||e.pinchStatus)&&(n=M(i,Vt)),!e.triggerOnTouchEnd||e.triggerOnTouchLeave){var s=!0;if(e.triggerOnTouchLeave){var a=Tt(this);s=Rt(r.end,a)}!e.triggerOnTouchEnd&&s?Vt=k(x):e.triggerOnTouchLeave&&!s&&(Vt=k(S)),Vt!=I&&Vt!=S||M(i,Vt)}}else Vt=I,M(i,Vt);n===!1&&(Vt=I,M(i,Vt))}}function z(t){var i=t.originalEvent;return E&&i.touches.length>0?(st(),!0):(ht()&&(Ut=Zt),Gt=Ct(),Wt=wt(),W()||!H()?(Vt=I,M(i,Vt)):e.triggerOnTouchEnd||0==e.triggerOnTouchEnd&&Vt===x?(t.preventDefault(),Vt=S,M(i,Vt)):!e.triggerOnTouchEnd&&X()?(Vt=S,D(i,Vt,c)):Vt===x&&(Vt=I,M(i,Vt)),ut(!1),null)}function j(){Ut=0,Gt=0,Qt=0,At=0,Pt=0,Bt=1,at(),ut(!1)}function O(t){var i=t.originalEvent;e.triggerOnTouchLeave&&(Vt=k(S),M(i,Vt))}function L(){$t.unbind(jt,g),$t.unbind(Mt,j),$t.unbind(Ot,R),$t.unbind(Lt,z),kt&&$t.unbind(kt,O),ut(!1)}function k(t){var i=t,n=P(),o=H(),r=W();return!n||r?i=I:!o||t!=x||e.triggerOnTouchEnd&&!e.triggerOnTouchLeave?!o&&t==S&&e.triggerOnTouchLeave&&(i=I):i=S,i}function M(t,e){var i=void 0;return Y()||U()?i=D(t,e,u):(N()||q())&&i!==!1&&(i=D(t,e,d)),ot()&&i!==!1?i=D(t,e,p):rt()&&i!==!1?i=D(t,e,f):nt()&&i!==!1&&(i=D(t,e,c)),e===I&&j(t),e===S&&(E?0==t.touches.length&&j(t):j(t)),i}function D(t,h,l){var g=void 0;if(l==u){if($t.trigger("swipeStatus",[h,Ht||null,Dt||0,Wt||0,Ut,Yt]),e.swipeStatus&&(g=e.swipeStatus.call($t,t,h,Ht||null,Dt||0,Wt||0,Ut,Yt),g===!1))return!1;if(h==S&&V()){if($t.trigger("swipe",[Ht,Dt,Wt,Ut,Yt]),e.swipe&&(g=e.swipe.call($t,t,Ht,Dt,Wt,Ut,Yt),g===!1))return!1;switch(Ht){case i:$t.trigger("swipeLeft",[Ht,Dt,Wt,Ut,Yt]),e.swipeLeft&&(g=e.swipeLeft.call($t,t,Ht,Dt,Wt,Ut,Yt));break;case n:$t.trigger("swipeRight",[Ht,Dt,Wt,Ut,Yt]),e.swipeRight&&(g=e.swipeRight.call($t,t,Ht,Dt,Wt,Ut,Yt));break;case o:$t.trigger("swipeUp",[Ht,Dt,Wt,Ut,Yt]),e.swipeUp&&(g=e.swipeUp.call($t,t,Ht,Dt,Wt,Ut,Yt));break;case r:$t.trigger("swipeDown",[Ht,Dt,Wt,Ut,Yt]),e.swipeDown&&(g=e.swipeDown.call($t,t,Ht,Dt,Wt,Ut,Yt))}}}if(l==d){if($t.trigger("pinchStatus",[h,qt||null,Ft||0,Wt||0,Ut,Bt,Yt]),e.pinchStatus&&(g=e.pinchStatus.call($t,t,h,qt||null,Ft||0,Wt||0,Ut,Bt,Yt),g===!1))return!1;if(h==S&&F())switch(qt){case s:$t.trigger("pinchIn",[qt||null,Ft||0,Wt||0,Ut,Bt,Yt]),e.pinchIn&&(g=e.pinchIn.call($t,t,qt||null,Ft||0,Wt||0,Ut,Bt,Yt));break;case a:$t.trigger("pinchOut",[qt||null,Ft||0,Wt||0,Ut,Bt,Yt]),e.pinchOut&&(g=e.pinchOut.call($t,t,qt||null,Ft||0,Wt||0,Ut,Bt,Yt))}}return l==c?h!==I&&h!==S||(clearTimeout(Kt),clearTimeout(te),Z()&&!tt()?(Jt=Ct(),Kt=setTimeout($.proxy(function(){Jt=null,$t.trigger("tap",[t.target]),e.tap&&(g=e.tap.call($t,t,t.target))},this),e.doubleTapThreshold)):(Jt=null,$t.trigger("tap",[t.target]),e.tap&&(g=e.tap.call($t,t,t.target)))):l==p?h!==I&&h!==S||(clearTimeout(Kt),Jt=null,$t.trigger("doubletap",[t.target]),e.doubleTap&&(g=e.doubleTap.call($t,t,t.target))):l==f&&(h!==I&&h!==S||(clearTimeout(Kt),Jt=null,$t.trigger("longtap",[t.target]),e.longTap&&(g=e.longTap.call($t,t,t.target)))),g}function H(){var t=!0;return null!==e.threshold&&(t=Dt>=e.threshold),t}function W(){var t=!1;return null!==e.cancelThreshold&&null!==Ht&&(t=mt(Ht)-Dt>=e.cancelThreshold),t}function A(){return null!==e.pinchThreshold?Ft>=e.pinchThreshold:!0}function P(){var t;return t=e.maxTimeThreshold?!(Wt>=e.maxTimeThreshold):!0}function B(t,s){if(e.allowPageScroll===h||q())t.preventDefault();else{var a=e.allowPageScroll===l;switch(s){case i:(e.swipeLeft&&a||!a&&e.allowPageScroll!=m)&&t.preventDefault();break;case n:(e.swipeRight&&a||!a&&e.allowPageScroll!=m)&&t.preventDefault();break;case o:(e.swipeUp&&a||!a&&e.allowPageScroll!=v)&&t.preventDefault();break;case r:(e.swipeDown&&a||!a&&e.allowPageScroll!=v)&&t.preventDefault()}}}function F(){var t=Q(),e=G(),i=A();return t&&e&&i}function q(){return!!(e.pinchStatus||e.pinchIn||e.pinchOut)}function N(){return!(!F()||!q())}function V(){var t=P(),e=H(),i=Q(),n=G(),o=W(),r=!o&&n&&i&&e&&t;return r}function U(){return!!(e.swipe||e.swipeStatus||e.swipeLeft||e.swipeRight||e.swipeUp||e.swipeDown)}function Y(){return!(!V()||!U())}function Q(){return Ut===e.fingers||e.fingers===y||!E}function G(){return 0!==Yt[0].end.x}function X(){return!!e.tap}function Z(){return!!e.doubleTap}function J(){return!!e.longTap}function K(){if(null==Jt)return!1;var t=Ct();return Z()&&t-Jt<=e.doubleTapThreshold}function tt(){return K()}function et(){return(1===Ut||!E)&&(isNaN(Dt)||Dt<e.threshold)}function it(){return Wt>e.longTapThreshold&&w>Dt}function nt(){return!(!et()||!X())}function ot(){return!(!K()||!Z())}function rt(){return!(!it()||!J())}function st(){Xt=Ct(),Zt=event.touches.length+1}function at(){Xt=0,Zt=0}function ht(){var t=!1;if(Xt){var i=Ct()-Xt;i<=e.fingerReleaseThreshold&&(t=!0)}return t}function lt(){return!($t.data(T+"_intouch")!==!0)}function ut(t){t===!0?($t.bind(Ot,R),$t.bind(Lt,z),kt&&$t.bind(kt,O)):($t.unbind(Ot,R,!1),$t.unbind(Lt,z,!1),kt&&$t.unbind(kt,O,!1)),$t.data(T+"_intouch",t===!0)}function dt(t,e){var i=void 0!==e.identifier?e.identifier:0;return Yt[t].identifier=i,Yt[t].start.x=Yt[t].end.x=e.pageX||e.clientX,Yt[t].start.y=Yt[t].end.y=e.pageY||e.clientY,Yt[t]}function ct(t){var e=void 0!==t.identifier?t.identifier:0,i=pt(e);return i.end.x=t.pageX||t.clientX,i.end.y=t.pageY||t.clientY,i}function pt(t){for(var e=0;e<Yt.length;e++)if(Yt[e].identifier==t)return Yt[e]}function ft(){for(var t=[],e=0;5>=e;e++)t.push({start:{x:0,y:0},end:{x:0,y:0},identifier:0});return t}function gt(t,e){e=Math.max(e,mt(t)),Nt[t].distance=e}function mt(t){return Nt[t]?Nt[t].distance:void 0}function vt(){var t={};return t[i]=yt(i),t[n]=yt(n),t[o]=yt(o),t[r]=yt(r),t}function yt(t){return{direction:t,distance:0}}function wt(){return Gt-Qt}function bt(t,e){var i=Math.abs(t.x-e.x),n=Math.abs(t.y-e.y);return Math.round(Math.sqrt(i*i+n*n))}function xt(t,e){var i=e/t*1;return i.toFixed(2)}function St(){return 1>Bt?a:s}function It(t,e){return Math.round(Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2)))}function Et(t,e){var i=t.x-e.x,n=e.y-t.y,o=Math.atan2(n,i),r=Math.round(180*o/Math.PI);return 0>r&&(r=360-Math.abs(r)),r}function _t(t,e){var s=Et(t,e);return 45>=s&&s>=0?i:360>=s&&s>=315?i:s>=135&&225>=s?n:s>45&&135>s?r:o}function Ct(){var t=new Date;return t.getTime()}function Tt(t){t=$(t);var e=t.offset(),i={left:e.left,right:e.left+t.outerWidth(),top:e.top,bottom:e.top+t.outerHeight()};return i}function Rt(t,e){return t.x>e.left&&t.x<e.right&&t.y>e.top&&t.y<e.bottom}var zt=E||C||!e.fallbackToMouseEvents,jt=zt?C?_?"MSPointerDown":"pointerdown":"touchstart":"mousedown",Ot=zt?C?_?"MSPointerMove":"pointermove":"touchmove":"mousemove",Lt=zt?C?_?"MSPointerUp":"pointerup":"touchend":"mouseup",kt=zt?null:"mouseleave",Mt=C?_?"MSPointerCancel":"pointercancel":"touchcancel",Dt=0,Ht=null,Wt=0,At=0,Pt=0,Bt=1,Ft=0,qt=0,Nt=null,$t=$(t),Vt="start",Ut=0,Yt=null,Qt=0,Gt=0,Xt=0,Zt=0,Jt=0,Kt=null,te=null;try{$t.bind(jt,g),$t.bind(Mt,j)}catch(ee){$.error("events not supported "+jt+","+Mt+" on jQuery.swipe")}this.enable=function(){return $t.bind(jt,g),$t.bind(Mt,j),$t},this.disable=function(){return L(),$t},this.destroy=function(){L(),$t.data(T,null),$t=null},this.option=function(t,i){if(void 0!==e[t]){if(void 0===i)return e[t];e[t]=i}else $.error("Option "+t+" does not exist on jQuery.swipe.options");return null}}var i="left",n="right",o="up",r="down",s="in",a="out",h="none",l="auto",u="swipe",d="pinch",c="tap",p="doubletap",f="longtap",g="hold",m="horizontal",v="vertical",y="all",w=10,b="start",x="move",S="end",I="cancel",E="ontouchstart"in window,_=window.navigator.msPointerEnabled&&!window.navigator.pointerEnabled,C=window.navigator.pointerEnabled||window.navigator.msPointerEnabled,T="TouchSwipe",R={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,hold:null,triggerOnTouchEnd:!0,triggerOnTouchLeave:!1,allowPageScroll:"auto",fallbackToMouseEvents:!0,excludedElements:"label, button, input, select, textarea, a, .noSwipe"};$.fn.swipe=function(e){var i=$(this),n=i.data(T);if(n&&"string"==typeof e){if(n[e])return n[e].apply(this,Array.prototype.slice.call(arguments,1));$.error("Method "+e+" does not exist on jQuery.swipe")}else if(!(n||"object"!=typeof e&&e))return t.apply(this,arguments);return i},$.fn.swipe.defaults=R,$.fn.swipe.phases={PHASE_START:b,PHASE_MOVE:x,PHASE_END:S,PHASE_CANCEL:I},$.fn.swipe.directions={LEFT:i,RIGHT:n,UP:o,DOWN:r,IN:s,OUT:a},$.fn.swipe.pageScroll={NONE:h,HORIZONTAL:m,VERTICAL:v,AUTO:l},$.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,ALL:y}}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?module.exports=t:t(jQuery)}(function($){function t(t){var n=t||window.event,o=r.call(arguments,1),h=0,u=0,d=0,c=0,p=0,f=0;if(t=$.event.fix(n),t.type="mousewheel","detail"in n&&(d=-1*n.detail),"wheelDelta"in n&&(d=n.wheelDelta),"wheelDeltaY"in n&&(d=n.wheelDeltaY),"wheelDeltaX"in n&&(u=-1*n.wheelDeltaX),"axis"in n&&n.axis===n.HORIZONTAL_AXIS&&(u=-1*d,d=0),h=0===d?u:d,"deltaY"in n&&(d=-1*n.deltaY,h=d),"deltaX"in n&&(u=n.deltaX,0===d&&(h=-1*u)),0!==d||0!==u){if(1===n.deltaMode){var g=$.data(this,"mousewheel-line-height");h*=g,d*=g,u*=g}else if(2===n.deltaMode){var m=$.data(this,"mousewheel-page-height");h*=m,d*=m,u*=m}if(c=Math.max(Math.abs(d),Math.abs(u)),(!a||a>c)&&(a=c,i(n,c)&&(a/=40)),i(n,c)&&(h/=40,u/=40,d/=40),h=Math[h>=1?"floor":"ceil"](h/a),u=Math[u>=1?"floor":"ceil"](u/a),d=Math[d>=1?"floor":"ceil"](d/a),l.settings.normalizeOffset&&this.getBoundingClientRect){var v=this.getBoundingClientRect();p=t.clientX-v.left,f=t.clientY-v.top}return t.deltaX=u,t.deltaY=d,t.deltaFactor=a,t.offsetX=p,t.offsetY=f,t.deltaMode=0,o.unshift(t,h,u,d),s&&clearTimeout(s),s=setTimeout(e,200),($.event.dispatch||$.event.handle).apply(this,o)}}function e(){a=null}function i(t,e){return l.settings.adjustOldDeltas&&"mousewheel"===t.type&&e%120===0}var n=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],o="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],r=Array.prototype.slice,s,a;if($.event.fixHooks)for(var h=n.length;h;)$.event.fixHooks[n[--h]]=$.event.mouseHooks;var l=$.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var e=o.length;e;)this.addEventListener(o[--e],t,!1);else this.onmousewheel=t;$.data(this,"mousewheel-line-height",l.getLineHeight(this)),$.data(this,"mousewheel-page-height",l.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var e=o.length;e;)this.removeEventListener(o[--e],t,!1);else this.onmousewheel=null;$.removeData(this,"mousewheel-line-height"),$.removeData(this,"mousewheel-page-height")},getLineHeight:function(t){var e=$(t),i=e["offsetParent"in $.fn?"offsetParent":"parent"]();return i.length||(i=$("body")),parseInt(i.css("fontSize"),10)||parseInt(e.css("fontSize"),10)||16},getPageHeight:function(t){return $(t).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};$.fn.extend({mousewheel:function(t){return t?this.bind("mousewheel",t):this.trigger("mousewheel")},unmousewheel:function(t){return this.unbind("mousewheel",t)}})}),function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||[];return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.enviraImagesLoaded=e(t,t.EvEmitter)}(window,function t(e,i){function n(t,e){for(var i in e)t[i]=e[i];return t}function o(t){var e=[];if(Array.isArray(t))e=t;else if("number"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i]);else e.push(t);return e}function r(t,e,i){return this instanceof r?("string"==typeof t&&(t=document.querySelectorAll(t)),this.elements=o(t),this.options=n({},this.options),"function"==typeof e?i=e:n(this.options,e),i&&this.on("always",i),this.getImages(),$&&(this.jqDeferred=new $.Deferred),void setTimeout(function(){this.check()}.bind(this))):new r(t,e,i)}function s(t){this.img=t}function a(t,e){this.url=t,this.element=e,this.img=new Image}var $=e.jQuery,h=e.console;r.prototype=Object.create(i.prototype),r.prototype.options={},r.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},r.prototype.addElementImages=function(t){"IMG"==t.nodeName&&this.addImage(t),this.options.background===!0&&this.addElementBackgroundImages(t);var e=t.nodeType;if(e&&l[e]){for(var i=t.querySelectorAll("img"),n=0;n<i.length;n++){var o=i[n];this.addImage(o)}if("string"==typeof this.options.background){var r=t.querySelectorAll(this.options.background);for(n=0;n<r.length;n++){var s=r[n];this.addElementBackgroundImages(s)}}}};var l={1:!0,9:!0,11:!0};return r.prototype.addElementBackgroundImages=function(t){var e=getComputedStyle(t);if(e)for(var i=/url\((['"])?(.*?)\1\)/gi,n=i.exec(e.backgroundImage);null!==n;){var o=n&&n[2];o&&this.addBackground(o,t),n=i.exec(e.backgroundImage)}},r.prototype.addImage=function(t){var e=new s(t);this.images.push(e)},r.prototype.addBackground=function(t,e){var i=new a(t,e);this.images.push(i)},r.prototype.check=function(){function t(t,i,n){setTimeout(function(){e.progress(t,i,n)})}var e=this;return this.progressedCount=0,this.hasAnyBroken=!1,this.images.length?void this.images.forEach(function(e){e.once("progress",t),e.check()}):void this.complete()},r.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount==this.images.length&&this.complete(),this.options.debug&&h&&h.log("progress: "+i,t,e)},r.prototype.complete=function(){var t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){var e=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[e](this)}},s.prototype=Object.create(i.prototype),s.prototype.check=function(){var t=this.getIsImageComplete();return t?void this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),void(this.proxyImage.src=this.img.src))},s.prototype.getIsImageComplete=function(){return this.img.complete&&void 0!==this.img.naturalWidth},s.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.img,e])},s.prototype.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},s.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},s.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},s.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},a.prototype=Object.create(s.prototype),a.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url;var t=this.getIsImageComplete();t&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},a.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},a.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},r.makeJQueryPlugin=function(t){t=t||e.jQuery,t&&($=t,$.fn.enviraImagesLoaded=function(t,e){var i=new r(this,t,e);return i.jqDeferred.promise($(this))})},r.makeJQueryPlugin(),r}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(i){e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("jquery")):t.jQueryBridget=e(t,t.jQuery)}(window,function e(t,i){"use strict";function n(e,n,$){function s(t,i,n){var o,r="$()."+e+'("'+i+'")';return t.each(function(t,s){var h=$.data(s,e);if(!h)return void a(e+" not initialized. Cannot call methods, i.e. "+r);var l=h[i];if(!l||"_"==i.charAt(0))return void a(r+" is not a valid method");var u=l.apply(h,n);o=void 0===o?u:o}),void 0!==o?o:t}function h(t,i){t.each(function(t,o){var r=$.data(o,e);r?(r.option(i),r._init()):(r=new n(o,i),$.data(o,e,r))})}$=$||i||t.jQuery,$&&(n.prototype.option||(n.prototype.option=function(t){$.isPlainObject(t)&&(this.options=$.extend(!0,this.options,t))}),$.fn[e]=function(t){if("string"==typeof t){var e=r.call(arguments,1);return s(this,t,e)}return h(this,t),this},o($))}function o($){!$||$&&$.bridget||($.bridget=n)}var r=Array.prototype.slice,s=t.console,a="undefined"==typeof s?function(){}:function(t){s.error(t)};return o(i||t.jQuery),n}),function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{};return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("get-size/get-size",[],function(){return e()}):"object"==typeof module&&module.exports?module.exports=e():t.getSize=e()}(window,function i(){"use strict";function t(t){var e=parseFloat(t),i=-1==t.indexOf("%")&&!isNaN(e);return i&&e}function e(){}function i(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},e=0;h>e;e++){var i=a[e];t[i]=0}return t}function n(t){var e=getComputedStyle(t);return e||s("Style returned "+e+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),e}function o(){if(!l){l=!0;var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style.boxSizing="border-box";var i=document.body||document.documentElement;i.appendChild(e);var o=n(e);r.isBoxSizeOuter=u=200==t(o.width),i.removeChild(e)}}function r(e){if(o(),"string"==typeof e&&(e=document.querySelector(e)),e&&"object"==typeof e&&e.nodeType){var r=n(e);if("none"==r.display)return i();var s={};s.width=e.offsetWidth,s.height=e.offsetHeight;for(var l=s.isBorderBox="border-box"==r.boxSizing,d=0;h>d;d++){var c=a[d],p=r[c],f=parseFloat(p);s[c]=isNaN(f)?0:f}var g=s.paddingLeft+s.paddingRight,m=s.paddingTop+s.paddingBottom,v=s.marginLeft+s.marginRight,y=s.marginTop+s.marginBottom,w=s.borderLeftWidth+s.borderRightWidth,b=s.borderTopWidth+s.borderBottomWidth,x=l&&u,S=t(r.width);S!==!1&&(s.width=S+(x?0:g+w));var I=t(r.height);return I!==!1&&(s.height=I+(x?0:m+b)),s.innerWidth=s.width-(g+w),s.innerHeight=s.height-(m+b),s.outerWidth=s.width+v,s.outerHeight=s.height+y,s}}var s="undefined"==typeof console?e:function(t){console.error(t)},a=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],h=a.length,l=!1,u;return r}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("desandro-matches-selector/matches-selector",e):"object"==typeof module&&module.exports?module.exports=e():t.matchesSelector=e()}(window,function n(){"use strict";var t=function(){var t=Element.prototype;if(t.matches)return"matches";if(t.matchesSelector)return"matchesSelector";for(var e=["webkit","moz","ms","o"],i=0;i<e.length;i++){var n=e[i],o=n+"MatchesSelector";if(t[o])return o}}();return function e(i,n){return i[t](n)}}),function(t,e){"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["desandro-matches-selector/matches-selector"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("desandro-matches-selector")):t.fizzyUIUtils=e(t,t.matchesSelector)}(window,function o(t,e){var i={};i.extend=function(t,e){for(var i in e)t[i]=e[i];return t},i.modulo=function(t,e){return(t%e+e)%e},i.makeArray=function(t){var e=[];if(Array.isArray(t))e=t;else if(t&&"number"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i]);else e.push(t);return e},i.removeFrom=function(t,e){var i=t.indexOf(e);-1!=i&&t.splice(i,1)},i.getParent=function(t,i){for(;t!=document.body;)if(t=t.parentNode,e(t,i))return t},i.getQueryElement=function(t){return"string"==typeof t?document.querySelector(t):t},i.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},i.filterFindElements=function(t,n){t=i.makeArray(t);var o=[];return t.forEach(function(t){if(t instanceof HTMLElement){if(!n)return void o.push(t);e(t,n)&&o.push(t);for(var i=t.querySelectorAll(n),r=0;r<i.length;r++)o.push(i[r])}}),o},i.debounceMethod=function(t,e,i){var n=t.prototype[e],o=e+"Timeout";t.prototype[e]=function(){var t=this[o];t&&clearTimeout(t);var e=arguments,r=this;this[o]=setTimeout(function(){n.apply(r,e),delete r[o]},i||100)}},i.docReady=function(t){"complete"==document.readyState?t():document.addEventListener("DOMContentLoaded",t)},i.toDashed=function(t){return t.replace(/(.)([A-Z])/g,function(t,e,i){return e+"-"+i}).toLowerCase()};var n=t.console;return i.htmlInit=function(e,o){i.docReady(function(){var r=i.toDashed(o),s="data-"+r,a=document.querySelectorAll("["+s+"]"),h=document.querySelectorAll(".js-"+r),l=i.makeArray(a).concat(i.makeArray(h)),u=s+"-options",d=t.jQuery;l.forEach(function(t){var i=t.getAttribute(s)||t.getAttribute(u),r;try{r=i&&JSON.parse(i)}catch(a){return void(n&&n.error("Error parsing "+s+" on "+t.className+": "+a))}var h=new e(t,r);d&&d.data(t,o,h)})})},i}),function(t,e){"function"==typeof define&&define.amd?define("outlayer/item",["ev-emitter/ev-emitter","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("ev-emitter"),require("get-size")):(t.Outlayer={},t.Outlayer.Item=e(t.EvEmitter,t.getSize))}(window,function r(t,e){"use strict";function i(t){for(var e in t)return!1;return e=null,!0}function n(t,e){t&&(this.element=t,this.layout=e,this.position={x:0,y:0},this._create())}function o(t){return t.replace(/([A-Z])/g,function(t){return"-"+t.toLowerCase()})}var r=document.documentElement.style,s="string"==typeof r.transition?"transition":"WebkitTransition",a="string"==typeof r.transform?"transform":"WebkitTransform",h={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[s],l={transform:a,transition:s,transitionDuration:s+"Duration",transitionProperty:s+"Property",transitionDelay:s+"Delay"},u=n.prototype=Object.create(t.prototype);u.constructor=n,u._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},u.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},u.getSize=function(){this.size=e(this.element)},u.css=function(t){var e=this.element.style;for(var i in t){var n=l[i]||i;e[n]=t[i]}},u.getPosition=function(){var t=getComputedStyle(this.element),e=this.layout._getOption("originLeft"),i=this.layout._getOption("originTop"),n=t[e?"left":"right"],o=t[i?"top":"bottom"],r=this.layout.size,s=-1!=n.indexOf("%")?parseFloat(n)/100*r.width:parseInt(n,10),a=-1!=o.indexOf("%")?parseFloat(o)/100*r.height:parseInt(o,10);s=isNaN(s)?0:s,a=isNaN(a)?0:a,s-=e?r.paddingLeft:r.paddingRight,a-=i?r.paddingTop:r.paddingBottom,this.position.x=s,this.position.y=a},u.layoutPosition=function(){var t=this.layout.size,e={},i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop"),o=i?"paddingLeft":"paddingRight",r=i?"left":"right",s=i?"right":"left",a=this.position.x+t[o];e[r]=this.getXValue(a),e[s]="";var h=n?"paddingTop":"paddingBottom",l=n?"top":"bottom",u=n?"bottom":"top",d=this.position.y+t[h];e[l]=this.getYValue(d),e[u]="",this.css(e),this.emitEvent("layout",[this])},u.getXValue=function(t){var e=this.layout._getOption("horizontal");return this.layout.options.percentPosition&&!e?t/this.layout.size.width*100+"%":t+"px"},u.getYValue=function(t){var e=this.layout._getOption("horizontal");return this.layout.options.percentPosition&&e?t/this.layout.size.height*100+"%":t+"px";
10
+ },u._transitionTo=function(t,e){this.getPosition();var i=this.position.x,n=this.position.y,o=parseInt(t,10),r=parseInt(e,10),s=o===this.position.x&&r===this.position.y;if(this.setPosition(t,e),s&&!this.isTransitioning)return void this.layoutPosition();var a=t-i,h=e-n,l={};l.transform=this.getTranslate(a,h),this.transition({to:l,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},u.getTranslate=function(t,e){var i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop");return t=i?t:-t,e=n?e:-e,"translate3d("+t+"px, "+e+"px, 0)"},u.goTo=function(t,e){this.setPosition(t,e),this.layoutPosition()},u.moveTo=u._transitionTo,u.setPosition=function(t,e){this.position.x=parseInt(t,10),this.position.y=parseInt(e,10)},u._nonTransition=function(t){this.css(t.to),t.isCleaning&&this._removeStyles(t.to);for(var e in t.onTransitionEnd)t.onTransitionEnd[e].call(this)},u.transition=function(t){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(t);var e=this._transn;for(var i in t.onTransitionEnd)e.onEnd[i]=t.onTransitionEnd[i];for(i in t.to)e.ingProperties[i]=!0,t.isCleaning&&(e.clean[i]=!0);if(t.from){this.css(t.from);var n=this.element.offsetHeight;n=null}this.enableTransition(t.to),this.css(t.to),this.isTransitioning=!0};var d="opacity,"+o(a);u.enableTransition=function(){if(!this.isTransitioning){var t=this.layout.options.transitionDuration;t="number"==typeof t?t+"ms":t,this.css({transitionProperty:d,transitionDuration:t,transitionDelay:this.staggerDelay||0}),this.element.addEventListener(h,this,!1)}},u.onwebkitTransitionEnd=function(t){this.ontransitionend(t)},u.onotransitionend=function(t){this.ontransitionend(t)};var c={"-webkit-transform":"transform"};u.ontransitionend=function(t){if(t.target===this.element){var e=this._transn,n=c[t.propertyName]||t.propertyName;if(delete e.ingProperties[n],i(e.ingProperties)&&this.disableTransition(),n in e.clean&&(this.element.style[t.propertyName]="",delete e.clean[n]),n in e.onEnd){var o=e.onEnd[n];o.call(this),delete e.onEnd[n]}this.emitEvent("transitionEnd",[this])}},u.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(h,this,!1),this.isTransitioning=!1},u._removeStyles=function(t){var e={};for(var i in t)e[i]="";this.css(e)};var p={transitionProperty:"",transitionDuration:"",transitionDelay:""};return u.removeTransitionStyles=function(){this.css(p)},u.stagger=function(t){t=isNaN(t)?0:t,this.staggerDelay=t+"ms"},u.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},u.remove=function(){return s&&parseFloat(this.layout.options.transitionDuration)?(this.once("transitionEnd",function(){this.removeElem()}),void this.hide()):void this.removeElem()},u.reveal=function(){delete this.isHidden,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("visibleStyle");e[i]=this.onRevealTransitionEnd,this.transition({from:t.hiddenStyle,to:t.visibleStyle,isCleaning:!0,onTransitionEnd:e})},u.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},u.getHideRevealTransitionEndProperty=function(t){var e=this.layout.options[t];if(e.opacity)return"opacity";for(var i in e)return i},u.hide=function(){this.isHidden=!0,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("hiddenStyle");e[i]=this.onHideTransitionEnd,this.transition({from:t.visibleStyle,to:t.hiddenStyle,isCleaning:!0,onTransitionEnd:e})},u.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},u.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},n}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("outlayer/outlayer",["ev-emitter/ev-emitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(i,n,o,r){return e(t,i,n,o,r)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):t.Outlayer=e(t,t.EvEmitter,t.getSize,t.fizzyUIUtils,t.Outlayer.Item)}(window,function s(t,e,i,n,o){"use strict";function r(t,e){var i=n.getQueryElement(t);if(!i)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(i||t)));this.element=i,l&&(this.$element=l(this.element)),this.options=n.extend({},this.constructor.defaults),this.option(e);var o=++d;this.element.outlayerGUID=o,c[o]=this,this._create();var r=this._getOption("initLayout");r&&this.layout()}function s(t){function e(){t.apply(this,arguments)}return e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e}function a(t){if("number"==typeof t)return t;var e=t.match(/(^\d*\.?\d*)(\w*)/),i=e&&e[1],n=e&&e[2];if(!i.length)return 0;i=parseFloat(i);var o=f[n]||1;return i*o}var h=t.console,l=t.jQuery,u=function(){},d=0,c={};r.namespace="outlayer",r.Item=o,r.defaults={containerStyle:{position:"relative"},initLayout:!0,originLeft:!0,originTop:!0,resize:!0,resizeContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}};var p=r.prototype;n.extend(p,e.prototype),p.option=function(t){n.extend(this.options,t)},p._getOption=function(t){var e=this.constructor.compatOptions[t];return e&&void 0!==this.options[e]?this.options[e]:this.options[t]},r.compatOptions={initLayout:"isInitLayout",horizontal:"isHorizontal",layoutInstant:"isLayoutInstant",originLeft:"isOriginLeft",originTop:"isOriginTop",resize:"isResizeBound",resizeContainer:"isResizingContainer"},p._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),n.extend(this.element.style,this.options.containerStyle);var t=this._getOption("resize");t&&this.bindResize()},p.reloadItems=function(){this.items=this._itemize(this.element.children)},p._itemize=function(t){for(var e=this._filterFindItemElements(t),i=this.constructor.Item,n=[],o=0;o<e.length;o++){var r=e[o],s=new i(r,this);n.push(s)}return n},p._filterFindItemElements=function(t){return n.filterFindElements(t,this.options.itemSelector)},p.getItemElements=function(){return this.items.map(function(t){return t.element})},p.layout=function(){this._resetLayout(),this._manageStamps();var t=this._getOption("layoutInstant"),e=void 0!==t?t:!this._isLayoutInited;this.layoutItems(this.items,e),this._isLayoutInited=!0},p._init=p.layout,p._resetLayout=function(){this.getSize()},p.getSize=function(){this.size=i(this.element)},p._getMeasurement=function(t,e){var n=this.options[t],o;n?("string"==typeof n?o=this.element.querySelector(n):n instanceof HTMLElement&&(o=n),this[t]=o?i(o)[e]:n):this[t]=0},p.layoutItems=function(t,e){t=this._getItemsForLayout(t),this._layoutItems(t,e),this._postLayout()},p._getItemsForLayout=function(t){return t.filter(function(t){return!t.isIgnored})},p._layoutItems=function(t,e){if(this._emitCompleteOnItems("layout",t),t&&t.length){var i=[];t.forEach(function(t){var n=this._getItemLayoutPosition(t);n.item=t,n.isInstant=e||t.isLayoutInstant,i.push(n)},this),this._processLayoutQueue(i)}},p._getItemLayoutPosition=function(){return{x:0,y:0}},p._processLayoutQueue=function(t){this.updateStagger(),t.forEach(function(t,e){this._positionItem(t.item,t.x,t.y,t.isInstant,e)},this)},p.updateStagger=function(){var t=this.options.stagger;return null===t||void 0===t?void(this.stagger=0):(this.stagger=a(t),this.stagger)},p._positionItem=function(t,e,i,n,o){n?t.goTo(e,i):(t.stagger(o*this.stagger),t.moveTo(e,i))},p._postLayout=function(){this.resizeContainer()},p.resizeContainer=function(){var t=this._getOption("resizeContainer");if(t){var e=this._getContainerSize();e&&(this._setContainerMeasure(e.width,!0),this._setContainerMeasure(e.height,!1))}},p._getContainerSize=u,p._setContainerMeasure=function(t,e){if(void 0!==t){var i=this.size;i.isBorderBox&&(t+=e?i.paddingLeft+i.paddingRight+i.borderLeftWidth+i.borderRightWidth:i.paddingBottom+i.paddingTop+i.borderTopWidth+i.borderBottomWidth),t=Math.max(t,0),this.element.style[e?"width":"height"]=t+"px"}},p._emitCompleteOnItems=function(t,e){function i(){o.dispatchEvent(t+"Complete",null,[e])}function n(){s++,s==r&&i()}var o=this,r=e.length;if(!e||!r)return void i();var s=0;e.forEach(function(e){e.once(t,n)})},p.dispatchEvent=function(t,e,i){var n=e?[e].concat(i):i;if(this.emitEvent(t,n),l)if(this.$element=this.$element||l(this.element),e){var o=l.Event(e);o.type=t,this.$element.trigger(o,i)}else this.$element.trigger(t,i)},p.ignore=function(t){var e=this.getItem(t);e&&(e.isIgnored=!0)},p.unignore=function(t){var e=this.getItem(t);e&&delete e.isIgnored},p.stamp=function(t){t=this._find(t),t&&(this.stamps=this.stamps.concat(t),t.forEach(this.ignore,this))},p.unstamp=function(t){t=this._find(t),t&&t.forEach(function(t){n.removeFrom(this.stamps,t),this.unignore(t)},this)},p._find=function(t){return t?("string"==typeof t&&(t=this.element.querySelectorAll(t)),t=n.makeArray(t)):void 0},p._manageStamps=function(){this.stamps&&this.stamps.length&&(this._getBoundingRect(),this.stamps.forEach(this._manageStamp,this))},p._getBoundingRect=function(){var t=this.element.getBoundingClientRect(),e=this.size;this._boundingRect={left:t.left+e.paddingLeft+e.borderLeftWidth,top:t.top+e.paddingTop+e.borderTopWidth,right:t.right-(e.paddingRight+e.borderRightWidth),bottom:t.bottom-(e.paddingBottom+e.borderBottomWidth)}},p._manageStamp=u,p._getElementOffset=function(t){var e=t.getBoundingClientRect(),n=this._boundingRect,o=i(t),r={left:e.left-n.left-o.marginLeft,top:e.top-n.top-o.marginTop,right:n.right-e.right-o.marginRight,bottom:n.bottom-e.bottom-o.marginBottom};return r},p.handleEvent=n.handleEvent,p.bindResize=function(){t.addEventListener("resize",this),this.isResizeBound=!0},p.unbindResize=function(){t.removeEventListener("resize",this),this.isResizeBound=!1},p.onresize=function(){this.resize()},n.debounceMethod(r,"onresize",100),p.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},p.needsResizeLayout=function(){var t=i(this.element),e=this.size&&t;return e&&t.innerWidth!==this.size.innerWidth},p.addItems=function(t){var e=this._itemize(t);return e.length&&(this.items=this.items.concat(e)),e},p.appended=function(t){var e=this.addItems(t);e.length&&(this.layoutItems(e,!0),this.reveal(e))},p.prepended=function(t){var e=this._itemize(t);if(e.length){var i=this.items.slice(0);this.items=e.concat(i),this._resetLayout(),this._manageStamps(),this.layoutItems(e,!0),this.reveal(e),this.layoutItems(i)}},p.reveal=function(t){if(this._emitCompleteOnItems("reveal",t),t&&t.length){var e=this.updateStagger();t.forEach(function(t,i){t.stagger(i*e),t.reveal()})}},p.hide=function(t){if(this._emitCompleteOnItems("hide",t),t&&t.length){var e=this.updateStagger();t.forEach(function(t,i){t.stagger(i*e),t.hide()})}},p.revealItemElements=function(t){var e=this.getItems(t);this.reveal(e)},p.hideItemElements=function(t){var e=this.getItems(t);this.hide(e)},p.getItem=function(t){for(var e=0;e<this.items.length;e++){var i=this.items[e];if(i.element==t)return i}},p.getItems=function(t){t=n.makeArray(t);var e=[];return t.forEach(function(t){var i=this.getItem(t);i&&e.push(i)},this),e},p.remove=function(t){var e=this.getItems(t);this._emitCompleteOnItems("remove",e),e&&e.length&&e.forEach(function(t){t.remove(),n.removeFrom(this.items,t)},this)},p.destroy=function(){var t=this.element.style;t.height="",t.position="",t.width="",this.items.forEach(function(t){t.destroy()}),this.unbindResize();var e=this.element.outlayerGUID;delete c[e],delete this.element.outlayerGUID,l&&l.removeData(this.element,this.constructor.namespace)},r.data=function(t){t=n.getQueryElement(t);var e=t&&t.outlayerGUID;return e&&c[e]},r.create=function(t,e){var i=s(r);return i.defaults=n.extend({},r.defaults),n.extend(i.defaults,e),i.compatOptions=n.extend({},r.compatOptions),i.namespace=t,i.data=r.data,i.Item=s(o),n.htmlInit(i,t),l&&l.bridget&&l.bridget(t,i),i};var f={ms:1,s:1e3};return r.Item=o,r}),function(t,e){"function"==typeof define&&define.amd?define("enviratope/item",["outlayer/outlayer"],e):"object"==typeof module&&module.exports?module.exports=e(require("outlayer")):(t.Enviratope=t.Enviratope||{},t.Enviratope.Item=e(t.Outlayer))}(window,function a(t){"use strict";function e(){t.Item.apply(this,arguments)}var i=e.prototype=Object.create(t.Item.prototype),n=i._create;i._create=function(){this.id=this.layout.itemGUID++,n.call(this),this.sortData={}},i.updateSortData=function(){if(!this.isIgnored){this.sortData.id=this.id,this.sortData["original-order"]=this.id,this.sortData.random=Math.random();var t=this.layout.options.getSortData,e=this.layout._sorters;for(var i in t){var n=e[i];this.sortData[i]=n(this.element,this)}}};var o=i.destroy;return i.destroy=function(){o.apply(this,arguments),this.css({display:""})},e}),function(t,e){"function"==typeof define&&define.amd?define("enviratope/layout-mode",["get-size/get-size","outlayer/outlayer"],e):"object"==typeof module&&module.exports?module.exports=e(require("get-size"),require("outlayer")):(t.Enviratope=t.Enviratope||{},t.Enviratope.LayoutMode=e(t.getSize,t.Outlayer))}(window,function h(t,e){"use strict";function i(t){this.enviratope=t,t&&(this.options=t.options[this.namespace],this.element=t.element,this.items=t.filteredItems,this.size=t.size)}var n=i.prototype,o=["_resetLayout","_getItemLayoutPosition","_manageStamp","_getContainerSize","_getElementOffset","needsResizeLayout","_getOption"];return o.forEach(function(t){n[t]=function(){return e.prototype[t].apply(this.enviratope,arguments)}}),n.needsVerticalResizeLayout=function(){var e=t(this.enviratope.element),i=this.enviratope.size&&e;return i&&e.innerHeight!=this.enviratope.size.innerHeight},n._getMeasurement=function(){this.enviratope._getMeasurement.apply(this,arguments)},n.getColumnWidth=function(){this.getSegmentSize("column","Width")},n.getRowHeight=function(){this.getSegmentSize("row","Height")},n.getSegmentSize=function(t,e){var i=t+e,n="outer"+e;if(this._getMeasurement(i,n),!this[i]){var o=this.getFirstItemSize();this[i]=o&&o[n]||this.enviratope.size["inner"+e]}},n.getFirstItemSize=function(){var e=this.enviratope.filteredItems[0];return e&&e.element&&t(e.element)},n.layout=function(){this.enviratope.layout.apply(this.enviratope,arguments)},n.getSize=function(){this.enviratope.getSize(),this.size=this.enviratope.size},i.modes={},i.create=function(t,e){function o(){i.apply(this,arguments)}return o.prototype=Object.create(n),o.prototype.constructor=o,e&&(o.options=e),o.prototype.namespace=t,i.modes[t]=o,o},i}),function(t,e){"function"==typeof define&&define.amd?define("masonry/masonry",["outlayer/outlayer","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("outlayer"),require("get-size")):t.Masonry=e(t.Outlayer,t.getSize)}(window,function l(t,e){var i=t.create("masonry");return i.compatOptions.fitWidth="isFitWidth",i.prototype._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns(),this.colYs=[];for(var t=0;t<this.cols;t++)this.colYs.push(0);this.maxY=0},i.prototype.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var t=this.items[0],i=t&&t.element;this.columnWidth=i&&e(i).outerWidth||this.containerWidth}var n=this.columnWidth+=this.gutter,o=this.containerWidth+this.gutter,r=o/n,s=n-o%n,a=s&&1>s?"round":"floor";r=Math[a](r),this.cols=Math.max(r,1)},i.prototype.getContainerWidth=function(){var t=this._getOption("fitWidth"),i=t?this.element.parentNode:this.element,n=e(i);this.containerWidth=n&&n.innerWidth},i.prototype._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth%this.columnWidth,i=e&&1>e?"round":"ceil",n=Math[i](t.size.outerWidth/this.columnWidth);n=Math.min(n,this.cols);for(var o=this._getColGroup(n),r=Math.min.apply(Math,o),s=o.indexOf(r),a={x:this.columnWidth*s,y:r},h=r+t.size.outerHeight,l=this.cols+1-o.length,u=0;l>u;u++)this.colYs[s+u]=h;return a},i.prototype._getColGroup=function(t){if(2>t)return this.colYs;for(var e=[],i=this.cols+1-t,n=0;i>n;n++){var o=this.colYs.slice(n,n+t);e[n]=Math.max.apply(Math,o)}return e},i.prototype._manageStamp=function(t){var i=e(t),n=this._getElementOffset(t),o=this._getOption("originLeft"),r=o?n.left:n.right,s=r+i.outerWidth,a=Math.floor(r/this.columnWidth);a=Math.max(0,a);var h=Math.floor(s/this.columnWidth);h-=s%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var l=this._getOption("originTop"),u=(l?n.top:n.bottom)+i.outerHeight,d=a;h>=d;d++)this.colYs[d]=Math.max(u,this.colYs[d])},i.prototype._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this._getOption("fitWidth")&&(t.width=this._getContainerFitWidth()),t},i.prototype._getContainerFitWidth=function(){for(var t=0,e=this.cols;--e&&0===this.colYs[e];)t++;return(this.cols-t)*this.columnWidth-this.gutter},i.prototype.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!=this.containerWidth},i}),function(t,e){"function"==typeof define&&define.amd?define("enviratope/layout-modes/masonry",["../layout-mode","masonry/masonry"],e):"object"==typeof module&&module.exports?module.exports=e(require("../layout-mode"),require("masonry-layout")):e(t.Enviratope.LayoutMode,t.Masonry)}(window,function u(t,e){"use strict";var i=t.create("masonry"),n=i.prototype,o={_getElementOffset:!0,layout:!0,_getMeasurement:!0};for(var r in e.prototype)o[r]||(n[r]=e.prototype[r]);var s=n.measureColumns;n.measureColumns=function(){this.items=this.enviratope.filteredItems,s.call(this)};var a=n._getOption;return n._getOption=function(t){return"fitWidth"==t?void 0!==this.options.isFitWidth?this.options.isFitWidth:this.options.fitWidth:a.apply(this.enviratope,arguments)},i}),function(t,e){"function"==typeof define&&define.amd?define("enviratope/layout-modes/fit-rows",["../layout-mode"],e):"object"==typeof exports?module.exports=e(require("../layout-mode")):e(t.Enviratope.LayoutMode)}(window,function d(t){"use strict";var e=t.create("fitRows"),i=e.prototype;return i._resetLayout=function(){this.x=0,this.y=0,this.maxY=0,this._getMeasurement("gutter","outerWidth")},i._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth+this.gutter,i=this.enviratope.size.innerWidth+this.gutter;0!==this.x&&e+this.x>i&&(this.x=0,this.y=this.maxY);var n={x:this.x,y:this.y};return this.maxY=Math.max(this.maxY,this.y+t.size.outerHeight),this.x+=e,n},i._getContainerSize=function(){return{height:this.maxY}},e}),function(t,e){"function"==typeof define&&define.amd?define("enviratope/layout-modes/vertical",["../layout-mode"],e):"object"==typeof module&&module.exports?module.exports=e(require("../layout-mode")):e(t.Enviratope.LayoutMode)}(window,function c(t){"use strict";var e=t.create("vertical",{horizontalAlignment:0}),i=e.prototype;return i._resetLayout=function(){this.y=0},i._getItemLayoutPosition=function(t){t.getSize();var e=(this.enviratope.size.innerWidth-t.size.outerWidth)*this.options.horizontalAlignment,i=this.y;return this.y+=t.size.outerHeight,{x:e,y:i}},i._getContainerSize=function(){return{height:this.y}},e}),function(t,e){"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size","desandro-matches-selector/matches-selector","fizzy-ui-utils/utils","./item","./layout-mode","./layout-modes/masonry","./layout-modes/fit-rows","./layout-modes/vertical"],function(i,n,o,r,s,a){return e(t,i,n,o,r,s,a)}):"object"==typeof module&&module.exports?module.exports=e(t,require("outlayer"),require("get-size"),require("desandro-matches-selector"),require("fizzy-ui-utils"),require("./item"),require("./layout-mode"),require("./layout-modes/masonry"),require("./layout-modes/fit-rows"),require("./layout-modes/vertical")):t.Enviratope=e(t,t.Outlayer,t.getSize,t.matchesSelector,t.fizzyUIUtils,t.Enviratope.Item,t.Enviratope.LayoutMode)}(window,function p(t,e,i,n,o,r,s){function a(t,e){return function i(n,o){for(var r=0;r<t.length;r++){var s=t[r],a=n.sortData[s],h=o.sortData[s];if(a>h||h>a){var l=void 0!==e[s]?e[s]:e,u=l?1:-1;return(a>h?1:-1)*u}}return 0}}var h=t.jQuery,l=String.prototype.trim?function(t){return t.trim()}:function(t){return t.replace(/^\s+|\s+$/g,"")},u=e.create("enviratope",{layoutMode:"masonry",isJQueryFiltering:!0,sortAscending:!0});u.Item=r,u.LayoutMode=s;var d=u.prototype;d._create=function(){this.itemGUID=0,this._sorters={},this._getSorters(),e.prototype._create.call(this),this.modes={},this.filteredItems=this.items,this.sortHistory=["original-order"];for(var t in s.modes)this._initLayoutMode(t)},d.reloadItems=function(){this.itemGUID=0,e.prototype.reloadItems.call(this)},d._itemize=function(){for(var t=e.prototype._itemize.apply(this,arguments),i=0;i<t.length;i++){var n=t[i];n.id=this.itemGUID++}return this._updateItemsSortData(t),t},d._initLayoutMode=function(t){var e=s.modes[t],i=this.options[t]||{};this.options[t]=e.options?o.extend(e.options,i):i,this.modes[t]=new e(this)},d.layout=function(){return!this._isLayoutInited&&this._getOption("initLayout")?void this.arrange():void this._layout()},d._layout=function(){var t=this._getIsInstant();this._resetLayout(),this._manageStamps(),this.layoutItems(this.filteredItems,t),this._isLayoutInited=!0},d.arrange=function(t){this.option(t),this._getIsInstant();var e=this._filter(this.items);this.filteredItems=e.matches,this._bindArrangeComplete(),this._isInstant?this._noTransition(this._hideReveal,[e]):this._hideReveal(e),this._sort(),this._layout()},d._init=d.arrange,d._hideReveal=function(t){this.reveal(t.needReveal),this.hide(t.needHide)},d._getIsInstant=function(){var t=this._getOption("layoutInstant"),e=void 0!==t?t:!this._isLayoutInited;return this._isInstant=e,e},d._bindArrangeComplete=function(){function t(){e&&i&&n&&o.dispatchEvent("arrangeComplete",null,[o.filteredItems])}var e,i,n,o=this;this.once("layoutComplete",function(){e=!0,t()}),this.once("hideComplete",function(){i=!0,t()}),this.once("revealComplete",function(){n=!0,t()})},d._filter=function(t){var e=this.options.filter;e=e||"*";for(var i=[],n=[],o=[],r=this._getFilterTest(e),s=0;s<t.length;s++){var a=t[s];if(!a.isIgnored){var h=r(a);h&&i.push(a),h&&a.isHidden?n.push(a):h||a.isHidden||o.push(a)}}return{matches:i,needReveal:n,needHide:o}},d._getFilterTest=function(t){return h&&this.options.isJQueryFiltering?function(e){return h(e.element).is(t)}:"function"==typeof t?function(e){return t(e.element)}:function(e){return n(e.element,t)}},d.updateSortData=function(t){var e;t?(t=o.makeArray(t),e=this.getItems(t)):e=this.items,this._getSorters(),this._updateItemsSortData(e)},d._getSorters=function(){var t=this.options.getSortData;for(var e in t){var i=t[e];this._sorters[e]=c(i)}},d._updateItemsSortData=function(t){for(var e=t&&t.length,i=0;e&&e>i;i++){var n=t[i];n.updateSortData()}};var c=function(){function t(t){if("string"!=typeof t)return t;var i=l(t).split(" "),n=i[0],o=n.match(/^\[(.+)\]$/),r=o&&o[1],s=e(r,n),a=u.sortDataParsers[i[1]];return t=a?function(t){return t&&a(s(t))}:function(t){return t&&s(t)}}function e(t,e){return t?function i(e){return e.getAttribute(t)}:function n(t){var i=t.querySelector(e);return i&&i.textContent}}return t}();u.sortDataParsers={parseInt:function(t){return parseInt(t,10)},parseFloat:function(t){return parseFloat(t)}},d._sort=function(){var t=this.options.sortBy;if(t){var e=[].concat.apply(t,this.sortHistory),i=a(e,this.options.sortAscending);this.filteredItems.sort(i),t!=this.sortHistory[0]&&this.sortHistory.unshift(t)}},d._mode=function(){var t=this.options.layoutMode,e=this.modes[t];if(!e)throw new Error("No layout mode: "+t);return e.options=this.options[t],e},d._resetLayout=function(){e.prototype._resetLayout.call(this),this._mode()._resetLayout()},d._getItemLayoutPosition=function(t){return this._mode()._getItemLayoutPosition(t)},d._manageStamp=function(t){this._mode()._manageStamp(t)},d._getContainerSize=function(){return this._mode()._getContainerSize()},d.needsResizeLayout=function(){return this._mode().needsResizeLayout()},d.appended=function(t){var e=this.addItems(t);if(e.length){var i=this._filterRevealAdded(e);this.filteredItems=this.filteredItems.concat(i)}},d.prepended=function(t){var e=this._itemize(t);if(e.length){this._resetLayout(),this._manageStamps();var i=this._filterRevealAdded(e);this.layoutItems(this.filteredItems),this.filteredItems=i.concat(this.filteredItems),this.items=e.concat(this.items)}},d._filterRevealAdded=function(t){var e=this._filter(t);return this.hide(e.needHide),this.reveal(e.matches),this.layoutItems(e.matches,!0),e.matches},d.insert=function(t){var e=this.addItems(t);if(e.length){var i,n,o=e.length;for(i=0;o>i;i++)n=e[i],this.element.appendChild(n.element);var r=this._filter(e).matches;for(i=0;o>i;i++)e[i].isLayoutInstant=!0;for(this.arrange(),i=0;o>i;i++)delete e[i].isLayoutInstant;this.reveal(r)}};var p=d.remove;return d.remove=function(t){t=o.makeArray(t);var e=this.getItems(t);p.call(this,t);for(var i=e&&e.length,n=0;i&&i>n;n++){var r=e[n];o.removeFrom(this.filteredItems,r)}},d.shuffle=function(){for(var t=0;t<this.items.length;t++){var e=this.items[t];e.sortData.random=Math.random()}this.options.sortBy="random",this._sort(),this._layout()},d._noTransition=function(t,e){var i=this.options.transitionDuration;this.options.transitionDuration=0;var n=t.apply(this,e);return this.options.transitionDuration=i,n},d.getFilteredItemElements=function(){return this.filteredItems.map(function(t){return t.element})},u}),function(t,e,$,i){"use strict";var n=$("html"),o=$(t),r=$(e),s=$.envirabox=function(){s.open.apply(this,arguments)},a=navigator.userAgent.match(/msie/i),h=null,l=e.createTouch!==i,u=function(t){return t&&t.hasOwnProperty&&t instanceof $},d=function(t){return t&&"string"===$.type(t)},c=function(t){return d(t)&&t.indexOf("%")>0},p=function(t){return t&&!(t.style.overflow&&"hidden"===t.style.overflow)&&(t.clientWidth&&t.scrollWidth>t.clientWidth||t.clientHeight&&t.scrollHeight>t.clientHeight)},f=function(t,e){var i=parseInt(t,10)||0;return e&&c(t)&&(i=s.getViewport()[e]/100*i),Math.ceil(i)},g=function(t,e){return f(t,e)+"px"};$.extend(s,{version:"2.1.5",defaults:{padding:15,margin:40,width:800,height:600,minWidth:100,minHeight:100,maxWidth:9999,maxHeight:9999,pixelRatio:1,autoSize:!0,autoHeight:!1,autoWidth:!1,autoResize:!0,autoCenter:!l,fitToView:!0,aspectRatio:!1,topRatio:.5,leftRatio:.5,scrolling:"auto",wrapCSS:"",arrows:!0,closeBtn:!0,closeClick:!1,nextClick:!1,mouseWheel:!0,autoPlay:!1,playSpeed:3e3,preload:3,modal:!1,loop:!0,ajax:{dataType:"html",headers:{"X-envirabox":!0}},iframe:{scrolling:"auto",preload:!0},swf:{wmode:"transparent",allowfullscreen:"true",allowscriptaccess:"always"},keys:{next:{13:"left",34:"up",39:"left",40:"up"},prev:{8:"right",33:"down",37:"right",38:"down"},close:[27],play:[32],toggle:[70]},direction:{next:"left",prev:"right"},scrollOutside:!0,index:0,type:null,href:null,content:null,title:null,tpl:{wrap:'<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin"><div class="envirabox-outer"><div class="envirabox-inner"></div></div></div></div>',image:'<img class="envirabox-image" src="{href}" />',iframe:'<iframe id="envirabox-frame{rnd}" name="envirabox-frame{rnd}" class="envirabox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen'+(a?' allowtransparency="true"':"")+"></iframe>",error:'<p class="envirabox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',closeBtn:'<a title="Close" class="envirabox-item envirabox-close" href="javascript:;"></a>',next:'<a title="Next" class="envirabox-nav envirabox-next" href="javascript:;"><span></span></a>',prev:'<a title="Previous" class="envirabox-nav envirabox-prev" href="javascript:;"><span></span></a>'},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0,openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:$.noop,beforeLoad:$.noop,afterLoad:$.noop,beforeShow:$.noop,afterShow:$.noop,beforeChange:$.noop,beforeClose:$.noop,afterClose:$.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1,isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(t,e,n){return t&&(n&&(t=n),$.isPlainObject(e)||(e={}),!1!==s.close(!0))?($.isArray(t)||(t=u(t)?$(t).get():[t]),$.each(t,function(n,o){var r={},a,h,l,c,p,f,g;"object"===$.type(o)&&(o.nodeType&&(o=$(o)),u(o)?(r={href:o.data("envirabox-href")||o.attr("href"),title:$("<div/>").text(o.data("envirabox-title")||o.attr("title")).html(),isDom:!0,element:o},$.metadata&&$.extend(!0,r,o.metadata())):r=o),a=e.href||r.href||(d(o)?o:null),h=e.title!==i?e.title:r.title||"",l=e.content||r.content,c=l?"html":e.type||r.type,!c&&r.isDom&&(c=o.data("envirabox-type"),c||(p=o.prop("class").match(/envirabox\.(\w+)/),c=p?p[1]:null)),d(a)&&(c||(s.isImage(a)?c="image":s.isSWF(a)?c="swf":"#"===a.charAt(0)?c="inline":d(o)&&(c="html",l=o)),"ajax"===c&&(f=a.split(/\s+/,2),a=f.shift(),g=f.shift())),l||("inline"===c?a?l=$(d(a)?a.replace(/.*(?=#[^\s]+$)/,""):a):r.isDom&&(l=o):"html"===c?l=a:c||a||!r.isDom||(c="inline",l=o)),$.extend(r,{href:a,type:c,content:l,title:h,selector:g}),t[n]=r}),s.opts=$.extend(!0,{},s.defaults,e),e.keys!==i&&(s.opts.keys=e.keys?$.extend({},s.defaults.keys,e.keys):!1),s.group=t,s._start(s.opts.index)):void 0},cancel:function(){var t=s.coming;t&&!1===s.trigger("onCancel")||(s.hideLoading(),t&&(s.ajaxLoad&&s.ajaxLoad.abort(),s.ajaxLoad=null,s.imgPreload&&(s.imgPreload.onload=s.imgPreload.onerror=null),t.wrap&&t.wrap.stop(!0,!0).trigger("onReset").remove(),s.coming=null,s.current||s._afterZoomOut(t)))},close:function(t){s.cancel(),!1!==s.trigger("beforeClose")&&(s.unbindEvents(),s.isActive&&(s.isOpen&&t!==!0?(s.isOpen=s.isOpened=!1,s.isClosing=!0,$(".envirabox-item, .envirabox-nav").remove(),s.wrap.stop(!0,!0).removeClass("envirabox-opened"),s.transitions[s.current.closeMethod]()):($(".envirabox-wrap").stop(!0).trigger("onReset").remove(),s._afterZoomOut())))},play:function(t){var e=function(){clearTimeout(s.player.timer)},i=function(){e(),s.current&&s.player.isActive&&(s.player.timer=setTimeout(s.next,s.current.playSpeed))},n=function(){e(),r.unbind(".player"),s.player.isActive=!1,s.trigger("onPlayEnd")},o=function(){s.current&&(s.current.loop||s.current.index<s.group.length-1)&&(s.player.isActive=!0,r.bind({"onCancel.player beforeClose.player":n,"onUpdate.player":i,"beforeLoad.player":e}),i(),s.trigger("onPlayStart"))};t===!0||!s.player.isActive&&t!==!1?o():n()},next:function(t){var e=s.current;e&&(d(t)||(t=e.direction.next),s.jumpto(e.index+1,t,"next"))},prev:function(t){var e=s.current;e&&(d(t)||(t=e.direction.prev),s.jumpto(e.index-1,t,"prev"))},jumpto:function(t,e,n){var o=s.current;o&&(t=f(t),s.direction=e||o.direction[t>=o.index?"next":"prev"],s.router=n||"jumpto",o.loop&&(0>t&&(t=o.group.length+t%o.group.length),t%=o.group.length),o.group[t]!==i&&(s.cancel(),s._start(t)))},reposition:function(t,e){var i=s.current,n=i?i.wrap:null,o;n&&(o=s._getPosition(e),t&&"scroll"===t.type?(delete o.position,n.stop(!0,!0).animate(o,200)):(n.css(o),i.pos=$.extend({},i.dim,o)))},update:function(t){var e=t&&t.originalEvent&&t.originalEvent.type,i=!e||"orientationchange"===e;i&&(clearTimeout(h),h=null),s.isOpen&&!h&&(h=setTimeout(function(){var n=s.current;n&&!s.isClosing&&(s.wrap.removeClass("envirabox-tmp"),(i||"load"===e||"resize"===e&&n.autoResize)&&s._setDimension(),"scroll"===e&&n.canShrink||s.reposition(t),s.trigger("onUpdate"),h=null)},i&&!l?0:300))},toggle:function(t){s.isOpen&&(s.current.fitToView="boolean"===$.type(t)?t:!s.current.fitToView,l&&(s.wrap.removeAttr("style").addClass("envirabox-tmp"),
11
+ s.trigger("onUpdate")),s.update())},hideLoading:function(){r.unbind(".loading"),$("#envirabox-loading").remove()},showLoading:function(){var t,e;s.hideLoading(),t=$('<div id="envirabox-loading"><div></div></div>').click(s.cancel).appendTo("body"),r.bind("keydown.loading",function(t){27===(t.which||t.keyCode)&&(t.preventDefault(),s.cancel())}),s.defaults.fixed||(e=s.getViewport(),t.css({position:"absolute",top:.5*e.h+e.y,left:.5*e.w+e.x})),s.trigger("onLoading")},getViewport:function(){var e=s.current&&s.current.locked||!1,i={x:o.scrollLeft(),y:o.scrollTop()};return e&&e.length?(i.w=e[0].clientWidth,i.h=e[0].clientHeight):(i.w=l&&t.innerWidth?t.innerWidth:o.width(),i.h=l&&t.innerHeight?t.innerHeight:o.height()),i},unbindEvents:function(){s.wrap&&u(s.wrap)&&s.wrap.unbind(".fb"),r.unbind(".fb"),o.unbind(".fb")},bindEvents:function(){var t=s.current,e;t&&(o.bind("orientationchange.fb"+(l?"":" resize.fb")+(t.autoCenter&&!t.locked?" scroll.fb":""),s.update),e=t.keys,e&&r.bind("keydown.fb",function(n){var o=n.which||n.keyCode,r=n.target||n.srcElement;return 27===o&&s.coming?!1:void(n.ctrlKey||n.altKey||n.shiftKey||n.metaKey||r&&(r.type||$(r).is("[contenteditable]"))||$.each(e,function(e,r){return t.group.length>1&&r[o]!==i?(s[e](r[o]),n.preventDefault(),!1):$.inArray(o,r)>-1?(s[e](),n.preventDefault(),!1):void 0}))}),$.fn.mousewheel&&t.mouseWheel&&s.wrap.bind("mousewheel.fb",function(e,i,n,o){for(var r=e.target||null,a=$(r),h=!1;a.length&&!(h||a.is(".envirabox-skin")||a.is(".envirabox-wrap"));)h=p(a[0]),a=$(a).parent();0===i||h||s.group.length>1&&!t.canShrink&&(o>0||n>0?s.prev(o>0?"down":"left"):(0>o||0>n)&&s.next(0>o?"up":"right"),e.preventDefault())}))},trigger:function(t,e){var i,n=e||s.coming||s.current;if(n){if($.isFunction(n[t])&&(i=n[t].apply(n,Array.prototype.slice.call(arguments,1))),i===!1)return!1;n.helpers&&$.each(n.helpers,function(e,i){i&&s.helpers[e]&&$.isFunction(s.helpers[e][t])&&s.helpers[e][t]($.extend(!0,{},s.helpers[e].defaults,i),n)})}r.trigger(t)},isImage:function(t){return d(t)&&t.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(t){return d(t)&&t.match(/\.(swf)((\?|#).*)?$/i)},_start:function(t){var e={},i,n,o,r,a;if(t=f(t),i=s.group[t]||null,!i)return!1;if(e=$.extend(!0,{},s.opts,i),r=e.margin,a=e.padding,"number"===$.type(r)&&(e.margin=[r,r,r,r]),"number"===$.type(a)&&(e.padding=[a,a,a,a]),e.modal&&$.extend(!0,e,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}}),e.autoSize&&(e.autoWidth=e.autoHeight=!0),"auto"===e.width&&(e.autoWidth=!0),"auto"===e.height&&(e.autoHeight=!0),e.group=s.group,e.index=t,s.coming=e,!1===s.trigger("beforeLoad"))return void(s.coming=null);if(o=e.type,n=e.href,!o)return s.coming=null,s.current&&s.router&&"jumpto"!==s.router?(s.current.index=t,s[s.router](s.direction)):!1;if(s.isActive=!0,"image"!==o&&"swf"!==o||(e.autoHeight=e.autoWidth=!1,e.scrolling="visible"),"image"===o&&(e.aspectRatio=!0),"iframe"===o&&l&&(e.scrolling="scroll"),e.wrap=$(e.tpl.wrap).addClass("envirabox-"+(l?"mobile":"desktop")+" envirabox-type-"+o+" envirabox-tmp "+e.wrapCSS).appendTo(e.parent||"body"),$.extend(e,{skin:$(".envirabox-skin",e.wrap),outer:$(".envirabox-outer",e.wrap),inner:$(".envirabox-inner",e.wrap)}),$.each(["Top","Right","Bottom","Left"],function(t,i){e.skin.css("padding"+i,g(e.padding[t]))}),s.trigger("onReady"),"inline"===o||"html"===o){if(!e.content||!e.content.length)return s._error("content")}else if(!n)return s._error("href");"image"===o?s._loadImage():"ajax"===o?s._loadAjax():"iframe"===o?s._loadIframe():s._afterLoad()},_error:function(t){$.extend(s.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:t,content:s.coming.tpl.error}),s._afterLoad()},_loadImage:function(){var t=s.imgPreload=new Image;t.onload=function(){this.onload=this.onerror=null,s.coming.width=this.width/s.opts.pixelRatio,s.coming.height=this.height/s.opts.pixelRatio,s._afterLoad()},t.onerror=function(){this.onload=this.onerror=null,s._error("image")},t.src=s.coming.href,t.complete!==!0&&s.showLoading()},_loadAjax:function(){var t=s.coming;s.showLoading(),s.ajaxLoad=$.ajax($.extend({},t.ajax,{url:t.href,error:function(t,e){s.coming&&"abort"!==e?s._error("ajax",t):s.hideLoading()},success:function(e,i){"success"===i&&(t.content=e,s._afterLoad())}}))},_loadIframe:function(){var t=s.coming,e=$(t.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",l?"auto":t.iframe.scrolling).attr("src",t.href);$(t.wrap).bind("onReset",function(){try{$(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(t){}}),t.iframe.preload&&(s.showLoading(),e.one("load",function(){$(this).data("ready",1),l||$(this).bind("load.fb",s.update),$(this).parents(".envirabox-wrap").width("100%").removeClass("envirabox-tmp").show(),s._afterLoad()})),t.content=e.appendTo(t.inner),t.iframe.preload||s._afterLoad()},_preloadImages:function(){var t=s.group,e=s.current,i=t.length,n=e.preload?Math.min(e.preload,i-1):0,o,r;for(r=1;n>=r;r+=1)o=t[(e.index+r)%i],"image"===o.type&&o.href&&((new Image).src=o.href)},_afterLoad:function(){var t=s.coming,e=s.current,i="envirabox-placeholder",n,o,r,a,h,l;if(s.hideLoading(),t&&s.isActive!==!1){if(!1===s.trigger("afterLoad",t,e))return t.wrap.stop(!0).trigger("onReset").remove(),void(s.coming=null);switch(e&&(s.trigger("beforeChange",e),e.wrap.stop(!0).removeClass("envirabox-opened").find(".envirabox-item, .envirabox-nav").remove()),s.unbindEvents(),n=t,o=t.content,r=t.type,a=t.scrolling,$.extend(s,{wrap:n.wrap,skin:n.skin,outer:n.outer,inner:n.inner,current:n,previous:e}),h=n.href,r){case"inline":case"ajax":case"html":n.selector?o=$("<div>").html(o).find(n.selector):u(o)&&(o.data(i)||o.data(i,$('<div class="'+i+'"></div>').insertAfter(o).hide()),o=o.show().detach(),n.wrap.bind("onReset",function(){$(this).find(o).length&&o.hide().replaceAll(o.data(i)).data(i,!1)}));break;case"image":o=n.tpl.image.replace(/\{href\}/g,h);break;case"swf":o='<object id="envirabox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="'+h+'"></param>',l="",$.each(n.swf,function(t,e){o+='<param name="'+t+'" value="'+e+'"></param>',l+=" "+t+'="'+e+'"'}),o+='<embed src="'+h+'" type="application/x-shockwave-flash" width="100%" height="100%"'+l+"></embed></object>"}u(o)&&o.parent().is(n.inner)||n.inner.append(o),s.trigger("beforeShow"),n.inner.css("overflow","yes"===a?"scroll":"no"===a?"hidden":a),s._setDimension(),s.reposition(),s.isOpen=!1,s.coming=null,s.bindEvents(),s.isOpened?e.prevMethod&&s.transitions[e.prevMethod]():$(".envirabox-wrap").not(n.wrap).stop(!0).trigger("onReset").remove(),s.transitions[s.isOpened?n.nextMethod:n.openMethod](),s._preloadImages()}},_setDimension:function(){var t=s.getViewport(),e=0,i=!1,n=!1,o=s.wrap,r=s.skin,a=s.inner,h=s.current,l=h.width,u=h.height,d=h.minWidth,p=h.minHeight,m=h.maxWidth,v=h.maxHeight,y=h.scrolling,w=h.scrollOutside?h.scrollbarWidth:0,b=h.margin,x=f(b[1]+b[3]),S=f(b[0]+b[2]),I,E,_,C,T,R,z,j,O,L,k,M,D,H,W;if(o.add(r).add(a).width("auto").height("auto").removeClass("envirabox-tmp"),I=f(r.outerWidth(!0)-r.width()),E=f(r.outerHeight(!0)-r.height()),_=x+I,C=S+E,T=c(l)?(t.w-_)*f(l)/100:l,R=c(u)?(t.h-C)*f(u)/100:u,"iframe"===h.type){if(H=h.content,h.autoHeight&&1===H.data("ready"))try{H[0].contentWindow.document.location&&(a.width(T).height(9999),W=H.contents().find("body"),w&&W.css("overflow-x","hidden"),R=W.outerHeight(!0))}catch(A){}}else(h.autoWidth||h.autoHeight)&&(a.addClass("envirabox-tmp"),h.autoWidth||a.width(T),h.autoHeight||a.height(R),h.autoWidth&&(T=a.width()),h.autoHeight&&(R=a.height()),a.removeClass("envirabox-tmp"));if(l=f(T),u=f(R),O=T/R,d=f(c(d)?f(d,"w")-_:d),m=f(c(m)?f(m,"w")-_:m),p=f(c(p)?f(p,"h")-C:p),v=f(c(v)?f(v,"h")-C:v),z=m,j=v,h.fitToView&&(m=Math.min(t.w-_,m),v=Math.min(t.h-C,v)),M=t.w-x,D=t.h-S,h.aspectRatio?(l>m&&(l=m,u=f(l/O)),u>v&&(u=v,l=f(u*O)),d>l&&(l=d,u=f(l/O)),p>u&&(u=p,l=f(u*O))):(l=Math.max(d,Math.min(l,m)),h.autoHeight&&"iframe"!==h.type&&(a.width(l),u=a.height()),u=Math.max(p,Math.min(u,v))),h.fitToView)if(a.width(l).height(u),o.width(l+I),L=o.width(),k=o.height(),h.aspectRatio)for(;(L>M||k>D)&&l>d&&u>p&&!(e++>19);)u=Math.max(p,Math.min(v,u-10)),l=f(u*O),d>l&&(l=d,u=f(l/O)),l>m&&(l=m,u=f(l/O)),a.width(l).height(u),o.width(l+I),L=o.width(),k=o.height();else l=Math.max(d,Math.min(l,l-(L-M))),u=Math.max(p,Math.min(u,u-(k-D)));w&&"auto"===y&&R>u&&M>l+I+w&&(l+=w),a.width(l).height(u),o.width(l+I),L=o.width(),k=o.height(),i=(L>M||k>D)&&l>d&&u>p,n=h.aspectRatio?z>l&&j>u&&T>l&&R>u:(z>l||j>u)&&(T>l||R>u),$.extend(h,{dim:{width:g(L),height:g(k)},origWidth:T,origHeight:R,canShrink:i,canExpand:n,wPadding:I,hPadding:E,wrapSpace:k-r.outerHeight(!0),skinSpace:r.height()-u}),!H&&h.autoHeight&&u>p&&v>u&&!n&&a.height("auto")},_getPosition:function(t){var e=s.current,i=s.getViewport(),n=e.margin,o=s.wrap.width()+n[1]+n[3],r=s.wrap.height()+n[0]+n[2],a={position:"absolute",top:n[0],left:n[3]};return e.helpers.title.type&&"float"==e.helpers.title.type&&(r+=$(".envirabox-skin .envirabox-title").height()),e.autoCenter&&e.fixed&&!t&&r<=i.h&&o<=i.w?a.position="fixed":e.locked||(a.top+=i.y,a.left+=i.x),a.top=g(Math.max(a.top,a.top+(i.h-r)*e.topRatio)),a.left=g(Math.max(a.left,a.left+(i.w-o)*e.leftRatio)),a},_afterZoomIn:function(){var t=s.current;t&&(s.isOpen=s.isOpened=!0,s.wrap.css("overflow","visible").addClass("envirabox-opened").hide().show(0),s.update(),(t.closeClick||t.nextClick&&s.group.length>1)&&s.inner.css("cursor","pointer").bind("click.fb",function(e){$(e.target).is("a")||$(e.target).parent().is("a")||(e.preventDefault(),s[t.closeClick?"close":"next"]())}),t.closeBtn&&$(t.tpl.closeBtn).appendTo(s.skin).bind("click.fb",function(t){t.preventDefault(),s.close()}),t.arrows&&s.group.length>1&&((t.loop||t.index>0)&&$(t.tpl.prev).appendTo(s.outer).bind("click.fb",s.prev),(t.loop||t.index<s.group.length-1)&&$(t.tpl.next).appendTo(s.outer).bind("click.fb",s.next)),s.trigger("afterShow"),t.loop||t.index!==t.group.length-1?s.opts.autoPlay&&!s.player.isActive&&(s.opts.autoPlay=!1,s.play(!0)):s.play(!1))},_afterZoomOut:function(t){t=t||s.current,$(".envirabox-wrap").trigger("onReset").remove(),$.extend(s,{group:{},opts:{},router:!1,current:null,isActive:!1,isOpened:!1,isOpen:!1,isClosing:!1,wrap:null,skin:null,outer:null,inner:null}),s.trigger("afterClose",t)}}),s.transitions={getOrigPosition:function(){var t=s.current,e=t.element,i=t.orig,n={},o=50,r=50,a=t.hPadding,h=t.wPadding,l=s.getViewport();return!i&&t.isDom&&e.is(":visible")&&(i=e.find("img:first"),i.length||(i=e)),u(i)?(n=i.offset(),i.is("img")&&(o=i.outerWidth(),r=i.outerHeight())):(n.top=l.y+(l.h-r)*t.topRatio,n.left=l.x+(l.w-o)*t.leftRatio),("fixed"===s.wrap.css("position")||t.locked)&&(n.top-=l.y,n.left-=l.x),n={top:g(n.top-a*t.topRatio),left:g(n.left-h*t.leftRatio),width:g(o+h),height:g(r+a)}},step:function(t,e){var i,n,o,r=e.prop,a=s.current,h=a.wrapSpace,l=a.skinSpace;"width"!==r&&"height"!==r||(i=e.end===e.start?1:(t-e.start)/(e.end-e.start),s.isClosing&&(i=1-i),n="width"===r?a.wPadding:a.hPadding,o=t-n,s.skin[r](f("width"===r?o:o-h*i)),s.inner[r](f("width"===r?o:o-h*i-l*i)))},zoomIn:function(){var t=s.current,e=t.pos,i=t.openEffect,n="elastic"===i,o=$.extend({opacity:1},e);delete o.position,n?(e=this.getOrigPosition(),t.openOpacity&&(e.opacity=.1)):"fade"===i&&(e.opacity=.1),s.wrap.css(e).animate(o,{duration:"none"===i?0:t.openSpeed,easing:t.openEasing,step:n?this.step:null,complete:s._afterZoomIn})},zoomOut:function(){var t=s.current,e=t.closeEffect,i="elastic"===e,n={opacity:.1};i&&(n=this.getOrigPosition(),t.closeOpacity&&(n.opacity=.1)),s.wrap.animate(n,{duration:"none"===e?0:t.closeSpeed,easing:t.closeEasing,step:i?this.step:null,complete:s._afterZoomOut})},changeIn:function(){var t=s.current,e=t.nextEffect,i=t.pos,n={opacity:1},o=s.direction,r=200,a;i.opacity=.1,"elastic"===e&&(a="down"===o||"up"===o?"top":"left","down"===o||"right"===o?(i[a]=g(f(i[a])-r),n[a]="+="+r+"px"):(i[a]=g(f(i[a])+r),n[a]="-="+r+"px")),"none"===e?s._afterZoomIn():s.wrap.css(i).animate(n,{duration:t.nextSpeed,easing:t.nextEasing,complete:s._afterZoomIn})},changeOut:function(){var t=s.previous,e=t.prevEffect,i={opacity:.1},n=s.direction,o=200;"elastic"===e&&(i["down"===n||"up"===n?"top":"left"]=("up"===n||"left"===n?"-":"+")+"="+o+"px"),t.wrap.animate(i,{duration:"none"===e?0:t.prevSpeed,easing:t.prevEasing,complete:function(){$(this).trigger("onReset").remove()}})}},s.helpers.overlay={defaults:{closeClick:!0,speedOut:200,showEarly:!0,css:{},locked:!l,fixed:!0},overlay:null,fixed:!1,el:$("html"),create:function(t){var e;t=$.extend({},this.defaults,t),this.overlay&&this.close(),e=s.coming?s.coming.parent:t.parent,this.overlay=$('<div class="envirabox-overlay"></div>').appendTo(e&&e.lenth?e:"body"),this.fixed=!1,t.fixed&&s.defaults.fixed&&(this.overlay.addClass("envirabox-overlay-fixed"),this.fixed=!0)},open:function(t){var e=this;t=$.extend({},this.defaults,t),this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(t),this.fixed||(o.bind("resize.overlay",$.proxy(this.update,this)),this.update()),t.closeClick&&this.overlay.bind("click.overlay",function(t){return $(t.target).hasClass("envirabox-overlay")?(s.isActive?s.close():e.close(),!1):void 0}),this.overlay.css(t.css).show()},close:function(){o.unbind("resize.overlay"),this.el.hasClass("envirabox-lock")&&($(".envirabox-margin").removeClass("envirabox-margin"),this.el.removeClass("envirabox-lock"),o.scrollTop(this.scrollV).scrollLeft(this.scrollH)),$(".envirabox-overlay").remove().hide(),$.extend(this,{overlay:null,fixed:!1})},update:function(){var t="100%",i;this.overlay.width(t).height("100%"),a?(i=Math.max(e.documentElement.offsetWidth,e.body.offsetWidth),r.width()>i&&(t=r.width())):r.width()>o.width()&&(t=r.width()),this.overlay.width(t).height(r.height())},onReady:function(t,e){var i=this.overlay;$(".envirabox-overlay").stop(!0,!0),i||this.create(t),t.locked&&this.fixed&&e.fixed&&(e.locked=this.overlay.append(e.wrap),e.fixed=!1),t.showEarly===!0&&this.beforeShow.apply(this,arguments)},beforeShow:function(t,e){e.locked&&!this.el.hasClass("envirabox-lock")&&(this.fixPosition!==!1&&$("*").filter(function(){return"fixed"===$(this).css("position")&&!$(this).hasClass("envirabox-overlay")&&!$(this).hasClass("envirabox-wrap")}).addClass("envirabox-margin"),this.el.addClass("envirabox-margin"),this.scrollV=o.scrollTop(),this.scrollH=o.scrollLeft(),this.el.addClass("envirabox-lock"),o.scrollTop(this.scrollV).scrollLeft(this.scrollH)),this.open(t)},onUpdate:function(){this.fixed||this.update()},afterClose:function(t){this.overlay&&!s.coming&&this.overlay.fadeOut(t.speedOut,$.proxy(this.close,this))}},s.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(t){var e=s.current,i=e.title,n=t.type,o,r;if($.isFunction(i)&&(i=i.call(e.element,e)),d(i)&&""!==$.trim(i)){switch(o=$('<div class="envirabox-title envirabox-title-'+n+'-wrap">'+i+"</div>"),n){case"inside":r=s.skin;break;case"outside":r=s.wrap;break;case"over":r=s.inner;break;default:r=s.skin,o.appendTo("body"),a&&o.width(o.width()),o.wrapInner('<span class="child"></span>'),s.current.margin[2]+=Math.abs(f(o.css("margin-bottom")))}o["top"===t.position?"prependTo":"appendTo"](r)}}},$.fn.envirabox=function(t,e){var i,n=$(this),o=this.selector||"",a=function(r){var a=$(this).blur(),h=i,l,u;r.ctrlKey||r.altKey||r.shiftKey||r.metaKey||a.is(".envirabox-wrap")||(l=t.groupAttr||"data-envirabox-group",u=a.attr(l),u||(l="rel",u=a.get(0)[l]),u&&""!==u&&"nofollow"!==u&&(a=o.length?$(o):n,a=a.filter("["+l+'="'+u+'"]'),h=a.index(this)),t.index=h,s.open(a,t,e)!==!1&&r.preventDefault())};return t=t||{},i=t.index||0,o&&t.live!==!1?r.undelegate(o,"click.fb-start").delegate(o+":not('.envirabox-item, .envirabox-nav')","click.fb-start",a):n.unbind("click.fb-start").bind("click.fb-start",a),this.filter("[data-envirabox-start=1]").trigger("click"),this},r.ready(function(){var e,o;$.scrollbarWidth===i&&($.scrollbarWidth=function(){var t=$('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo("body"),e=t.children(),i=e.innerWidth()-e.height(99).innerWidth();return t.remove(),i}),$.support.fixedPosition===i&&($.support.fixedPosition=function(){var t=$('<div style="position:fixed;top:20px;"></div>').appendTo("body"),e=20===t[0].offsetTop||15===t[0].offsetTop;return t.remove(),e}()),$.extend(s.defaults,{scrollbarWidth:$.scrollbarWidth(),fixed:$.support.fixedPosition,parent:$("body")}),e=$(t).width(),n.addClass("envirabox-lock-test"),o=$(t).width(),n.removeClass("envirabox-lock-test"),$("<style type='text/css'>.envirabox-margin{margin-right:"+(o-e)+"px;}</style>").appendTo("head")})}(window,document,jQuery),function($){var t=$.envirabox;t.helpers.buttons={defaults:{skipSingle:!1,position:"top",inline:!1,tpl:'<div id="envirabox-buttons"><ul><li><a class="btnPrev" title="Previous" href="javascript:;"></a></li><li><a class="btnPlay" title="Start slideshow" href="javascript:;"></a></li><li><a class="btnNext" title="Next" href="javascript:;"></a></li><li><a class="btnToggle" title="Toggle size" href="javascript:;"></a></li><li><a class="btnClose" title="Close" href="javascript:;"></a></li></ul></div>'},list:null,buttons:null,beforeLoad:function(t,e){return t.skipSingle&&e.group.length<2?(e.helpers.buttons=!1,void(e.closeBtn=!0)):(e.margin["bottom"===t.position?2:0]+=30,void 0!=e.helpers.thumbs&&"top"==t.position&&"top"==e.helpers.thumbs.position&&(e.helpers.thumbs.position="top has-other-content"),void(void 0!=e.helpers.thumbs&&"bottom"==t.position&&"bottom"==e.helpers.thumbs.position&&(e.helpers.thumbs.position="bottom has-other-content")))},onPlayStart:function(){this.buttons&&this.buttons.play.attr("title","Pause slideshow").addClass("btnPlayOn")},onPlayEnd:function(){this.buttons&&this.buttons.play.attr("title","Start slideshow").removeClass("btnPlayOn")},afterShow:function(e,i){var n=this.buttons;n||(this.list=$(e.tpl).addClass(e.position).appendTo("body"),e.inline&&this.list.addClass("inline"),n={prev:this.list.find(".btnPrev").click(t.prev),next:this.list.find(".btnNext").click(t.next),play:this.list.find(".btnPlay").click(t.play),toggle:this.list.find(".btnToggle").click(t.toggle),close:this.list.find(".btnClose").click(t.close)}),i.index>0||i.loop?n.prev.removeClass("btnDisabled"):n.prev.addClass("btnDisabled"),i.loop||i.index<i.group.length-1?(n.next.removeClass("btnDisabled"),n.play.removeClass("btnDisabled")):(n.next.addClass("btnDisabled"),n.play.addClass("btnDisabled")),this.buttons=n,this.onUpdate(e,i)},onUpdate:function(t,e){var i;this.buttons&&(i=this.buttons.toggle.removeClass("btnDisabled btnToggleOn"),e.canShrink?i.addClass("btnToggleOn"):e.canExpand||i.addClass("btnDisabled"))},beforeClose:function(){this.list&&this.list.remove(),this.list=null,this.buttons=null}}}(jQuery),function($){"use strict";var t=$.envirabox,e=function(t,e,i){return i=i||"","object"===$.type(i)&&(i=$.param(i,!0)),$.each(e,function(e,i){t=t.replace("$"+e,i||"")}),i.length&&(t+=(t.indexOf("?")>0?"&":"?")+i),t};t.helpers.media={defaults:{youtube:{matcher:/(youtube\.com|youtu\.be|youtube-nocookie\.com)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i,params:{autoplay:1,autohide:1,fs:1,rel:0,hd:1,wmode:"opaque",enablejsapi:1},type:"iframe",url:"//www.youtube.com/embed/$3"},vimeo:{matcher:/(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/,params:{autoplay:1,hd:1,show_title:1,show_byline:1,show_portrait:0,fullscreen:1},type:"iframe",url:"//player.vimeo.com/video/$1"},metacafe:{matcher:/metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/,params:{autoPlay:"yes"},type:"swf",url:function(t,e,i){return i.swf.flashVars="playerVars="+$.param(e,!0),"//www.metacafe.com/fplayer/"+t[1]+"/.swf"}},dailymotion:{matcher:/dailymotion.com\/video\/(.*)\/?(.*)/,params:{additionalInfos:0,autoStart:1},type:"swf",url:"//www.dailymotion.com/swf/video/$1"},twitvid:{matcher:/twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i,params:{autoplay:0},type:"iframe",url:"//www.twitvid.com/embed.php?guid=$1"},twitpic:{matcher:/twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i,type:"image",url:"//twitpic.com/show/full/$1/"},instagram:{matcher:/(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,type:"image",url:"//$1/p/$2/media/?size=l"},google_maps:{matcher:/maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i,type:"iframe",url:function(t){return"//maps.google."+t[1]+"/"+t[3]+t[4]+"&output="+(t[4].indexOf("layer=c")>0?"svembed":"embed")}}},beforeLoad:function(t,i){var n=i.href||"",o=!1,r,s,a,h;for(r in t)if(t.hasOwnProperty(r)&&(s=t[r],a=n.match(s.matcher))){o=s.type,h=$.extend(!0,{},s.params,i[r]||($.isPlainObject(t[r])?t[r].params:null)),n="function"===$.type(s.url)?s.url.call(this,a,h,i):e(s.url,a,h);break}o&&(i.href=n,i.type=o,i.autoHeight=!1)}}}(jQuery),function($){var t=$.envirabox;t.helpers.thumbs={defaults:{width:50,height:50,position:"bottom",inline:!1,source:function(t){var e;return t.element&&(e=$(t.element).find("img").attr("src")),!e&&"image"===t.type&&t.href&&(e=t.href),e}},wrap:null,list:null,width:0,init:function(t,e){var i=this,n,o=t.width,r=t.height,s=t.source;n="";for(var a=0;a<e.group.length;a++)n+='<li><a style="width:'+o+"px;height:"+r+'px;" href="javascript:jQuery.envirabox.jumpto('+a+');"></a></li>';this.wrap=$('<div id="envirabox-thumbs"></div>').addClass(t.position).appendTo("body"),this.list=$("<ul>"+n+"</ul>").appendTo(this.wrap),$.each(e.group,function(t){var n=e.group[t],a=s(n);a&&$("<img />").load(function(){var e=this.width,n=this.height,s,a,h;i.list&&e&&n&&(s=e/o,a=n/r,h=i.list.children().eq(t).find("a"),s>=1&&a>=1&&(s>a?(e=Math.floor(e/a),n=r):(e=o,n=Math.floor(n/s))),$(this).css({width:e,height:n,top:Math.floor(r/2-n/2),left:Math.floor(o/2-e/2)}),h.width(o).height(r),$(this).hide().appendTo(h).fadeIn(300))}).attr("src",a).attr("title",n.title)});var h=this.list.children().eq(0),l=$("a",$(h));this.width=parseInt(l.css("border-left-width"))+parseInt(l.css("border-left-width"))+parseInt(h.css("margin-left"))+parseInt(h.css("margin-right"))+parseInt(h.css("width")),this.list.width(this.width*e.group.length).css("left",Math.floor(.5*$(window).width()-(e.index*this.width+.5*this.width)))},beforeLoad:function(t,e){return e.group.length<2?void(e.helpers.thumbs=!1):void(e.margin["top"===t.position?0:2]+=t.height+15)},afterShow:function(t,e){this.list?this.onUpdate(t,e):this.init(t,e),t.inline&&this.wrap.addClass("inline"),this.list.children().removeClass("active").eq(e.index).addClass("active")},onUpdate:function(t,e){this.list&&this.list.stop(!0).animate({left:Math.floor(.5*$(window).width()-(e.index*this.width+.5*this.width))},150)},beforeClose:function(){this.wrap&&this.wrap.remove(),this.wrap=null,this.list=null,this.width=0}}}(jQuery),function($){"use strict";var t=$.envirabox,e=function(t,e,i){return i=i||"","object"===$.type(i)&&(i=$.param(i,!0)),t};t.helpers.video={defaults:{autoplay:0,playpause:0,progress:0,current:0,duration:0,volume:0},beforeLoad:function(t,e){var i=/\.(mp4|flv|ogv|webm|MP4|FLV|OGV|WEBM)$/i.test(e.href);if(i){var n="";switch(e.href.split(".").pop()){case"mp4":n="video/mp4";break;case"ogv":n="video/ogg";break;case"ogg":n="application/ogg";break;case"webm":n="video/webm"}var o=$('a[href="'+e.href+'"]').attr("data-video-width"),r=$('a[href="'+e.href+'"]').attr("data-video-height");e.content='<div class="envira-video-container" style="max-width:'+o+"px;max-height:"+r+'px;"><video class="envira-video" width="'+o+'" height="'+r+'" preload="metadata" style="width:'+o+"px;height:"+o+'px;"><source type="'+n+'" src="'+e.href+'" /></video></div>',e.type="html";var s=[];1===t.playpause&&s.push("playpause"),1===t.progress&&s.push("progress"),1===t.current&&s.push("current"),1===t.duration&&s.push("duration"),1===t.volume&&s.push("volume")}},afterShow:function(t,e){var i=/\.(mp4|flv|ogv|webm|MP4|FLV|OGV|WEBM)$/i.test(e.href);if(i){var n=[];1===t.playpause&&n.push("playpause"),1===t.progress&&n.push("progress"),1===t.current&&n.push("current"),1===t.duration&&n.push("duration"),1===t.volume&&n.push("volume");var o=$(".envira-video").mediaelementplayer({features:n,videoWidth:"100%",videoHeight:"100%",enableAutosize:!0,success:function(e,i){1===t.autoplay&&e.addEventListener("canplay",function(){e.play()},!1)}});setTimeout(function(){$(window).trigger("resize")},500)}}}}(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/min/media-insert-third-party-min.js CHANGED
@@ -1 +1 @@
1
- wp.media.view.EnviraGalleryError=wp.Backbone.View.extend({tagName:"div",className:"notice error envira-gallery-error",render:function(){return this.template=wp.media.template("envira-gallery-error"),this.$el.html(this.template(this.model)),this}}),wp.media.view.EnviraGalleryItem=wp.Backbone.View.extend({tagName:"li",className:"attachment envira-gallery-item",render:function(){return this.template=wp.media.template("envira-gallery-item"),this.$el.html(this.template(this.model.toJSON())),this}}),wp.media.view.Toolbar.EnviraGalleryToolbar=wp.media.view.Toolbar.extend({initialize:function(){_.defaults(this.options,{event:"envira_gallery_insert",close:!1,items:{envira_gallery_insert:{id:"envira-gallery-insert-button",style:"primary",text:wp.media.view.l10n.insertIntoPost,priority:80,requires:!1,click:function(){this.controller.state().insert()}}}}),wp.media.view.Toolbar.prototype.initialize.apply(this,arguments)},refresh:function(){var e=this.controller.state().props;this.get("envira_gallery_insert").model.set("disabled",!e.length),wp.media.view.Toolbar.prototype.refresh.apply(this,arguments)}}),wp.media.view.EnviraGalleryView=wp.media.View.extend({className:"attachments-browser envira-gallery",path:"/",is_loading:!1,events:{"click .envira-gallery-item":"click",keyup:"search",search:"search"},get_action:"",search_action:"",initialize:function(e){this.collection=new Backbone.Collection,this.$el.prepend(wp.media.template("envira-gallery-search-bar")),this.$el.prepend(wp.media.template(e.sidebar_template)),this.$el.prepend(wp.media.template("envira-gallery-items")),this.on("loading",this.loading,this),this.on("loaded",this.loaded,this),this.get_action=e.get_action,this.search_action=e.search_action,this.path=e.path,this.getItems(!1,"")},click:function(e){var t=jQuery(e.currentTarget),i=jQuery("div.attachment-preview",t).attr("data-is-dir"),a=jQuery("div.attachment-preview",t).attr("data-id");"true"==i?(this.path=a,this.getItems()):t.hasClass("selected")?this.removeFromSelection(t,a):this.addToSelection(t,a)},search:function(e){if(!this.is_loading){var t=e.target.value;return 0==t.length?void this.getItems(!1,""):void(t.length<3||this.getItems(!0,t))}},loading:function(){this.is_loading=!0,this.$el.find(".spinner").addClass("is-active")},loaded:function(e){this.is_loading=!1,this.$el.find(".spinner").removeClass("is-active"),this.$el.find("div.envira-gallery-error").remove(),"undefined"!=typeof e&&this.$el.find("div.media-toolbar").after(this.renderError(e)),this.controller.toolbar.get().refresh()},clearItems:function(){this.$el.find("ul.envira-gallery-attachments li.attachment.selected").removeClass("selected details"),this.$el.find("ul.envira-gallery-attachments").empty()},getItems:function(e,t){if(!this.is_loading){this.trigger("loading"),this.clearItems();var i=e?this.search_action:this.get_action,a={nonce:envira_gallery_media_insert.nonce,path:this.path};e&&(a.search=t),wp.media.ajax(i,{context:this,data:a,success:function(e){var t=new Backbone.Collection(e);this.collection.add(t.models),this.collection.each(function(e){this.$el.find("ul.envira-gallery-attachments").append(this.renderItem(e))},this),this.trigger("loaded")},error:function(e){this.trigger("loaded",e)}})}},renderItem:function(e){var t=new wp.media.view.EnviraGalleryItem({model:e});return t.render().el},renderError:function(e){var t={};t.error=e;var i=new wp.media.view.EnviraGalleryError({model:t});return i.render().el},addToSelection:function(e,t){this.trigger("loading"),this.collection.each(function(e){e.get("id")==t&&this.getSelection().add(e)},this),e.addClass("selected details"),this.trigger("loaded")},removeFromSelection:function(e,t){this.trigger("loading"),this.getSelection().each(function(e){this.getSelection().remove([{cid:e.cid}])},this),e.removeClass("selected details"),this.trigger("loaded")},getSelection:function(){return this.controller.state().props},clearSelection:function(){this.selection=this.getSelection(),this.selection.each(function(e){this.$el.find('div[data-id="'+e.get("id")+'"]').parent().removeClass("selected details")},this),this.selection.reset()}}),wp.media.controller.EnviraGalleryController=wp.media.controller.State.extend({insert_action:"",initialize:function(e){this.props=new Backbone.Collection,this.insert_action=e.insert_action},insert:function(){var e=this.frame.content.get(),t=[];this.button=this.frame.toolbar.get().get("envira_gallery_insert"),this.button.model.set("text",wp.media.view.l10n.inserting),this.button.model.set("disabled",!0),this.trigger("loading"),e.getSelection().each(function(e){t.push(e.get("id"))},this),wp.media.ajax(this.insert_action,{context:this,data:{nonce:envira_gallery_media_insert.nonce,post_id:envira_gallery_media_insert.post_id,images:t},success:function(t){jQuery("ul#envira-gallery-output").html(t),this.trigger("loaded"),this.button.model.set("text",wp.media.view.l10n.insertIntoPost),this.button.model.set("disabled",!1),e.clearSelection(),this.frame.close()},error:function(t){this.button.model.set("text",wp.media.view.l10n.insertIntoPost),this.button.model.set("disabled",!1),e.trigger("loaded",t)}})}});var EnviraGalleryPostFrame=wp.media.view.MediaFrame.Post;wp.media.view.MediaFrame.Post=EnviraGalleryPostFrame.extend({initialize:function(){EnviraGalleryPostFrame.prototype.initialize.apply(this,arguments),_.each(envira_gallery_media_insert.addons,function(e,t){this.states.add([new wp.media.controller.EnviraGalleryController({id:t,content:t+"-content",toolbar:t+"-toolbar",menu:"default",title:wp.media.view.l10n[t],priority:200,type:"link",insert_action:e+"_insert_images"})]),this.on("content:render:"+t+"-content",_.bind(this.renderContent,this,t,e)),this.on("toolbar:create:"+t+"-toolbar",this.renderToolbar,this)},this)},renderContent:function(e,t){this.content.set(new wp.media.view.EnviraGalleryView({controller:this,model:this.state().props,addon:e,sidebar_template:e+"-side-bar",get_action:t+"_get_files_folders",search_action:t+"_search_files_folders",insert_action:t+"_insert_images",path:"/"}))},renderToolbar:function(e){e.view=new wp.media.view.Toolbar.EnviraGalleryToolbar({controller:this})}});
1
+ wp.media.view.EnviraGalleryError=wp.Backbone.View.extend({tagName:"div",className:"notice error envira-gallery-error",render:function(){return this.template=wp.media.template("envira-gallery-error"),this.$el.html(this.template(this.model)),this}}),wp.media.view.EnviraGalleryItem=wp.Backbone.View.extend({tagName:"li",className:"attachment envira-gallery-item",render:function(){return this.template=wp.media.template("envira-gallery-item"),this.$el.html(this.template(this.model.toJSON())),this}}),wp.media.view.Toolbar.EnviraGalleryToolbar=wp.media.view.Toolbar.extend({initialize:function(){_.defaults(this.options,{event:"envira_gallery_insert",close:!1,items:{envira_gallery_insert:{id:"envira-gallery-insert-button",style:"primary",text:wp.media.view.l10n.insertIntoPost,priority:80,requires:!1,click:function(){this.controller.state().insert()}}}}),wp.media.view.Toolbar.prototype.initialize.apply(this,arguments)},refresh:function(){var e=this.controller.state().props;this.get("envira_gallery_insert").model.set("disabled",!e.length),wp.media.view.Toolbar.prototype.refresh.apply(this,arguments)}}),wp.media.view.EnviraGalleryView=wp.media.View.extend({className:"attachments-browser envira-gallery",path:"/",is_loading:!1,events:{"click .envira-gallery-item":"click",keyup:"search",search:"search"},get_action:"",search_action:"",initialize:function(e){this.collection=new Backbone.Collection,this.$el.prepend(wp.media.template("envira-gallery-search-bar")),this.$el.prepend(wp.media.template(e.sidebar_template)),this.$el.prepend(wp.media.template("envira-gallery-items")),this.on("loading",this.loading,this),this.on("loaded",this.loaded,this),this.get_action=e.get_action,this.search_action=e.search_action,this.path=e.path,this.getItems(!1,"")},click:function(e){var t=jQuery(e.currentTarget),i=jQuery("div.attachment-preview",t).attr("data-is-dir"),a=jQuery("div.attachment-preview",t).attr("data-id");"true"==i?(this.path=a,this.getItems(!1,"")):t.hasClass("selected")?this.removeFromSelection(t,a):this.addToSelection(t,a)},search:function(e){if(!this.is_loading){var t=e.target.value;return 0==t.length?void this.getItems(!1,""):void(t.length<3||this.getItems(!0,t))}},loading:function(){this.is_loading=!0,this.$el.find(".spinner").addClass("is-active")},loaded:function(e){this.is_loading=!1,this.$el.find(".spinner").removeClass("is-active"),this.$el.find("div.envira-gallery-error").remove(),"undefined"!=typeof e&&this.$el.find("div.media-toolbar").after(this.renderError(e)),this.controller.toolbar.get().refresh()},clearItems:function(){this.$el.find("ul.envira-gallery-attachments li.attachment.selected").removeClass("selected details"),this.$el.find("ul.envira-gallery-attachments").empty()},getItems:function(e,t){if(!this.is_loading){this.trigger("loading"),this.clearItems();var i=e?this.search_action:this.get_action,a={nonce:envira_gallery_media_insert.nonce,path:this.path};e&&(a.search=t),wp.media.ajax(i,{context:this,data:a,success:function(e){var t=new Backbone.Collection(e);this.collection.reset(),this.collection.add(t.models),this.collection.each(function(e){this.$el.find("ul.envira-gallery-attachments").append(this.renderItem(e))},this),this.trigger("loaded")},error:function(e){this.trigger("loaded",e)}})}},renderItem:function(e){var t=new wp.media.view.EnviraGalleryItem({model:e});return t.render().el},renderError:function(e){var t={};t.error=e;var i=new wp.media.view.EnviraGalleryError({model:t});return i.render().el},addToSelection:function(e,t){this.trigger("loading"),this.collection.each(function(e){e.get("id")==t&&this.getSelection().add(e)},this),e.addClass("selected details"),this.trigger("loaded")},removeFromSelection:function(e,t){this.trigger("loading"),this.getSelection().each(function(e){this.getSelection().remove([{cid:e.cid}])},this),e.removeClass("selected details"),this.trigger("loaded")},getSelection:function(){return this.controller.state().props},clearSelection:function(){this.selection=this.getSelection(),this.selection.each(function(e){this.$el.find('div[data-id="'+e.get("id")+'"]').parent().removeClass("selected details")},this),this.selection.reset()}}),wp.media.controller.EnviraGalleryController=wp.media.controller.State.extend({insert_action:"",initialize:function(e){this.props=new Backbone.Collection,this.insert_action=e.insert_action},insert:function(){var e=this.frame.content.get(),t=[];this.button=this.frame.toolbar.get().get("envira_gallery_insert"),this.button.model.set("text",wp.media.view.l10n.inserting),this.button.model.set("disabled",!0),this.trigger("loading"),e.getSelection().each(function(e){t.push(e.get("id"))},this),wp.media.ajax(this.insert_action,{context:this,data:{nonce:envira_gallery_media_insert.nonce,post_id:envira_gallery_media_insert.post_id,images:t},success:function(t){jQuery("ul#envira-gallery-output").html(t),this.trigger("loaded"),this.button.model.set("text",wp.media.view.l10n.insertIntoPost),this.button.model.set("disabled",!1),e.clearSelection(),this.frame.close()},error:function(t){this.button.model.set("text",wp.media.view.l10n.insertIntoPost),this.button.model.set("disabled",!1),e.trigger("loaded",t)}})}});var EnviraGalleryPostFrame=wp.media.view.MediaFrame.Post;wp.media.view.MediaFrame.Post=EnviraGalleryPostFrame.extend({initialize:function(){EnviraGalleryPostFrame.prototype.initialize.apply(this,arguments),_.each(envira_gallery_media_insert.addons,function(e,t){this.states.add([new wp.media.controller.EnviraGalleryController({id:t,content:t+"-content",toolbar:t+"-toolbar",menu:"default",title:wp.media.view.l10n[t],priority:200,type:"link",insert_action:e+"_insert_images"})]),this.on("content:render:"+t+"-content",_.bind(this.renderContent,this,t,e)),this.on("toolbar:create:"+t+"-toolbar",this.renderToolbar,this)},this)},renderContent:function(e,t){this.content.set(new wp.media.view.EnviraGalleryView({controller:this,model:this.state().props,addon:e,sidebar_template:e+"-side-bar",get_action:t+"_get_files_folders",search_action:t+"_search_files_folders",insert_action:t+"_insert_images",path:"/"}))},renderToolbar:function(e){e.view=new wp.media.view.Toolbar.EnviraGalleryToolbar({controller:this})}});
envira-gallery-lite.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: Envira Gallery is best responsive WordPress gallery plugin. This is the lite version.
6
  * Author: Thomas Griffin
7
  * Author URI: http://enviragallery.com
8
- * Version: 1.5.1
9
  * Text Domain: envira-gallery
10
  *
11
  * Envira Gallery is free software: you can redistribute it and/or modify
@@ -53,7 +53,7 @@ class Envira_Gallery_Lite {
53
  *
54
  * @var string
55
  */
56
- public $version = '1.5.1';
57
 
58
  /**
59
  * The name of the plugin.
5
  * Description: Envira Gallery is best responsive WordPress gallery plugin. This is the lite version.
6
  * Author: Thomas Griffin
7
  * Author URI: http://enviragallery.com
8
+ * Version: 1.5.2
9
  * Text Domain: envira-gallery
10
  *
11
  * Envira Gallery is free software: you can redistribute it and/or modify
53
  *
54
  * @var string
55
  */
56
+ public $version = '1.5.2';
57
 
58
  /**
59
  * The name of the plugin.
includes/global/shortcode.php CHANGED
@@ -203,7 +203,18 @@ class Envira_Gallery_Shortcode {
203
  $opacity_insert = ' style="opacity: 0.0" ';
204
  }
205
 
206
- $gallery .= '<div' . $opacity_insert . ' id="envira-gallery-' . sanitize_html_class( $data['id'] ) . '" class="envira-gallery-public envira-gallery-' . sanitize_html_class( $this->get_config( 'columns', $data ) ) . '-columns envira-clear' . ( $this->get_config( 'isotope', $data ) ? ' enviratope' : '' ) . ( $this->get_config( 'css_animations', $data ) ? ' envira-gallery-css-animations' : '' ) . '" data-envira-columns="' . $this->get_config( 'columns', $data ) . '">';
 
 
 
 
 
 
 
 
 
 
 
207
 
208
  // Start image loop
209
  foreach ( $data['gallery'] as $id => $item ) {
@@ -297,22 +308,37 @@ class Envira_Gallery_Shortcode {
297
  $output = apply_filters( 'envira_gallery_output_before_link', $output, $id, $item, $data, $i );
298
 
299
  // Top Left box
300
- $output .= '<div class="envira-gallery-position-overlay envira-gallery-top-left">';
 
 
 
 
301
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'top-left' );
302
  $output .= '</div>';
303
 
304
  // Top Right box
305
- $output .= '<div class="envira-gallery-position-overlay envira-gallery-top-right">';
 
 
 
 
306
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'top-right' );
307
  $output .= '</div>';
308
 
309
  // Bottom Left box
310
- $output .= '<div class="envira-gallery-position-overlay envira-gallery-bottom-left">';
 
 
 
 
311
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'bottom-left' );
312
  $output .= '</div>';
313
 
314
  // Bottom Right box
315
- $output .= '<div class="envira-gallery-position-overlay envira-gallery-bottom-right">';
 
 
 
316
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'bottom-right' );
317
  $output .= '</div>';
318
 
@@ -625,6 +651,7 @@ class Envira_Gallery_Shortcode {
625
  <?php ob_start(); ?>
626
 
627
  var envira_galleries = [],
 
628
  envira_isotopes = [],
629
  envira_isotopes_config = [];
630
 
@@ -652,10 +679,13 @@ class Envira_Gallery_Shortcode {
652
  // if the user has selected a custom theme, only output the needed JS
653
  $gallery_theme = $this->get_config( 'justified_gallery_theme', $data );
654
 
 
 
 
655
  ?>
656
 
657
  $('#envira-gallery-<?php echo $data["id"]; ?>').enviraJustifiedGallery({
658
- rowHeight : <?php echo $this->get_config( 'justified_row_height', $data ); ?>,
659
  maxRowHeight: -1,
660
  selector: '> div > div',
661
  lastRow: 'nojustify'
@@ -1079,7 +1109,7 @@ class Envira_Gallery_Shortcode {
1079
  // Use images from $lightbox_images
1080
  add_filter( 'envira_minify_strip_double_forward_slashes', '__return_false' );
1081
  ?>
1082
- var envira_gallery_images_<?php echo $data['id']; ?> = [];
1083
  <?php
1084
  // Build a JS array of all images
1085
  $count = 0;
@@ -1089,7 +1119,7 @@ class Envira_Gallery_Shortcode {
1089
  continue;
1090
  }
1091
  ?>
1092
- envira_gallery_images_<?php echo $data['id']; ?>.push({
1093
  href: '<?php echo $image['src']; ?>',
1094
  gallery_id: <?php echo $data['id']; ?>,
1095
  id: <?php echo $image_id; ?>,
@@ -1106,9 +1136,10 @@ class Envira_Gallery_Shortcode {
1106
 
1107
  // Open envirabox when an image is clicked, telling envirabox which images are available to it.
1108
  ?>
1109
- envira_galleries['<?php echo $data['id']; ?>'] = $('.envira-gallery-<?php echo $data['id']; ?>').envirabox( envira_gallery_options );
1110
  $('#envira-gallery-wrap-<?php echo $data['id']; ?>').on('click', 'a.envira-gallery-link', function(e) {
1111
  e.preventDefault();
 
1112
  $.envirabox.close();
1113
  if ( $('#envira-gallery-wrap-<?php echo $data['id']; ?> div.envira-pagination').length > 0 ) { /* this exists, perhaps pagination doesn't display nav because it's only one page? */
1114
  var envirabox_page = ( $('#envira-gallery-wrap-<?php echo $data['id']; ?> div.envira-pagination').data('page') - 1 );
@@ -1124,7 +1155,7 @@ class Envira_Gallery_Shortcode {
1124
 
1125
  var envirabox_index = ( Number($('img', $(this)).data('envira-index')) - 1 );
1126
  envira_gallery_options.index = ((envirabox_page * envirabox_per_page) + envirabox_index);
1127
- envira_galleries['<?php echo $data['id']; ?>'] = $.envirabox( envira_gallery_images_<?php echo $data['id']; ?>, envira_gallery_options );
1128
  });
1129
  <?php
1130
  }
@@ -1534,7 +1565,11 @@ class Envira_Gallery_Shortcode {
1534
  public function get_lightbox_template( $data ) {
1535
 
1536
  // Build out the lightbox template
1537
- $template = '<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin envirabox-theme-' . $this->get_config( 'lightbox_theme', $data ) . '"><div class="envirabox-outer"><div class="envirabox-inner">';
 
 
 
 
1538
 
1539
  // Top Left box
1540
  $template .= '<div class="envirabox-position-overlay envira-gallery-top-left">';
203
  $opacity_insert = ' style="opacity: 0.0" ';
204
  }
205
 
206
+ // add justified CSS?
207
+ $extra_css = 'envira-gallery-justified-public';
208
+ $row_height = false;
209
+ $justified_gallery_theme = false;
210
+ if ( $this->get_config( 'columns', $data ) > 0 ) {
211
+ $extra_css = false;
212
+ } else {
213
+ $row_height = $this->get_config( 'justified_row_height', $data );
214
+ $justified_gallery_theme = $this->get_config( 'justified_gallery_theme', $data );
215
+ }
216
+
217
+ $gallery .= '<div' . $opacity_insert . ' data-row-height="'.$row_height.'" data-gallery-theme="'.$justified_gallery_theme.'" id="envira-gallery-' . sanitize_html_class( $data['id'] ) . '" class="envira-gallery-public '.$extra_css.' envira-gallery-' . sanitize_html_class( $this->get_config( 'columns', $data ) ) . '-columns envira-clear' . ( $this->get_config( 'isotope', $data ) ? ' enviratope' : '' ) . ( $this->get_config( 'css_animations', $data ) ? ' envira-gallery-css-animations' : '' ) . '" data-envira-columns="' . $this->get_config( 'columns', $data ) . '">';
218
 
219
  // Start image loop
220
  foreach ( $data['gallery'] as $id => $item ) {
308
  $output = apply_filters( 'envira_gallery_output_before_link', $output, $id, $item, $data, $i );
309
 
310
  // Top Left box
311
+
312
+ $css_class = false; // no css classes yet
313
+ $css_class = apply_filters( 'envira_gallery_output_dynamic_position_css', $css_class, $output, $id, $item, $data, $i, 'top-left' );
314
+
315
+ $output .= '<div class="envira-gallery-position-overlay ' . $css_class . ' envira-gallery-top-left">';
316
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'top-left' );
317
  $output .= '</div>';
318
 
319
  // Top Right box
320
+
321
+ $css_class = false; // no css classes yet
322
+ $css_class = apply_filters( 'envira_gallery_output_dynamic_position_css', $css_class, $output, $id, $item, $data, $i, 'top-right' );
323
+
324
+ $output .= '<div class="envira-gallery-position-overlay ' . $css_class . ' envira-gallery-top-right">';
325
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'top-right' );
326
  $output .= '</div>';
327
 
328
  // Bottom Left box
329
+
330
+ $css_class = false; // no css classes yet
331
+ $css_class = apply_filters( 'envira_gallery_output_dynamic_position_css', $css_class, $output, $id, $item, $data, $i, 'bottom-left' );
332
+
333
+ $output .= '<div class="envira-gallery-position-overlay ' . $css_class . ' envira-gallery-bottom-left">';
334
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'bottom-left' );
335
  $output .= '</div>';
336
 
337
  // Bottom Right box
338
+ $css_class = false; // no css classes yet
339
+ $css_class = apply_filters( 'envira_gallery_output_dynamic_position_css', $css_class, $output, $id, $item, $data, $i, 'bottom-right' );
340
+
341
+ $output .= '<div class="envira-gallery-position-overlay ' . $css_class . ' envira-gallery-bottom-right">';
342
  $output = apply_filters( 'envira_gallery_output_dynamic_position', $output, $id, $item, $data, $i, 'bottom-right' );
343
  $output .= '</div>';
344
 
651
  <?php ob_start(); ?>
652
 
653
  var envira_galleries = [],
654
+ envira_gallery_images = [],
655
  envira_isotopes = [],
656
  envira_isotopes_config = [];
657
 
679
  // if the user has selected a custom theme, only output the needed JS
680
  $gallery_theme = $this->get_config( 'justified_gallery_theme', $data );
681
 
682
+ // in some cases, previous gallery using the old automattic layout aren't showing a row height, so just in case...
683
+ $justified_row_height = $this->get_config( 'justified_row_height', $data ) ? $this->get_config( 'justified_row_height', $data ) : 150;
684
+
685
  ?>
686
 
687
  $('#envira-gallery-<?php echo $data["id"]; ?>').enviraJustifiedGallery({
688
+ rowHeight : <?php echo $justified_row_height; ?>,
689
  maxRowHeight: -1,
690
  selector: '> div > div',
691
  lastRow: 'nojustify'
1109
  // Use images from $lightbox_images
1110
  add_filter( 'envira_minify_strip_double_forward_slashes', '__return_false' );
1111
  ?>
1112
+ envira_gallery_images[<?php echo $data['id']; ?>] = [];
1113
  <?php
1114
  // Build a JS array of all images
1115
  $count = 0;
1119
  continue;
1120
  }
1121
  ?>
1122
+ envira_gallery_images[<?php echo $data['id']; ?>].push({
1123
  href: '<?php echo $image['src']; ?>',
1124
  gallery_id: <?php echo $data['id']; ?>,
1125
  id: <?php echo $image_id; ?>,
1136
 
1137
  // Open envirabox when an image is clicked, telling envirabox which images are available to it.
1138
  ?>
1139
+ envira_galleries['<?php echo $data['id']; ?>'] = $('.envira-gallery-<?php echo $data['id']; ?>').envirabox( envira_gallery_options, envira_gallery_images[<?php echo $data['id']; ?>] );
1140
  $('#envira-gallery-wrap-<?php echo $data['id']; ?>').on('click', 'a.envira-gallery-link', function(e) {
1141
  e.preventDefault();
1142
+ e.stopPropagation();
1143
  $.envirabox.close();
1144
  if ( $('#envira-gallery-wrap-<?php echo $data['id']; ?> div.envira-pagination').length > 0 ) { /* this exists, perhaps pagination doesn't display nav because it's only one page? */
1145
  var envirabox_page = ( $('#envira-gallery-wrap-<?php echo $data['id']; ?> div.envira-pagination').data('page') - 1 );
1155
 
1156
  var envirabox_index = ( Number($('img', $(this)).data('envira-index')) - 1 );
1157
  envira_gallery_options.index = ((envirabox_page * envirabox_per_page) + envirabox_index);
1158
+ envira_galleries['<?php echo $data['id']; ?>'] = $.envirabox( envira_gallery_images[<?php echo $data['id']; ?>], envira_gallery_options );
1159
  });
1160
  <?php
1161
  }
1565
  public function get_lightbox_template( $data ) {
1566
 
1567
  // Build out the lightbox template
1568
+ $envirabox_wrap_css_classes = apply_filters( 'envirabox_wrap_css_classes', 'envirabox-wrap', $data );
1569
+
1570
+ $envirabox_theme = apply_filters( 'envirabox_theme', 'envirabox-theme-' . $this->get_config( 'lightbox_theme', $data ), $data );
1571
+
1572
+ $template = '<div class="' . $envirabox_wrap_css_classes . '" tabIndex="-1"><div class="envirabox-skin ' . $envirabox_theme . '"><div class="envirabox-outer"><div class="envirabox-inner">';
1573
 
1574
  // Top Left box
1575
  $template .= '<div class="envirabox-position-overlay envira-gallery-top-left">';
languages/envira-gallery.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the Envira Gallery Lite package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Envira Gallery Lite 1.5.1\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/envira-gallery\n"
7
- "POT-Creation-Date: 2016-08-26 15:47:26+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -1467,19 +1467,19 @@ msgstr ""
1467
  msgid "No Envira galleries found in trash."
1468
  msgstr ""
1469
 
1470
- #: includes/global/shortcode.php:868
1471
  msgid "The requested content cannot be loaded.<br/>Please try again later.</p>"
1472
  msgstr ""
1473
 
1474
- #: includes/global/shortcode.php:869 includes/global/shortcode.php:1514
1475
  msgid "Close"
1476
  msgstr ""
1477
 
1478
- #: includes/global/shortcode.php:870 includes/global/shortcode.php:1504
1479
  msgid "Next"
1480
  msgstr ""
1481
 
1482
- #: includes/global/shortcode.php:871 includes/global/shortcode.php:1500
1483
  msgid "Previous"
1484
  msgstr ""
1485
 
2
  # This file is distributed under the same license as the Envira Gallery Lite package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Envira Gallery Lite 1.5.2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/envira-gallery\n"
7
+ "POT-Creation-Date: 2016-09-02 13:54:36+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
1467
  msgid "No Envira galleries found in trash."
1468
  msgstr ""
1469
 
1470
+ #: includes/global/shortcode.php:898
1471
  msgid "The requested content cannot be loaded.<br/>Please try again later.</p>"
1472
  msgstr ""
1473
 
1474
+ #: includes/global/shortcode.php:899 includes/global/shortcode.php:1545
1475
  msgid "Close"
1476
  msgstr ""
1477
 
1478
+ #: includes/global/shortcode.php:900 includes/global/shortcode.php:1535
1479
  msgid "Next"
1480
  msgstr ""
1481
 
1482
+ #: includes/global/shortcode.php:901 includes/global/shortcode.php:1531
1483
  msgid "Previous"
1484
  msgstr ""
1485
 
readme.txt CHANGED
@@ -185,11 +185,14 @@ Also, I'm an <a href="https://thomasgriffin.io" rel="me" title="WordPress Develo
185
 
186
  == Changelog ==
187
 
 
 
 
188
  = 1.5.1 =
189
- * Added: A justified layout replaces the old "automatic" layout setting for galleries. See documentation on enviragallery.com for additional information.</li>
190
- * Updated: Spanish translation.</li>
191
- * Fix: Removing "Insert From Url" option for galleries.</li>
192
- * Fix: Gallery display follows settings properly when WPML is used in certain cirucmstances.</li>
193
 
194
  = 1.5.0.8 =
195
  * Fix: Fix: Close button in lightbox admin bar should not jump position with longer gallery titles.
185
 
186
  == Changelog ==
187
 
188
+ = 1.5.2 =
189
+ * Fix: Justified layout setting of 150 pixels for row height applies to galleries that were using the older automattic layout.
190
+
191
  = 1.5.1 =
192
+ * Added: A justified layout replaces the old "automatic" layout setting for galleries. See documentation on enviragallery.com for additional information.
193
+ * Updated: Spanish translation.
194
+ * Fix: Removing "Insert From Url" option for galleries.
195
+ * Fix: Gallery display follows settings properly when WPML is used in certain cirucmstances.
196
 
197
  = 1.5.0.8 =
198
  * Fix: Fix: Close button in lightbox admin bar should not jump position with longer gallery titles.