Old view larger application
/* | |
File: ViewLarger class | |
Version: 0.9 | |
Desc: This class builds the View Larger functionality on a product page. | |
Requires: /pages/v4/script/dhtml_lib.js | |
/pages/v4/script/ProductHelper.js | |
/pages/v4/script/AjaxHelper.js | |
Use: Auto-initialize by setting up a window load event to call AutoInit static member | |
EventHelper.AddEvent(window, 'load', ViewLarger.AutoInit, false); | |
This assumes you already have a link to the view larger page. | |
Author: Eric Shepherd | |
Date: December 2006 | |
Methods: The following methods are in this class. | |
init() | |
If the large image link is present, calls activate() | |
Version History: | |
0.9 EBS Development | |
1.0 EBS Production | |
*/ | |
// Class ViewLarger | |
function ViewLarger(parent) | |
{ | |
this._relAttribute = 'view-larger'; | |
this._imageCaptionId = 'product-caption'; | |
this._parent = parent; | |
} | |
// Public | |
ViewLarger.prototype.SetRelAttribute = function(value) { | |
this._relAttribute = value; | |
} | |
ViewLarger.prototype.SetImageCaptionId = function(value) { | |
this._imageCaptionId = value; | |
} | |
ViewLarger.prototype.SetParent = function(value) { | |
this._parent = value; | |
} | |
// Function: init() | |
// Calls activate() if the view larger link is present | |
// Returns: | |
// void | |
ViewLarger.prototype.init = function() | |
{ | |
if (this.largeImageLink(this._parent) != null) { | |
this.activate(this._parent); | |
} | |
} | |
// Funtion: largeImageLink() | |
// Returns the large image link by querying the document to match the rel attribute "view-larger" | |
// Parameters: | |
// parent - the element in which to check for a view larger link | |
// Returns: | |
// the view larger link if present, else null | |
ViewLarger.prototype.largeImageLink = function(parent) | |
{ | |
var theLinks = parent.getElementsByTagName('a'); | |
var theLink = null; | |
for (i=0; i<theLinks.length; i++) { | |
if (theLinks[i].getAttribute('rel') && theLinks[i].getAttribute('rel').match(this._relAttribute)) { | |
theLink = theLinks[i]; | |
} | |
} | |
return theLink; | |
} | |
// Function: activate() | |
// Adds the click event to trigger the view larger functionality | |
// Parameters: | |
// parent - the element which contains the current view larger scope | |
// Returns: | |
// void | |
ViewLarger.prototype.activate = function(parent) | |
{ | |
var theLink = this.largeImageLink(parent); | |
var thisReference = this; | |
EventHelper.AddEvent(theLink, 'click', ptr = function(e) { thisReference.showLarger(theLink, e); }, false); | |
} | |
// Function: showLarger() | |
// Builds the view larger modal window, or reactivates it as needed, then cancels the default action | |
// Parameters: | |
// theLink - the view larger link which was clicked to activate the view larger functionality | |
// e - the click event | |
// Returns: | |
// void | |
ViewLarger.prototype.showLarger = function(theLink, e) | |
{ | |
// here is where we actually build stuff | |
if (document.getElementById('larger-image') == null) { | |
var newDiv = document.createElement('div'); | |
newDiv.id = 'larger-image'; | |
newDiv.style.display = 'none'; | |
var theBody = document.getElementsByTagName('body')[0]; | |
theBody.appendChild(newDiv); | |
// set overlay size | |
this.overlay(); | |
// load the external page into the div | |
var thisReference = this; | |
// make the xmlhttprequest | |
AjaxHelper.load(newDiv, theLink, function() { thisReference.setBehaviors(); }); | |
} else if (SupportTest.isIE) { // ie has bugs when reactivating the hidden div - things vanish - so we need to make the ajax call again | |
// delete div | |
var div = document.getElementById('larger-image'); | |
div.parentNode.removeChild(div); | |
// redo ajax call | |
var newDiv = document.createElement('div'); | |
newDiv.id = 'larger-image'; | |
newDiv.style.display = 'none'; | |
var theBody = document.getElementsByTagName('body')[0]; | |
theBody.appendChild(newDiv); | |
this.overlay(); | |
var thisReference = this; | |
AjaxHelper.load(newDiv, theLink, function() { thisReference.setBehaviors(); }); | |
} else { // good browsers can just reactivate the hidden div | |
// restore the visibility of the previously hidden element | |
$('larger-image').setStyle('display', 'block'); | |
$('viewlarger-scroll-frame').setStyle('display', 'block'); | |
$('viewlarger-close').setStyle('display', 'block'); | |
$('viewlarger-include').effect('opacity').custom(0,1); | |
// we need to set the image display now, also | |
this.fixImages(theLink); | |
this.fixCaption(); | |
// run the effects for the mouseovers and close functionality | |
this.setBehaviors(); | |
} | |
// cancel the default action | |
EventHelper.CancelDefault(e); | |
} | |
// Function: fixImages() | |
// Fixes all images after a new click reactivates since we don't instantiate a new scroller object | |
// This is kind of ugly, but the scroller doesn't know what's inside it, | |
// so we have to longhand compare the large image with the scroller items. | |
// Parameters: | |
// theLink - the link which was clicked to activate view larger | |
// Returns: | |
// void | |
ViewLarger.prototype.fixImages = function(theLink) | |
{ | |
// get a reference to the ViewLarger object stored as a reference in document | |
var VLI = document.ViewLargerInstance; | |
// get the large image | |
var image = $('main-large-image').getElementsByTagName('img')[0]; | |
// Here we go... | |
// get the old number image and the newly selected image number. | |
// we can take the difference and jump by that number | |
var theOldNumberArr = image.src.match(/_(\d{1,2})\./); | |
var theOldNumber = theOldNumberArr.length > 0 ? theOldNumberArr[1] : 1; | |
// get the new number | |
var theNewNumberArr = theLink.href.match(/image=(\d+)/); | |
var theNewNumber = theNewNumberArr.length > 0 ? theNewNumberArr[1] : 1; | |
// set the new large image | |
var newImage = document.createElement('img'); | |
newImage.src = image.src.replace(/_\d+.jpg/g, '_' + theNewNumber + '.jpg'); | |
newImage.onload = function() { | |
image.src = newImage.src; | |
newImage = null; | |
} | |
// get an array of the images | |
// PROBLEM: IE places the script objects in the ViewLarger.aspx page out of scope, so we can't read from the instances | |
// SOLUTION: Place a reference to the instance in the document object when it's created in ViewLarger.aspx | |
var container = document.getElementById(VLI.scroller._itemId); | |
var thumbnails = container.getElementsByTagName('img'); | |
// get the new number | |
var str = '_' + theNewNumber + '.jpg'; | |
var imageSlot = 1; | |
// assign imageSlot to index in array of that number's occurrence | |
// and set the selected list item for use below | |
var theNewLi; | |
for (i=0; i<thumbnails.length; i++) { | |
if (thumbnails[i].src.match(str)) { | |
imageSlot = i; | |
theNewLi = DomHelper.AscendDom(thumbnails[i], 'li'); | |
} | |
} | |
var oldTop = VLI.scroller._itemTop; | |
var newTop = imageSlot * VLI.scroller._increment; | |
// reset scroller to new position | |
if (thumbnails.length > 6) { | |
VLI.scroller._scrollerItem.style.top = (0 - newTop) + 'px'; | |
VLI.scroller._itemTop = parseInt(VLI.scroller._scrollerItem.style.top); | |
} | |
// change the active/inactive items | |
// start with scroller buttons | |
VLI.scroller.updateControls(0, VLI.scroller.canScrollBackward()); | |
VLI.scroller.updateControls(1, VLI.scroller.canScrollForward()); | |
// then do the image active states and links using the currently instantiated ProductHelper object | |
var theListItems = container.getElementsByTagName('li'); | |
var activeEl; | |
for (i=0; i<theListItems.length; i++) { | |
if (!theListItems[i].getElementsByTagName('a').length > 0) { | |
activeEl = theListItems[i]; | |
VLI.viewLargerPH._storage = DomHelper.DeactivateElement(activeEl, VLI.viewLargerPH._storage); | |
VLI.viewLargerPH._storage = DomHelper.ActivateElement(theNewLi, VLI.viewLargerPH._storage); | |
} | |
} | |
} | |
// Function: fixCaption() | |
// Fix the caption after the modal window is reactivated | |
// Returns: | |
// void | |
ViewLarger.prototype.fixCaption = function() | |
{ | |
var theCaptionNode = document.getElementById(this._imageCaptionId); | |
var theCaption = theCaptionNode.firstChild ? theCaptionNode.firstChild.nodeValue : ' '; | |
var theNewCaptionNode = document.getElementById('viewlarger-caption'); | |
theNewCaptionNode.innerHTML = theCaption; | |
} | |
// Function: setBehaviors() | |
// Callback after ajax call or reactivation of hidden elements. Sets the behavioral effects of the modal window | |
// Returns: | |
// void | |
ViewLarger.prototype.setBehaviors = function() | |
{ | |
var thisReference = this; | |
targetsLoaded = setInterval(setEffects, 300); | |
function setEffects() { | |
if (typeof $ != 'undefined') { | |
// INIT: set the position before making visible | |
thisReference.setPosition(); | |
// make visible | |
$('larger-image').setStyle('display', 'block'); | |
$('viewlarger-scroll-frame').setStyle('display', 'block'); | |
$('viewlarger-close').setStyle('display', 'block'); | |
// EFFECT: sets the opacity of the entire modal window, including display none | |
// after it fades out, so that it won't be present over the product page window | |
viewLargerOpacityEffect = $('viewlarger-include').effect('opacity', { | |
onStart : function() { | |
}, | |
onComplete: function() { | |
$('larger-image').setStyle('display', 'none'); | |
$('viewlarger-scroll-frame').setStyle('display', 'none'); | |
$('viewlarger-close').setStyle('display', 'none'); | |
} | |
}); | |
// ACTION: make modal window draggable | |
var dragOptions = { | |
onStart : function() { | |
$('viewlarger-include').setStyle('cursor', 'move'); | |
}, | |
onComplete : function() { | |
$('viewlarger-include').setStyle('cursor', 'default'); | |
} | |
} | |
$('viewlarger-include').makeDraggable(dragOptions); | |
// EVENT: click - ELEMENT: close button or window overlay - ACTION: close and hide modal window | |
$('viewlarger-overlay').addEvent('click', function() { viewLargerOpacityEffect.custom(1,0); }); | |
$('viewlarger-close').addEvent('click', function() { viewLargerOpacityEffect.custom(1,0); }); | |
// EVENT: keypress - ESCAPE KEY - ACTION: close and hide modal window | |
document.onkeydown = function(e){ | |
if (e == null) { // ie | |
keycode = event.keyCode; | |
} else { // mozilla | |
keycode = e.which; | |
} | |
if(keycode == 27){ // close | |
viewLargerOpacityEffect.custom(1,0); | |
} | |
} | |
// clear interval - TODO: add a try/catch to be sure the interval gets cleared? | |
clearInterval(targetsLoaded); | |
} | |
} | |
} | |
// ----------------------- | |
// HELPER METHODS | |
// ----------------------- | |
// Function: overlay() | |
// Sets the size of the overlay div to match the height and width of the current window | |
// Returns: | |
// void | |
ViewLarger.prototype.overlay = function() | |
{ | |
if (window.innerHeight && window.scrollMaxY || window.innerWidth && window.scrollMaxX) { | |
xScroll = window.innerWidth + window.scrollMaxX; | |
yScroll = window.innerHeight + window.scrollMaxY; | |
var doc = document.documentElement; | |
var docw = (doc && doc.clientWidth) || document.body.clientWidth || window.innerWidth || self.innerWidth; | |
var doch = (doc && doc.clientHeight) || document.body.clientHeight || window.innerHeight || self.innerHeight; | |
xScroll -= (window.innerWidth - docw); | |
yScroll -= (window.innerHeight - doch); | |
} else if (document.body.scrollHeight > document.body.offsetHeight || document.body.scrollWidth > document.body.offsetWidth) { | |
xScroll = document.body.scrollWidth; | |
yScroll = document.body.scrollHeight; | |
} else { | |
xScroll = document.body.offsetWidth; | |
yScroll = document.body.offsetHeight; | |
} | |
$('larger-image').setStyles({ | |
'width' : xScroll + 'px', | |
'height' : yScroll + 'px' | |
}); | |
} | |
// Function: getPageSizes() | |
// Returns an array containing the width and height of the current page | |
// Returns: | |
// array[width, height] | |
ViewLarger.prototype.getPageSizes = function() | |
{ | |
var doc = document.documentElement; | |
var w = window.innerWidth || self.innerWidth || (doc && doc.clientWidth) || document.body.clientWidth; | |
var h = window.innerHeight || self.innerHeight || (doc && doc.clientHeight) || document.body.clientHeight; | |
pageSizes = new Array(w, h); | |
return pageSizes; | |
} | |
// Function: setPosition() | |
// Sets the left and top offsets of the view larger modal window | |
// Returns: | |
// void | |
ViewLarger.prototype.setPosition = function() | |
{ | |
var pageSizes = this.getPageSizes(); | |
var pageScrolls = this.getPageScrollTop(); | |
$('viewlarger-include').setStyles({ | |
'left' : pageScrolls[0] + ((pageSizes[0] - 590)/2) + 'px', | |
'top' : (pageScrolls[1] + 25) + 'px' | |
}); | |
} | |
// Function: getPageScrollTop() | |
// Returns the amount the page has been scrolled | |
// Returns: | |
// array[left offset, top offset] | |
ViewLarger.prototype.getPageScrollTop = function() | |
{ | |
var xScrollLeft; | |
var yScrollTop; | |
if (self.pageYOffset || self.pageXOffset) { | |
xScrollLeft = self.pageXOffset; | |
yScrollTop = self.pageYOffset; | |
} else if (document.documentElement && document.documentElement.scrollTop || document.documentElement.scrollLeft) { | |
xScrollLeft = document.documentElement.scrollLeft; | |
yScrollTop = document.documentElement.scrollTop; | |
} else if (document.body) { | |
xScrollLeft = document.body.scrollLeft; | |
yScrollTop = document.body.scrollTop; | |
} | |
pageScrolls = new Array(xScrollLeft, yScrollTop); | |
return pageScrolls; | |
} | |
// Function: AutoInit() | |
// Static member to create a standard application on a product page assuming we are targeting the "#product-shot" element | |
// Returns: | |
// void | |
ViewLarger.AutoInit = function() { | |
var parent = document.getElementById('product-shot'); | |
var instance = new ViewLarger(parent); | |
instance.init(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment