Skip to content

Instantly share code, notes, and snippets.

@webketje
Last active February 20, 2024 10:15
Show Gist options
  • Save webketje/2bda98ced2ac32e0bcb0 to your computer and use it in GitHub Desktop.
Save webketje/2bda98ced2ac32e0bcb0 to your computer and use it in GitHub Desktop.
JS Simple Image Expand

##JS Simple Image Expand

A simple Javascript plugin that shows an image in full size on click, and should be compatible up to IE6.

####Basic usage: In the <head> tag, include:

<script type="text/javascript" src="your/path/to/simple-image-zoom.min.js"></script>

Before the closing </body> tag, include:

<script type="text/javascript"> simpleImageExpand(); </script>

By default, the plugin will add functionality to all images with the class expand-enabled (but you can change this in options).

####Options: You can also specify some options:

  • zoomClass - the class of images to add zoom functionality to.
  • zoomMaxWidth - The max-width of an image when zoomed.
  • zoomMaxHeight - The max-height of an image when zoomed.
  • overlayOpacity - Opacity of the overlay (between 0-1).
  • overlayColor - Any HTML color (HEX, RGB, colorname)
  • iconImg - A link / dataURI to an icon image as 'Expand' icon
  • iconShow - Whether to add an 'Expand' icon over the image (TRUE or FALSE)
  • iconSize - (Square) Size of the icon (eg. '25px', '1em', '10%')
  • iconToggleOnly - Whether to toggle image expand only on icon click (TRUE), or on the entire picture (FALSE)
  • iconPos - Any of the CSS position properties, in an object, eg: {right: 0, bottom: 0}
  • dynamicLoad - Set this to TRUE if lazyloading images/ loading images with AJAX / on the fly
  • dynamicInterval - Rate at which plugin checks for new images to add functionality to. Default is 200ms.

Below are the default settings (so doing simpleImageExpand() is exactly the same as doing it with the options below):

<script type="text/javascript"> 
  simpleImageExpand({
    zoomClass: 'expand-enabled',
    zoomMaxWidth: 'initial',
    zoomMaxHeight: 'initial',
    overlayColor: 'black', 
    overlayOpacity: '.8',
    iconShow: true,
    iconSize: '24px',
    iconImg: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqVJREFUeNq8VjuLGlEUnhlHNz5BsnkYXdwQNWCxVoFUWlhJCotgI4LiP5AUlpZiEfwBgljZSBohpaCpUgUkIEELH1EkJCH4fo1jzpE7wZjRnXElB84uc+d6vjnnfOe7l95sNjRFUfeJX1DntQX4T3QWAUaj0XU0GnU3Go2Xk8nESNP0nRE0Gs0vu93+MZvNftDr9RQNGT0PBAKvqtXqa3jPwjN3DiCMBc65XK53hULhPYPlwkzIiyWA8PD/HL7EmCT2BQJR0+nUiOjU+Y0jsbdZ/GNQPobjOCXP88zuOsMwPDinUCjWp9QRA1O7fUGQZrP5Yn/zcDhc+/3+z71ebywVAGNvPxL/7Dd/PxO0wWDAx2Kxr+12ey4nEyE2I/UHUC6q3+8jWTanNEsykE6nY4LB4APIVkmG/O5AQrrQC65SqUyF9VAoZEylUk8BTHEykNA0ArRutVqLZDLZDYfDXyKRSEt4V6vVZrhdLhAqw43D4XiLqkEGbUtvtVqtBDlaA53XYKzX6720WCyqXC7Xh379UQ8y4McSmdbr9TfsgdLx8/l8gQTYzgDLrsrl8jeBFAgMWZq63e6yVCr9QGAsp1arVcxms5UYOCODpjw6EgHK+SSRSFxlMplnbrf70Wq1Uvt8vsfFYvEGZpA9OLBiQ3sM0+l0qoUHKOU1EOahzWZTmc1mFGXFUSCpio09i8fjzeVyySALcc3j8WjESLX78Yxs9sDAAtgqn89/H4/HvBRVOAmIfCltMplUQAp5oirXrFbrvXQ6fWUwGBiR0vKS1fs263Q6Mzg5P4kdIzgKYurNyiHCjsCupZ5Jf5EBLxKnlvG21pDYW6AF3lbIUa4ia1tHKdp9FvMjezAWR2IvUOsud69bwhkvtXeH9uxdt1r0/7pA/hZgACO4VuIsr37kAAAAAElFTkSuQmC',
    iconPos: {right: 0, bottom: 0 },
    iconToggleOnly: false,
    dynamicLoading: false,
    dynamicInterval: 200
  });
</script>

####Styling You can further style the expand-overlay, icon and image by using the following CSS rules:

#expand-overlay { ... } /* style the background overlay shown when an image is clicked */
#expand-overlay img { ... } /* style the image shown full-size */
.expand-container { ... } /* container in which images are placed after plugin initiation */
.expand-container .expand-icon { ... } /* expand-icon */
var simpleImageExpand = function(options) {
// IE8 utility function
function addEventHandler(elem,eventType,handler) {
if (elem.addEventListener)
elem.addEventListener (eventType,handler,false);
else if (elem.attachEvent)
elem.attachEvent ('on'+eventType,handler);
}
// handle options
var fullIconPos = '',
options = options || {};
options.zoomClass = options.zoomClass || 'zoom-enabled';
options.zoomMaxWidth = options.zoomMaxWidth || 'initial';
options.zoomMaxHeight = options.zoomMaxHeight || 'initial';
options.overlayOpacity = options.overlayOpacity || '.8';
options.overlayColor = options.overlayColor || 'black';
options.iconSize = options.iconSize || '24px';
options.iconShow = options.hasOwnProperty('iconShow') ? options.iconShow : true;
options.iconToggleOnly = options.iconToggleOnly || false;
options.iconPos = options.iconPos || { right: 0, bottom: 0};
for (var posProp in options.iconPos)
fullIconPos += posProp + ': ' + options.iconPos[posProp] + ';';
options.iconImg = options.iconImg || 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqVJREFUeNq8VjuLGlEUnhlHNz5BsnkYXdwQNWCxVoFUWlhJCotgI4LiP5AUlpZiEfwBgljZSBohpaCpUgUkIEELH1EkJCH4fo1jzpE7wZjRnXElB84uc+d6vjnnfOe7l95sNjRFUfeJX1DntQX4T3QWAUaj0XU0GnU3Go2Xk8nESNP0nRE0Gs0vu93+MZvNftDr9RQNGT0PBAKvqtXqa3jPwjN3DiCMBc65XK53hULhPYPlwkzIiyWA8PD/HL7EmCT2BQJR0+nUiOjU+Y0jsbdZ/GNQPobjOCXP88zuOsMwPDinUCjWp9QRA1O7fUGQZrP5Yn/zcDhc+/3+z71ebywVAGNvPxL/7Dd/PxO0wWDAx2Kxr+12ey4nEyE2I/UHUC6q3+8jWTanNEsykE6nY4LB4APIVkmG/O5AQrrQC65SqUyF9VAoZEylUk8BTHEykNA0ArRutVqLZDLZDYfDXyKRSEt4V6vVZrhdLhAqw43D4XiLqkEGbUtvtVqtBDlaA53XYKzX6720WCyqXC7Xh379UQ8y4McSmdbr9TfsgdLx8/l8gQTYzgDLrsrl8jeBFAgMWZq63e6yVCr9QGAsp1arVcxms5UYOCODpjw6EgHK+SSRSFxlMplnbrf70Wq1Uvt8vsfFYvEGZpA9OLBiQ3sM0+l0qoUHKOU1EOahzWZTmc1mFGXFUSCpio09i8fjzeVyySALcc3j8WjESLX78Yxs9sDAAtgqn89/H4/HvBRVOAmIfCltMplUQAp5oirXrFbrvXQ6fWUwGBiR0vKS1fs263Q6Mzg5P4kdIzgKYurNyiHCjsCupZ5Jf5EBLxKnlvG21pDYW6AF3lbIUa4ia1tHKdp9FvMjezAWR2IvUOsud69bwhkvtXeH9uxdt1r0/7pA/hZgACO4VuIsr37kAAAAAElFTkSuQmCC';
// DOM elements
var style = document.createElement('style'),
cnt = document.createElement('div'),
icon = document.createElement('i');
cnt.className = 'zoom-container';
icon.className = 'zoom-icon';
var css = document.createTextNode('.zoom-container { display: block !important; position: relative !important; text-decoration: none; }\n ' +
'#zoom-overlay { z-index: 990; position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; background-color:' + options.overlayColor + '; text-align: center; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=' + (options.overlayOpacity*10) + ')";' +
'filter: alpha(opacity=' + (options.overlayOpacity*10) + '); -moz-opacity: ' + options.overlayOpacity + '; -khtml-opacity: ' + options.overlayOpacity + '; opacity: ' + options.overlayOpacity + ';} \n' +
'#zoom-overlay img { top: 50%; width: initial; height: initial; position: relative; max-width:' + options.zoomMaxWidth + '; max-height: ' + options.zoomMaxHeight + '}\n' +
'.zoom-container i { display: block; position: absolute; height: ' + options.iconSize + '; width: ' + options.iconSize + '; ' + 'background-image: url(' + options.iconImg + ');' + fullIconPos + '}');
style.appendChild(css);
// overlay functions & element
var overlay = {
element: document.createElement('div'),
init: function() {
overlay.status = 0;
overlay.element.id = 'zoom-overlay';
document.body.insertBefore(overlay.element, document.body.firstChild);
addEventHandler(overlay.element, 'click', overlay.hide);
},
show: function(img) {
var img = img.cloneNode();
overlay.status = 1;
overlay.element.appendChild(img);
img.onload = function() {
img.style.marginTop = - (img.clientHeight/2) +'px';
};
overlay.element.style.display = 'block';
},
hide: function() {
overlay.status = 0;
overlay.element.innerHTML = '';
overlay.element.style.cssText = '';
}
},
// always return the container
boundElement = function(elem) {
if (elem.className === 'zoom-container' && !options.iconToggleOnly)
return elem;
else if ((elem.className === options.zoomClass && !options.iconToggleOnly) || elem.className === 'zoom-icon')
return elem.parentNode;
},
// zoom functions
zoom = {
bind: function() {
var zoomImages = document.getElementsByTagName('img');
for (var i = zoomImages.length; i--;) {
if (zoomImages[i].className === options.zoomClass && zoomImages[i].getAttribute('data-bound') !== 'true')
zoom.init(zoomImages[i]);o
}
},
init: function(e) {
var target = e.target || e.srcElement || e, container;
target.setAttribute('data-bound', 'true');
container = cnt.cloneNode();
target.parentNode.insertBefore(container, target);
container.appendChild(target);
container.style.width = target.clientWidth +'px';
container.style.height = target.clientHeight +'px';
if (options.iconShow)
container.appendChild(icon.cloneNode());
},
update: function(e) {
var target = boundElement(e.target || e.srcElement), img;
if (target) {
img = target.getElementsByTagName('img')[0];
if (!overlay.hasOwnProperty('status'))
overlay.init();
if (!overlay.status)
overlay.show(img);
else
overlay.hide();
}
}
};
// init
document.getElementsByTagName('head')[0].appendChild(style);
addEventHandler(document.body, 'click', zoom.update);
zoom.bind();
if (options.dynamicLoad) {
setInterval(function() {
if (overlay.status !== 1)
zoom.bind();
}, options.dynamicInterval || 200);
}
};
var simpleImageExpand = function(v) { function adEvt(e,t,h) { if (e.addEventListener) e.addEventListener(t,h,false); else if (e.attachEvent) e.attachEvent('on'+t,h); } var fIP = '', v = v || {}; v.zC = v.expandClass || 'expand-enabled'; v.zMw = v.expandMaxWidth || 'initial'; v.zMh = v.expandMaxHeight || 'initial'; v.oO = v.overlayOpacity || '.8'; v.oC = v.overlayColor || 'black'; v.iS = v.iconSize || '24px'; v.iSh = v.hasOwnProperty('iconShow') ? v.iconShow : true; v.iTo = v.iconToggleOnly || false; v.iP = v.iconPos || { right: '5px', bottom: '5px'}; for (var pP in v.iP) fIP += pP + ': ' + v.iP[pP] + ';'; v.iI = v.iconImg || 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqVJREFUeNq8VjuLGlEUnhlHNz5BsnkYXdwQNWCxVoFUWlhJCotgI4LiP5AUlpZiEfwBgljZSBohpaCpUgUkIEELH1EkJCH4fo1jzpE7wZjRnXElB84uc+d6vjnnfOe7l95sNjRFUfeJX1DntQX4T3QWAUaj0XU0GnU3Go2Xk8nESNP0nRE0Gs0vu93+MZvNftDr9RQNGT0PBAKvqtXqa3jPwjN3DiCMBc65XK53hULhPYPlwkzIiyWA8PD/HL7EmCT2BQJR0+nUiOjU+Y0jsbdZ/GNQPobjOCXP88zuOsMwPDinUCjWp9QRA1O7fUGQZrP5Yn/zcDhc+/3+z71ebywVAGNvPxL/7Dd/PxO0wWDAx2Kxr+12ey4nEyE2I/UHUC6q3+8jWTanNEsykE6nY4LB4APIVkmG/O5AQrrQC65SqUyF9VAoZEylUk8BTHEykNA0ArRutVqLZDLZDYfDXyKRSEt4V6vVZrhdLhAqw43D4XiLqkEGbUtvtVqtBDlaA53XYKzX6720WCyqXC7Xh379UQ8y4McSmdbr9TfsgdLx8/l8gQTYzgDLrsrl8jeBFAgMWZq63e6yVCr9QGAsp1arVcxms5UYOCODpjw6EgHK+SSRSFxlMplnbrf70Wq1Uvt8vsfFYvEGZpA9OLBiQ3sM0+l0qoUHKOU1EOahzWZTmc1mFGXFUSCpio09i8fjzeVyySALcc3j8WjESLX78Yxs9sDAAtgqn89/H4/HvBRVOAmIfCltMplUQAp5oirXrFbrvXQ6fWUwGBiR0vKS1fs263Q6Mzg5P4kdIzgKYurNyiHCjsCupZ5Jf5EBLxKnlvG21pDYW6AF3lbIUa4ia1tHKdp9FvMjezAWR2IvUOsud69bwhkvtXeH9uxdt1r0/7pA/hZgACO4VuIsr37kAAAAAElFTkSuQmCC'; var sy = document.createElement('style'), cnt = document.createElement('div'), icon = document.createElement('i'); cnt.className = 'expand-container'; icon.className = 'expand-icon'; var css = document.createTextNode('.expand-container { display: block !important; position: relative !important; text-decoration: none; }\n ' + '#expand-overlay { z-index: 990; position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; background-color:' + v.oC + '; text-align: center; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=' + (v.oO*10) + ')";' + 'filter: alpha(opacity=' + (v.oO*10) + '); -moz-opacity: ' + v.oO + '; -khtml-opacity: ' + v.oO + '; opacity: ' + v.oO + ';} \n' + '#expand-overlay img { top: 50%; width: initial; height: initial; position: relative; max-width:' + v.zMw + '; max-height: ' + v.zMh + '; }\n' + '.expand-container i { display: block; position: absolute; height: ' + v.iS + '; width: ' + v.iS + '; ' + 'background-image: url(' + v.iI + ');' + fIP + '}'); sy.appendChild(css); var o = { e: document.createElement('div'), i: function() { o.st = 0; o.e.id = 'expand-overlay'; document.body.insertBefore(o.e, document.body.firstChild); adEvt(o.e, 'click', o.h); }, s: function(i) { var i = i.cloneNode(); o.st = 1; o.e.appendChild(i); i.onload = function() { i.style.marginTop = - (i.clientHeight/2) +'px'; }; o.e.style.display = 'block'; }, h: function() { o.st = 0; o.e.innerHTML = ''; o.e.style.cssText = ''; } }, bE = function(e) { if (e.className === 'expand-container' && !v.iTo) return e; else if ((e.className === v.zC && !v.iTo) || e.className === 'expand-icon') return e.parentNode; }, z = { b: function() { var zI = document.getElementsByTagName('img'); for (var i = zI.length; i--;) { if (zI[i].className === v.zC && zI[i].getAttribute('data-bound') !== 'true') z.i(zI[i]); } }, i: function(e) { var t = e.target || e.srcElement || e, c = cnt.cloneNode(); t.setAttribute('data-bound', 'true'); t.parentNode.insertBefore(c, t); c.appendChild(t); c.style.width = t.clientWidth +'px'; c.style.height = t.clientHeight +'px'; if (v.iSh) c.appendChild(icon.cloneNode()); }, u: function(e) { var t = bE(e.target || e.srcElement), i; if (t) { i = t.getElementsByTagName('img')[0]; if (!o.hasOwnProperty('st')) o.i(); if (!o.st) o.s(i); else o.h(); } } }; document.getElementsByTagName('head')[0].appendChild(sy); adEvt(document.body, 'click', z.u); z.b(); if (v.dynamicLoad) { setInterval(function() { if (o.st !== 1) z.b(); }, v.dynamicInterval || 200); } };
@davidmcmurrey2022
Copy link

Hello from Austin, TX USA. Great stuff. My tech writing students have asked about this. Best I've found! Thanks, Kevin.
David McMurrey, Ph.D.
Business, Government & Technical Communications
Austin Community College
https://mcmassociates.io/dmz_index.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment