Skip to content

Instantly share code, notes, and snippets.

@ryankinal
Created July 11, 2012 16:39
Show Gist options
  • Save ryankinal/3091608 to your computer and use it in GitHub Desktop.
Save ryankinal/3091608 to your computer and use it in GitHub Desktop.
POJS lightbox
/**
These two functions (addEvent and removeEvent) should be added to common.js
- they are generally useful functions that could be used across the entire site
when custom javascript is needed. The lightbox requires them for use.
**/
function addEvent( obj, type, fn )
{
if (obj.addEventListener)
{
obj.addEventListener( type, fn, false );
}
else if (obj.attachEvent)
{
obj["e"+type+fn] = fn;
obj[type+fn] = function() { return obj["e"+type+fn]( window.event ); };
obj.attachEvent( "on"+type, obj[type+fn] );
}
}
function removeEvent( obj, type, fn )
{
if (obj.removeEventListener)
{
obj.removeEventListener( type, fn, false );
}
else if (obj.detachEvent)
{
obj.detachEvent( "on"+type, obj[type+fn] );
obj[type+fn] = null;
obj["e"+type+fn] = null;
}
}
/**
Gets the current scroll position of the window - might want to add
to common.js? Not sure we'll use it elsewhere.
**/
var getScrollTop = function()
{
var w = window.pageYOffset;
var d = document.documentElement ? document.documentElement.scrollTop : 0;
var b = document.body ? document.body.scrolltop : 0;
var val = w || d || b;
if (val)
{
return val;
}
else
{
return 0;
}
};
/**
Gets the height of the window - not the document, but the viewport. Again,
may want to add to common.js.
**/
var getWindowHeight = function()
{
var w = window.innerHeight;
var d = document.documentElement ? document.documentElement.clientHeight : 0;
var b = document.body ? document.body.clientHeight : 0;
var val = w || d || b;
if (val)
{
return val;
}
else
{
return 0;
}
};
/**
Gets the width of the window - not the document, but the viewport. Again,
may want to add to common.js
**/
var getWindowWidth = function()
{
var w = window.innerwidth;
var d = document.documentElement ? document.documentElement.clientWidth : 0;
var b = document.body ? document.body.clientWidth : 0;
var val = w || d || b;
if (val)
{
return val;
}
else
{
return 0;
}
};
/**
Call this function to initialize ALL lightbox elements on the page
- lightbox elements are determined by links (<a> tags) with rel="lightbox".
The href should be #id where id is the id of the element to be shown
by that link.
You can pass a parameters object to the function to customize its behavior:
openCallBack: The function to be called after the lightbox opens
closeCallBack: The function to be called after the lightbox closes
sticky: Whether clicking outside the lightbox will close the lightbox - defaults to false
blanketColor: The color of the blanket fade-in - defaults to '#FFF'
ex: lb = lightbox({closeCallBack: function, sticky: true, blanketColor: '#000'});
KNOWN ISSUE:
If 'sticky' is false, checkboxes will not function within the lightbox in Internet Explorer
**/
var lightbox = function(p_params)
{
var openCallBack;
var closeCallBack;
var sticky = false;
var blanketColor = '#FFF';
if (p_params)
{
if (p_params.hasOwnProperty('openCallBack') && typeof p_params.openCallBack === 'function')
{
openCallBack = p_params.openCallBack;
}
if (p_params.hasOwnProperty('closeCallBack') && typeof p_params.closeCallBack === 'function')
{
closeCallBack = p_params.closeCallBack;
}
if (p_params.hasOwnProperty('sticky') && typeof p_params.sticky === 'boolean')
{
sticky = p_params.sticky;
}
if (p_params.hasOwnProperty('blanketColor') && typeof p_params.blanketColor === 'string')
{
blanketColor = p_params.blanketColor;
}
}
/**
The blanket that covers the rest of the content while
the lightbox is shown. There is only one.
**/
var blanket = document.getElementById('lightboxBlanket');
if (!blanket)
{
blanket = document.createElement('div');
blanket.id = 'lightboxBlanket';
blanket.style.position = 'absolute';
blanket.style.left = '0';
blanket.style.top = '0';
blanket.style.width = '100%';
blanket.style.height = '100%';
blanket.style.display = 'none';
blanket.style.backgroundColor = blanketColor;
blanket.style.filter = 'alpha(opacity=80)';
blanket.style.opacity = '0.8';
blanket.style.zIndex = '2000';
}
document.body.appendChild(blanket);
/**
Fades the blanket in
**/
var fadeBlanketIn = function()
{
var max = 70;
var helper = function(p_opacity)
{
if (p_opacity < max)
{
blanket.style.opacity = p_opacity / 100;
blanket.style.filter = 'alpha(opacity=' + p_opacity + ')';
setTimeout(function() { helper(p_opacity + 5); }, 3);
}
else
{
blanket.style.opacity = max / 100;
blanket.style.filter = 'alpha(opacity=' + max + ')';
}
};
helper(0);
};
/**
The close link - there is only one, and it gets passed around
between each of the lightboxes.
**/
var closeLink = document.getElementById('lightboxClose');
if (!closeLink)
{
closeLink = document.createElement('a');
var closeText = document.createTextNode('close');
closeLink.href = '#';
closeLink.className = 'lightboxClose';
closeLink.id = 'lightboxClose';
closeLink.style.display = 'block';
closeLink.style.clear = 'both';
closeLink.appendChild(closeText);
}
// Keep track of which lightbox is displayed
var displayed;
// A function to close the displayed lightbox - almost always called as an event handler
var closeDisplayed = function(e)
{
if (displayed)
{
displayed.style.display = 'none';
blanket.style.display = 'none';
if (!sticky)
{
removeEvent(document, 'click', closeDisplayed);
}
displayed = undefined;
if (closeCallBack)
{
closeCallBack();
}
}
if (e && e.preventDefault)
{
e.preventDefault();
}
else if (window.event && window.event.returnValue)
{
window.eventReturnValue = false;
}
return false;
};
// Add the 'close' event
addEvent(closeLink, 'click', closeDisplayed);
// Add a resize event, so the blanket doesn't get screwed up
addEvent(window, 'resize', function() {
if (displayed)
{
blanket.style.width = getWindowWidth() + 'px';
blanket.style.height = Math.max(displayed.offsetHeight + 60, Math.max(document.body.offsetHeight + 30, getWindowHeight())) + 'px';
}
});
/**
Makes a click handler for the rel="lightbox" links, and returns it
This is where all the actual work happens.
**/
var makeClick = function(p_href)
{
/** Checking to see if the ID from p_href is valid **/
var id = p_href.substring(p_href.indexOf('#') + 1);
var elem = document.getElementById(id);
if (elem)
{
elem.style.position = 'absolute';
elem.style.top = '50%';
elem.style.left = '50%';
elem.style.zIndex = parseInt(blanket.style.zIndex, 10) + 1;
/** The actual event handler **/
return function(e) {
/** close anything that's displayed **/
closeDisplayed();
/** display the blanket **/
blanket.style.display = 'block';
blanket.style.width = getWindowWidth() + 'px';
fadeBlanketIn();
/** display and position the actual lightbox element **/
elem.style.display = 'block';
var adjustedOffset;
if (elem.offsetHeight > getWindowHeight())
{
// Element is bigger than the viewport
adjustedOffset = ((getWindowHeight() / 2) - 30) * -1;
}
else
{
adjustedOffset = ((elem.offsetHeight / 2) - getScrollTop()) * -1;
}
elem.style.marginTop = adjustedOffset + 'px';
elem.style.marginLeft = '-' + (elem.offsetWidth / 2) + 'px';
elem.appendChild(closeLink);
displayed = elem;
/**
If the user clicks anywhere on the document, other than the
lightbox, it closes the lightbox.
**/
if (!sticky)
{
addEvent(document, 'click', closeDisplayed);
/**
Make sure that if the user clicks on the actual element,
it doesn't disappear - this stops the event bubble
**/
addEvent(elem, 'click', function(e) {
if (!e)
{
e = window.event;
}
e.cancelBubble = true;
if (e.stopPropagation)
{
e.stopPropagation();
}
return false;
});
}
/** Set the blanket height after the element is displayed, to make sure we are
getting accurate measurements **/
blanket.style.height = Math.max(elem.offsetHeight + 60, Math.max(document.body.offsetHeight + 30, getWindowHeight())) + 'px';
/**
Stop event bubbling
**/
if (!e)
{
e = window.event;
}
e.cancelBubble = true;
if (e.stopPropagation)
{
e.stopPropagation();
}
/**
Prevent the default action (i.e. following the link) for newer browsers
**/
if (e &&e.preventDefault)
{
e.preventDefault();
}
else if (window.event && window.event.returnValue)
{
window.eventReturnValue = false;
}
if (openCallBack)
{
openCallBack();
}
/**
Prevent the default action (i.e. following the link) for older browsers
**/
return false;
};
}
else
{
/**
If no element with the given ID exists, use the default action
**/
return function() { return true; };
}
};
/**
Get all the anchors in the document, check to see if they're lightbox links,
and if they are, make them a click handler via makeClick()
**/
var anchors = document.getElementsByTagName('a');
var i = 0;
for (i =0; i < anchors.length; i = i + 1)
{
if (anchors[i].rel === 'lightbox')
{
addEvent(anchors[i], 'click', makeClick(anchors[i].href));
}
}
/**
Return an object to control various aspects of the lightbox
- setCloseCallBack - sets a function to be run when the lightbox is closed
- setOpenCallBack - sets a function to be run when the lightbox is opened
- close - closes the lightbox
- getDisplayed - gets the element currently displayed in the lightbox
- setBlanketColor - changes the color of the blanket
**/
var controlObject = {
setCloseCallBack: function(p_callback)
{
if (typeof p_callback === 'function')
{
closeCallBack = p_callback;
return true;
}
return false;
},
setOpenCallBack: function(p_callback)
{
if (typeof p_callback === 'function')
{
openCallBack = p_callback;
return true;
}
return false;
},
close: function()
{
closeDisplayed();
},
getDisplayed: function()
{
return displayed;
},
setBlanketColor: function(p_color)
{
if (typeof p_color === 'string')
{
blanket.style.backgroundColor = p_color
}
}
};
return controlObject;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment