1/* 2 * components.image-viewer.js 3 * 4 * Provides an interface for users to click through a series of images. 5 * 6 * === Changelog ============================================================== 7 * 8 * Version Date Notes 9 * 10 * 1.0.2 2016-08-26 Removed a dependency on the obsolete ModalTrigger component. 11 * 12 * 1.0.1 2015-08-10 Added YouTube video functionality. 13 * 14 * 1.0.0 2015-07-22 Initial version. 15 * 16 */ 17(function (WOW, $, undefined) { 18 'use strict'; 19 WOW.Modules.register({ 20 name: 'Components.ImageViewer', 21 version: '1.0.2', 22 dependencies: [ 23 'Components', 24 'Components.ZoomPanel', 25 'Components.Modal 3.1.0' 26 ] 27 }, function () { 28 29 var $empty = $(), 30 ImageViewer; 31 32 ImageViewer = WOW.Components.create(function ImageViewer() { 33 /// <field name="display" type="jQuery" /> 34 /// <field name="list" type="jQuery" /> 35 /// <field name="itemElements" type="jQuery" /> 36 /// <field name="items" type="Array" elementType="ImageViewerItem" /> 37 /// <field name="activeItem" type="ImageViewerItem" /> 38 /// <field name="enabled" type="Boolean" /> 39 /// <field name="zoomElement" type="jQuery" /> 40 /// <field name="zoomPanel" type="WOW.Components.ZoomPanel" /> 41 /// <field name="modalTrigger" type="WOW.Components.Modal.ModalTrigger" /> 42 /// <field name="videoContainer" type="jQuery" /> 43 /// <field name="videoIframe" type="HTMLIFrameElement" /> 44 45 this.display = $empty; 46 this.list = $empty; 47 this.itemElements = $empty; 48 this.activeItem = null; 49 this.enabled = false; 50 this.zoomElement = $empty; 51 this.zoomPanel = null; 52 this.modalTrigger = null; 53 this.videoContainer = $empty; 54 this.videoIframe = null; 55 }); 56 57 ImageViewer.prototype.initialize = function () { 58 var $this = this, 59 children = this.element.children(), 60 display = children.filter(".imageViewer__display").first(), 61 i = 0, 62 activeItem; 63 this.display = display.length ? display : $(document.createElement("div")).addClass("imageViewer__display").prependTo(this.element); 64 this.list = children.filter(".imageViewer__list").first(); 65 this.itemElements = this.list.find(".imageViewer__item"); 66 this.zoomElement = this.display.filter(".zoomPanel"); 67 this.items = []; 68 if (this.itemElements.length) { 69 this.itemElements.each(function (i, item) { 70 $this.items[i] = new ImageViewerItem($(item)); 71 }); 72 activeItem = this.items.filter(function (item) { 73 /// <param name="item" type="ImageViewerItem" /> 74 return (item.type === 'image'); 75 }); 76 if (activeItem.length > 0) { 77 this.setActiveItem(activeItem[0]); 78 } 79 if (this.zoomElement.length) { 80 WOW.Components.ZoomPanel.findInstance(function (zoomPanel) { 81 $this.zoomPanel = zoomPanel; 82 $this.setActiveItem($this.activeItem); 83 }, this.element, true); 84 } 85 if (this.display.hasClass('modalTrigger') || this.display.is("[rel='_modal']")) { 86 WOW.Components.Modal.ModalTrigger.findInstance(function (modalTrigger) { 87 $this.modalTrigger = modalTrigger; 88 }, this.display, false); 89 } 90 this.items.forEach(function (item) { 91 $this.addHandlers("click", { 92 target: item.button, 93 prefix: "button",
94 extraArguments: item 95 }); 96 }); 97 this.videoIframe = document.createElement('iframe'); 98 this.videoIframe.frameBorder = 0; 99 this.videoIframe.setAttribute('allowfullscreen', ''); 100 this.videoIframe.className = 'imageViewer__videoIframe video__iframe'; 101 this.videoContainer = $(document.createElement('div')).addClass('imageViewer__video video video--youtube').append(this.videoIframe); 102 return true; 103 } 104 return false; 105 }; 106 107 ImageViewer.prototype.setActiveItem = function (item) { 108 /// <param name="item" type="ImageViewerItem" /> 109 var itemHasZoomSize, opts; 110 if (this.activeItem) { 111 if (this.activeItem.type === 'video') { 112 this.videoIframe.src = ''; 113 this.videoContainer.detach(); 114 } else { 115 this.activeItem.sizes.panel.getElement().detach(); 116 if (this.activeItem.sizes.zoom) { 117 this.activeItem.sizes.zoom.getElement().detach(); 118 } 119 } 120 this.activeItem.button.removeClass("imageViewer__item--active"); 121 this.activeItem.active = false; 122 } 123 if (item.type === 'image') { 124 this.videoContainer.detach(); 125 if (this.zoomPanel) { 126 opts = { map: item.sizes.panel.getElement() }; 127 if (itemHasZoomSize = (item.sizes.zoom ? true : false)) { 128 opts.content = item.sizes.zoom.getElement(); 129 } 130 this.zoomPanel.setContent(opts); 131 } else { 132 this.display.empty().append(item.sizes.panel.getElement()); 133 } 134 if (this.display.is("a[href]")) { 135 this.display.attr("href", item.sizes[itemHasZoomSize ? 'zoom' : 'panel'].src); 136 if (this.modalTrigger) { 137 this.modalTrigger.refresh(); 138 } 139 } 140 this.display.prependTo(this.element); 141 } else { 142 this.display.detach(); 143 this.videoContainer.prependTo(this.element); 144 this.videoIframe.src = item.embed; 145 } 146 this.activeItem = item; 147 this.activeItem.active = true; 148 this.activeItem.button.addClass("imageViewer__item--active"); 149 }; 150 151 ImageViewer.prototype.on_button_click = function (event, item) { 152 /// <param name="event" type="jQuery.Event" /> 153 /// <param name="item" type="ImageViewerItem" /> 154 event.preventDefault(); 155 if (item !== this.activeItem) { 156 this.setActiveItem(item); 157 } 158 }; 159 160 function ImageViewerItem(button) { 161 /// <param name="button" type="jQuery" /> 162 /// <field name="alt" type="String" /> 163 /// <field name="button" type="jQuery" /> 164 /// <field name="active" type="Boolean" /> 165 /// <field name="type" type="String" /> 166 /// <field name="sizes" type="Object" /> 167 /// <field name="embed" type="String" /> 168 var $this = this, 169 alt = '', 170 thumbnail, panel, zoom, thumbnailImage; 171 this.button = $(button); 172 this.active = false; 173 this.embed = ''; 174 175 if (this.button.is("img")) { 176 alt = this.button.attr("alt"); 177 thumbnailImage = this.button; 178 thumbnail = this.button.attr("src"); 179 } else if ((thumbnail = $(this.button.find("img"))).length > 0) { 180 alt = thumbnail.attr("alt"); 181 thumbnailImage = thumbnail; 182 thumbnail = thumbnail.attr("src"); 183 } 184 if (this.button.hasClass('imageViewer__item--video')) { 185 this.type = 'video'; 186 this.embed = button.attr('data-embed'); 187 } else { 188 this.type = 'image'; 189 } 190
191 if (this.type === 'image') { 192 panel = this.button.attr(this.button.is("a") ? "href" : "data-image-panel"); 193 if (!panel) { 194 panel = thumbnail; 195 } 196 197 zoom = this.button.attr("data-image-zoom"); 198 199 /// <field name="alt" type="String" /> 200 this.alt = alt || ""; 201 /// <field name="sizes" value="{ thumbnail: new ImageViewerSize(), panel: new ImageViewerSize(), zoom: new ImageViewerSize() }" /> 202 this.sizes = { 203 thumbnail: new ImageViewerSize(this, thumbnail, thumbnailImage), 204 panel: new ImageViewerSize(this, panel), 205 zoom: (zoom) ? new ImageViewerSize(this, zoom) : null 206 }; 207 } 208 } 209 210 function ImageViewerSize(item, src, element) { 211 /// <param name="item" type="ImageViewerItem" /> 212 /// <param name="src" type="String" /> 213 /// <param name="element" type="jQuery" optional="true" /> 214 /// <field name="image" type="ImageViewerImage" /> 215 this.item = item; 216 /// <field name="src" type="String" /> 217 this.src = src; 218 /// <field name="element" type="jQuery" /> 219 this.element = element || null; 220 } 221 222 ImageViewerSize.prototype.getElement = function () { 223 if (!this.element) { 224 this.element = $(document.createElement("img")).attr({ src: this.src, alt: this.item.alt }); 225 } 226 return this.element; 227 }; 228 229 return ImageViewer; 230 231 }); 232})(Whereoware, jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.