Last active
September 25, 2015 11:08
-
-
Save c-vetter/912465 to your computer and use it in GitHub Desktop.
simple click-through gallery, two variants, see comments and example pages -- add your own sample pics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The ImageCycle class cycles through a given set of images upon clicking the automatically generated buttons. | |
* | |
* @param Node | |
* This container node is expected to contain at least one 'img' tag. | |
* The first 'img' tag found will be used for displaying the cyled images. | |
* @param Array of Array of String [optional] | |
* Array of Arrays, each of which contains | |
* first the image path, then the title, optionally the caption. | |
* | |
* Expects the generated elements to be positioned/styled by CSS. | |
* | |
* Generates buttons inside the container node. | |
* The buttons are 'a' tags with classes 'next_image' and 'previous_image', each containing an 'img' tag | |
* pointing to '/images/next_image.png' or '/images/previous_image.png', respectively. | |
* | |
* Generates a caption element inside the container node. | |
* The caption element is a 'p' tag with class 'caption'. | |
* For empty captions, the caption element gets the additional class 'empty'. | |
* If the caption starts with content enclosed in brackets ('[' and ']'), | |
* that content is assumed to be a css class and added as such. | |
* Apart from that, the caption is considered and handled as plain text. | |
* | |
* Requires DOM functions! | |
* Almost no error handling throughout!! | |
*/ | |
function ImageCycle(container, images) { | |
this.container = container; | |
for(i in this.container.childNodes) | |
if (this.container.childNodes[i].tagName | |
&& this.container.childNodes[i].tagName.toLowerCase() == 'img') { | |
this.image = this.container.childNodes[i]; | |
break; | |
} | |
this.caption = document.createElement('p'); | |
this.caption.className = 'caption'; | |
this.container.appendChild(this.caption); | |
this.images = []; | |
this.set_images(images); | |
this.forth_button = document.createElement('a'); | |
this.forth_button.cycler = this; | |
this.forth_button.onclick = this.next_image; | |
image = document.createElement('img'); | |
image.src = this.next_image_button_path; | |
image.alt = this.next_image_label; | |
this.forth_button.appendChild(image); | |
this.forth_button.className = 'next_image'; | |
this.container.appendChild(this.forth_button); | |
this.back_button = document.createElement('a'); | |
this.back_button.cycler = this; | |
this.back_button.onclick = this.previous_image; | |
image = document.createElement('img'); | |
image.src = this.previous_image_button_path; | |
image.alt = this.previous_image_label; | |
this.back_button.appendChild(image); | |
this.back_button.className = 'previous_image'; | |
this.container.appendChild(this.back_button); | |
} | |
// global defaults | |
ImageCycle.prototype.next_image_label = 'next image'; | |
ImageCycle.prototype.next_image_button_path = 'images/next_image.png'; | |
ImageCycle.prototype.previous_image_label = 'previous image'; | |
ImageCycle.prototype.previous_image_button_path = 'images/previous_image.png'; | |
/** | |
* Updates the array of images with the given array. | |
* | |
* @param Array of Array of String | |
* | |
* @return false if given object is not an array | |
* | |
* Expects an Array of Arrays, each of which contains | |
* first the image path, then the title, optionally the caption. | |
*/ | |
ImageCycle.prototype.set_images = function(new_images) { | |
if (is_array(new_images)) { | |
this.images = []; | |
for(i in new_images) { | |
array = new_images[i]; | |
object = {}; | |
object.path = array[0]; | |
object.title = array[1]; | |
if (array[2]) { | |
caption_data = /^(\s*\[(.+?)\]\s*)?(.*)/.exec(array[2]); | |
object.caption = caption_data[3]; | |
object.caption_style = caption_data[2] || ''; | |
} else { | |
object.caption = ''; | |
object.caption_style = 'empty'; | |
} | |
this.images.push(object); | |
} | |
count_down = this.images.length; | |
while (count_down-- > 0 && this.image_data().path != this.image.src) | |
this.cycle_images_forth(); | |
this.update_image(); | |
} else { | |
return false; | |
} | |
} | |
/** | |
* Updates the image and caption elements with the current image data. | |
*/ | |
ImageCycle.prototype.update_image = function() { | |
this.image.src = this.image_data().path; | |
this.image.alt = this.image_data().title; | |
this.image.title = this.image_data().title; | |
this.caption.innerHTML = this.image_data().caption; | |
this.caption.className = 'caption '+this.image_data().caption_style; | |
} | |
/** | |
* Returns the data for the current image. | |
* | |
* @return Object | |
*/ | |
ImageCycle.prototype.image_data = function() { | |
return this.images[0]; | |
} | |
/** | |
* Tells the cycling object to advance by one image. | |
* | |
* Is automatically added to the generated next-button, | |
* expects to be called from there. | |
*/ | |
ImageCycle.prototype.next_image = function() { | |
this.cycler.cycle_images_forth(); | |
this.cycler.update_image(); | |
} | |
/** | |
* Tells the cycling object to regress by one image. | |
* | |
* Is automatically added to the generated previous-button, | |
* expects to be called from there. | |
*/ | |
ImageCycle.prototype.previous_image = function() { | |
this.cycler.cycle_images_back(); | |
this.cycler.update_image(); | |
} | |
/** | |
* Cycles the images array, putting the first element to the rear. | |
*/ | |
ImageCycle.prototype.cycle_images_forth = function() { | |
this.images.push(this.images.shift()); | |
} | |
/** | |
* Cycles the images array, getting the last element to the front. | |
*/ | |
ImageCycle.prototype.cycle_images_back = function() { | |
this.images.unshift(this.images.pop()); | |
} | |
// Helper functions not directly part of the class | |
/** | |
* Checks whether the given object is an Array. | |
* | |
* @param Object | |
* | |
* @return true if given object is an Array, false otherwise | |
*/ | |
function is_array(object) { | |
try { | |
return object instanceof Array; | |
} catch (error) { | |
// if the client doesn't support the instanceof operator this has the same result, albeit at a lower speed | |
return (obj.constructor.toString().indexOf("Array") != -1); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html | |
PUBLIC "-//W3C//DTD XHTML 1.1//EN" | |
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>ImageCycle example</title> | |
<script type="text/javascript" src="image_cycle.js"/> | |
</head> | |
<body> | |
<div id="gallery"><img src="images/sample.jpg" alt="what you see when there's no gallery"/></div> | |
<script type="text/javascript"> | |
gallery = new ImageCycle(document.getElementById('gallery'), [ | |
['images/one.jpg', "one's company"], | |
['images/two.jpg', "two's a crowd", 'crowded places make me itchy, especially my trigger finger'], | |
['images/three.jpg', "three's a party", '"Party on, Wayne" "Party on, Garth"'] | |
]); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The ExtendedImageCycle class is based on the ImageCycle class. | |
* | |
* @param Node | |
* This container node is expected to contain at least one 'img' tag. | |
* The first 'img' tag found will be used for displaying the cyled images. | |
* The second 'img' tag found will be used for displaying the extra images. | |
* @param Node | |
* Title element | |
* @param Node | |
* Descritption element | |
* @param Array of Array of String [optional] | |
* Array of Arrays, each of which contains in this order: | |
* + image path | |
* + title | |
* + description | |
* + optionally the additional image path | |
* | |
* Expects the generated elements to be positioned/styled by CSS. | |
* | |
* Generates buttons inside the container node. | |
* The buttons are 'a' tags with classes 'next_image' and 'previous_image', each containing an 'img' tag | |
* pointing to '/images/next_image.png' or '/images/previous_image.png', respectively. | |
* | |
* The ExtendedImageCycle class extends upon and modifies the ImageCycle class in these regards: | |
* - It adds an optional second image for every data set | |
* - Instead of the optional caption with an associated style it uses a mandatory description, | |
* which may contain markup, in contrast to the plain-text caption. | |
* - It utilizes more space, namely additional nodes for the description and the title | |
* | |
* Requires DOM functions! | |
* Almost no error handling throughout!! | |
*/ | |
function ExtendedImageCycle(container, title, description, images) { | |
this.container = container; | |
for(i in this.container.childNodes) | |
if (this.container.childNodes[i].tagName | |
&& this.container.childNodes[i].tagName.toLowerCase() == 'img') { | |
if (this.image) { | |
this.extra_image = this.container.childNodes[i]; | |
break; | |
} else | |
this.image = this.container.childNodes[i]; | |
} | |
this.title = title; | |
this.description = description; | |
this.images = []; | |
this.set_images(images); | |
this.forth_button = document.createElement('a'); | |
this.forth_button.cycler = this; | |
this.forth_button.onclick = this.next_image; | |
image = document.createElement('img'); | |
image.src = this.next_image_button_path; | |
image.alt = this.next_image_label; | |
this.forth_button.appendChild(image); | |
this.forth_button.className = 'next_image'; | |
this.container.appendChild(this.forth_button); | |
this.back_button = document.createElement('a'); | |
this.back_button.cycler = this; | |
this.back_button.onclick = this.previous_image; | |
image = document.createElement('img'); | |
image.src = this.previous_image_button_path; | |
image.alt = this.previous_image_label; | |
this.back_button.appendChild(image); | |
this.back_button.className = 'previous_image'; | |
this.container.appendChild(this.back_button); | |
} | |
// global defaults | |
ExtendedImageCycle.prototype.next_image_label = 'next image'; | |
ExtendedImageCycle.prototype.next_image_button_path = 'images/next_image.png'; | |
ExtendedImageCycle.prototype.previous_image_label = 'previous image'; | |
ExtendedImageCycle.prototype.previous_image_button_path = 'images/previous_image.png'; | |
/** | |
* Updates the array of images with the given array. | |
* | |
* @param Array of Array of String | |
* | |
* @return false if given object is not an array | |
* | |
* Expects an Array of Arrays, each of which contains in this order: | |
* the image path, the title, the description, optionally the additional image path. | |
*/ | |
ExtendedImageCycle.prototype.set_images = function(new_images) { | |
if (is_array(new_images)) { | |
this.images = []; | |
for(i in new_images) { | |
array = new_images[i]; | |
object = {}; | |
object.path = array[0]; | |
object.title = array[1]; | |
object.description = array[2]; | |
if (array[3]) | |
object.extra_path = array[3]; | |
this.images.push(object); | |
} | |
count_down = this.images.length; | |
while (count_down-- > 0 && this.image_data().path != this.image.src) | |
this.cycle_images_forth(); | |
this.update_image(); | |
} else { | |
return false; | |
} | |
} | |
/** | |
* Updates the display elements with the current image data. | |
*/ | |
ExtendedImageCycle.prototype.update_image = function() { | |
data = this.image_data(); | |
this.image.src = data.path; | |
this.title.innerHTML = data.title; | |
this.description.innerHTML = data.description; | |
if(data.extra_path) { | |
this.extra_image.src = data.extra_path; | |
this.show_extra_image(); | |
} else | |
this.hide_extra_image(); | |
} | |
/** | |
* Returns the data for the current image. | |
* | |
* @return Object | |
*/ | |
ExtendedImageCycle.prototype.image_data = function() { | |
return this.images[0]; | |
} | |
/** | |
* Tells the cycling object to advance by one image. | |
* | |
* Is automatically added to the generated next-button, | |
* expects to be called from there. | |
*/ | |
ExtendedImageCycle.prototype.next_image = function() { | |
this.cycler.cycle_images_forth(); | |
this.cycler.update_image(); | |
} | |
/** | |
* Tells the cycling object to regress by one image. | |
* | |
* Is automatically added to the generated previous-button, | |
* expects to be called from there. | |
*/ | |
ExtendedImageCycle.prototype.previous_image = function() { | |
this.cycler.cycle_images_back(); | |
this.cycler.update_image(); | |
} | |
/** | |
* Cycles the images array, putting the first element to the rear. | |
*/ | |
ExtendedImageCycle.prototype.cycle_images_forth = function() { | |
this.images.push(this.images.shift()); | |
} | |
/** | |
* Cycles the images array, getting the last element to the front. | |
*/ | |
ExtendedImageCycle.prototype.cycle_images_back = function() { | |
this.images.unshift(this.images.pop()); | |
} | |
/** | |
* Makes the optional additional image visible. | |
*/ | |
ExtendedImageCycle.prototype.show_extra_image = function() { | |
this.extra_image.removeAttribute('style'); | |
} | |
/** | |
* Makes the optional additional image invisible. | |
*/ | |
ExtendedImageCycle.prototype.hide_extra_image = function() { | |
this.extra_image.setAttribute('style', 'display: none'); | |
} | |
// Helper functions not directly part of the class | |
/** | |
* Checks whether the given object is an Array. | |
* | |
* @param Object | |
* | |
* @return true if given object is an Array, false otherwise | |
*/ | |
function is_array(object) { | |
try { | |
return object instanceof Array; | |
} catch (error) { | |
// if the client doesn't support the instanceof operator this has the same result, albeit at a lower speed | |
return (obj.constructor.toString().indexOf("Array") != -1); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html | |
PUBLIC "-//W3C//DTD XHTML 1.1//EN" | |
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>ImageCycle example</title> | |
<script type="text/javascript" src="image_cycle_extended.js"/> | |
</head> | |
<body> | |
<p id="title" style="font-weight: bold"/> | |
<div id="gallery"> | |
<img src="images/sample.jpg" alt="what you see when there's no gallery"/> | |
<img src="images/extra.jpg" alt="what else you see when there's no gallery"/> | |
</div> | |
<div id="description"/> | |
<script type="text/javascript"><![CDATA[ | |
gallery = new ExtendedImageCycle( | |
document.getElementById('gallery'), | |
document.getElementById('title'), | |
document.getElementById('description'), | |
[ | |
['images/one.jpg', "one's company", ''], | |
['images/two.jpg', "two's a crowd", 'crowded places make me <em>itchy</em>, especially my <strong>trigger finger</strong>'], | |
['images/three.jpg', "three's a party", '<blockquote>Party on, Wayne</blockquote><blockquote>Party on, Garth</blockquote>', 'images/wayne.jpg'] | |
] | |
); | |
]]></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment