var JaS = {
// Customization parameters
imagePath : "../Assets/images/",
images : [
["MBchAerialVw.jpg", "South Mission Beach Aerial View", "Aerial views"],
["HseFrnt.jpg", "Front view of House", "House-outside"],
["HseFrntLeft.jpg", "Main bedroom verandah", "House-outside"],
["BkVrndh.jpg", "Back verandah", "House-outside"],
["HseBkLft.jpg", "Late afternoon", "House-outside"],
["HseFrntLime.jpg", "View of house from limetrees", "House-outside"],
["VrndhDng.jpg", "Verandah ~ dining for up to 8 with barbie", "Verandah"],
["MtMckyVw.jpg", "Mount Mackay from verandah", "Verandah"],
["PlVwSteps.jpg", "The Pool ~ just 10 paces from the house", "Pool"],
["PlSnDk.jpg", "relax and sunbake(factor 30 every time)", "Pool"],
["PlVwfrBure.jpg", "sit in the cool of the Shadehouse", "Pool"],
["PlWfall.jpg", "be soothed by the trickling waterfall", "Pool"],
["PlRflctn.jpg", "time for reflection..", "Pool"],
["PlGrvl.jpg", "stepping stones", "Pool"],
["Bedroom 1-a.jpg", "Bedroom 1 ~ carved beds from Java, polished hardwood floors", "House-inside"],
["Bedroom 1-view b.jpg", "all bedrooms have great views & open to verandah", "House-inside"],
["Bdrm2.jpg", "Bedroom 2 ~ all bedrooms have en-suite wetrooms", "House-inside"],
["Bdrm3Lvr.jpg", "Bedroom 3 ~ lots of timber louvres & fans keep the rooms cool & airy", "House-inside"],
["Living Room.jpg", "Living Room ~ the suite is made from twisted banana leaf weave", "House-inside"],
["Kitchen -left.jpg", "Kitchen ~ fully equipped, all mod cons", "House-inside"],
["Kitchen -right.jpg", "hardwood servery slab/breakfast bar", "House-inside"],
["Bfst1.jpg", "enjoy a delicious tropical fruit breakfast ~ grapefruit, mango, lychees, pineapple, paw-paw", "House-inside"],
["Ayers Rock.jpg", "Ayers Rock", "Out and About"],
["PlSunbake.jpg", "lie back and listen to the birds", "Pool"],
["PoolatNight.jpg", "pool at night, underwater seats and lights", "Pool"],
["BchWlks.jpg", "walk the beach", "Beach"],
["Bchempty.jpg", "beach on a busy day", "Beach"],
["Cycle.jpg", "stretch you mind - and your bike!", "Beach"],
["DnkVwfrBch.jpg", "Dunk Island from Mission Beach", "Beach"],
["DnkVwfrBch2.jpg", "Dunk Island through the palms", "Beach"],
["FeetBch.jpg", "feel the sand between your toes", "Beach"],
["MBchBranch.jpg", "typical October day", "Beach"],
["MBchthroughtrees.jpg", "late afternoon at North Mission", "Beach"],
["WtrTxi.jpg", "water-taxi from Wongaling to Dunk Island takes 10 mins", "Dunk Island"],
["DnkWtrsptCntr.jpg", "watersports centre & beach bar", "Dunk Island"],
["SailingDnk.jpg", "sailing", "Dunk Island"],
["DunkRsrt.jpg", "day permit for Dunk Island Resort includes lunch, use of pool & grounds", "Dunk Island"],
["Connectingflights.jpg", "connecting flights to/from Dunk Island", "Dunk Island"],
["DunkJetty.jpg", "the jetty", "Dunk Island"],
["GolfonDunk.jpg", "new and challenging 18-hole resort course", "Dunk Island"],
["DunkAerialblue.jpg", "Dunk Island from the air", "Aerial views"],
["DunkAerialSports.jpg", "watersports from the air", "Aerial views"],
["dunkspa.jpg", "Spa of Peace & Plenty relaxation area", "Dunk Island"],
["Rainforest tracks.jpg", "cool shady rainforest tracks & walks", "Dunk Island"],
["MBchRestaurant.jpg", "'Friends' Restaurant at North Mission Beach", "Mission_Beach"],
["BlueMts.jpg", "The Blue Mountains, west of Sydney", "Out and About"],
["EmptyRoads.jpg", "empty roads, time to see the scenery", "Out and About"],
["EnjoyingaStubby.jpg", "chill out with a 'stubby'", "Out and About"],
["Horizons1.jpg", "enjoy a swim and lunch at 'The Horizon, South Mission Beach", "Mission_Beach"],
["Horizons4.jpg", "spectacular view over Dunk Island from 'The Horizon'", "Mission_Beach"],
["Boulders.jpg", "The Babinda Boulders is not just a beautiful swimming hole, but the area also holds great significance for local Aboriginal people", "Out and About"],
["Cafe.jpg", "street cafe at Mission Beach", "Mission_Beach"],
["MilaaMilaa.jpg", "beautiful Milaa Milaa falls on Atherton Tablelands ~ 1 hr from Yamacutta", "Waterfalls"],
["Elinja.jpg", "Elinja falls ~ Atherton Tablelands", "Waterfalls"],
["WlmnFlls.jpg", "Wallaman Falls is the largest single drop waterfall in Australia, tumbling 305m (1,000 feet) through a rainbow-fringed cloud of mist to a large pool ~ 2 hrs from Yamacutta", "Waterfalls"],
["HinchnbrkRsrt.jpg", "Port Hinchinbrook ~ the Marina", "Out and About"],
["PortHnchnbrk.jpg", "Port Hinchinbrook ~ 30 mins from Yamacutta. Gateway to the 'Hinchinbrook Island experience':untamed wilderness, superb beaches, deserted islands, coral reefs and the best boating and fishing area in Australia", "Out and About"],
["SailingCruise.jpg", "a sailing cruise from Cairns", "Out and About"],
["YamAerialMarked.jpg", "Yamacutta from the air", "Aerial views"],
["Cassowaries with chicks from verandah.jpg", "cassowaries with 1 week old chicks in the garden", "Flora & Fauna"],
["Ulysses large.jpg", "stunning 'Ulysses' butterflies often circuit the house around mid-day", "Flora & Fauna"],
["CswryClse.jpg", "a regular visitor ~ the male cassowary rears the chicks", "Flora & Fauna"],
["FrstKfshr.jpg", "Forest Kingfisher sits in a Foxtail Palm in front of the house", "Flora & Fauna"],
["green tree frog.jpg", "Green Tree Frog", "Flora & Fauna"],
["Sunbird.jpg", "Sunbird", "Flora & Fauna"],
["Wallaby with young.jpg", "wallaby with young", "Flora & Fauna"],
["SunbirdinNest.jpg", "intricate nest of sunbird hangs on the windchime on the verandah", "Flora & Fauna"],
["QldMapleseed.jpg", "star-shaped seedpod of the Queensland Maple", "Flora & Fauna"],
["AloeVera.jpg", "Aloe Vera thrives around Mission Beach", "Flora & Fauna"],
["WhieAnttrails.jpg", "white ant trails","Flora & Fauna"],
["Vine.jpg","rainforest vine", "Flora & Fauna"],
["PncianaLge.jpg", "Poinciana flowers brilliantly in North Queensland", "Flora & Fauna"],
["Licuala.jpg", "Licuala ~ dramatic fan palm found in the Rainforest", "Flora & Fauna"],
["BlueQuandongFruit.jpg", "fruit of Blue Quandong ~ important component of cassowary's diet", "Flora & Fauna"],
["TullyGorge.jpg", "nearby Tully Gorge ~ a good excursion for a wet day walk(also white-water rafting)", "Out and About"],
["BrownHuntsman.jpg", "Brown Huntsman spider ~ large but considered harmless.(All spiders can & will bite if threatened so look don't touch!)", "Flora & Fauna"],
["Croc.jpg", "the 'Saltie' or saltwater crocodile is found throughout Northern Australia", "Flora & Fauna"],
["balooning.jpg", "Ballooning over the Tablelands","Out and About"],
["rafting.jpg", "white-water rafting on the Tully River", "Out and About"],
["quickcat.jpg", "Reef trips on the 'Quickcat' from Mission Beach", "Out and About"],
["Lmades.jpg", "Lemonade trees in the orchard", "Flora & Fauna"],
["Jackfruit.jpg", "Jack Fruit ~ largest tree-born fruit in the world can grow to 3 feet long","Flora & Fauna"],
["Bamboo.jpg", "Giant Bamboo ~ can grow at an incredible 0.24mtrs a day!", "Flora & Fauna"]
],
fadeContainerId : "jas-container",
imageContainerId : "jas-image",
imageTextContainerId : "jas-image-text",
previousLinkId : "previous-image",
nextLinkId : "next-image",
imageCounterId : "image-counter",
startSlideShowId : "start-slideshow",
stopSlideShowId : "stop-slideshow",
thumbnailContainerId: "jas-thumbnails",
tagsContainerId: "jas-tags",
tagsSelectAllId: "jas-select-all-tags",
useImageText : true,
useThumbnails : true,
useTags : true,
useKeyboardShortcuts : true,
useFadingIn : true,
useFadingOut : true,
useFadeWhenNotSlideshow : false,
useFadeForSlideshow : true,
useFadeAtInitialLoad : false,
fadeIncrement : 0.1,
fadeInterval : 100, // Milliseconds
timeForSlideInSlideshow : 3000, // Milliseconds

// JaS function parameters
allImages : null,
currentImages : null,
fadeContainer : null,
imageContainer : null,
imageTextContainer : null,
previousLink : null,
nextLink : null,
imageCounter : null,
startSlideShowLink : null,
stopSlideShowLink : null,
thumbnailContainer : null,
thumbnailCollection : [],
currentThumbnailSelected : null,
tagsContainer : null,
tagsSelectAll : null,
tagsList : null,
tags : [],
tagsCheckboxes : [],
selectAllTags : true,
imageText : null,
imageText : "",
imageSource : "",
imageIndex : 0,
fadingIn : true,
fadeLevel : 0,
fadeEndLevel : 1,
fadeTimer : null,
hasOpacitySupport : false,
useMSFilter : false,
useMSCurrentStyle : false,
slideshowIsSupported : false,
slideshowIsPlaying : false,
functionAfterFade : null,
isInitialLoad : false,

init : function (){
    if(document.getElementById){
this.fadeContainer = document.getElementById(this.fadeContainerId);
this.imageContainer = document.getElementById(this.imageContainerId);
this.slideshowIsSupported = this.fadeContainer && this.imageContainer;
if(this.slideshowIsSupported){
this.allImages = this.images;
this.currentImages = this.images;
if(this.useImageText){
this.imageTextContainer = document.getElementById(this.imageTextContainerId);
if(!this.imageTextContainer){
this.useImageText = false;
}
}
this.hasOpacitySupport = typeof this.fadeContainer.style.filter != "undefined" || typeof this.fadeContainer.style.opacity != "undefined";
this.useMSFilter = typeof this.fadeContainer.style.filter != "undefined";
this.useMSCurrentStyle = typeof this.fadeContainer.currentStyle != "undefined";

this.previousLink = document.getElementById(this.previousLinkId);
this.previousLink.onclick = function(oEvent){
var oEvent = (typeof oEvent != "undefined")? oEvent : event;
JaS.preventDefaultEventBehavior(oEvent);
JaS.previousImage();
};
this.nextLink = document.getElementById(this.nextLinkId);
this.nextLink.onclick = function(oEvent){
var oEvent = (typeof oEvent != "undefined")? oEvent : event;
JaS.preventDefaultEventBehavior(oEvent);
JaS.nextImage();
};
this.imageCounter = document.getElementById(this.imageCounterId);
this.startSlideShowLink = document.getElementById(this.startSlideShowId);
if(this.startSlideShowLink){
this.startSlideShowLink.style.display = "inline";
}
this.startSlideShowLink.onclick = function(oEvent){
var oEvent = (typeof oEvent != "undefined")? oEvent : event;
JaS.preventDefaultEventBehavior(oEvent);
JaS.startSlideshow();
};
this.stopSlideShowLink = document.getElementById(this.stopSlideShowId);
if(this.stopSlideShowLink){
this.stopSlideShowLink.style.display = "none";
}
this.stopSlideShowLink.onclick = function(oEvent){
var oEvent = (typeof oEvent != "undefined")? oEvent : event;
JaS.preventDefaultEventBehavior(oEvent);
JaS.stopSlideshow();
};

if(this.useKeyboardShortcuts){
document.onkeydown = function(oEvent){
var oEvent = (typeof oEvent != "undefined")? oEvent : event;
JaS.applyKeyboardNavigation(oEvent);
};
}

this.thumbnailContainer = document.getElementById(this.thumbnailContainerId);
if(this.useThumbnails && this.thumbnailContainer){
this.createThumbnails();
}

this.tagsContainer = document.getElementById(this.tagsContainerId);
if(this.useTags && this.tagsContainer){
this.tagsSelectAll = document.getElementById(this.tagsSelectAllId);
if(this.tagsSelectAll){
this.tagsSelectAll.onclick = function (oEvent){
JaS.tagsSelectAll = this.checked;
JaS.markAllTags();
};
this.createTagList();
}
}

this.isInitialLoad = true;
this.setImage();
this.isInitialLoad = false;
}
}
},

setImage : function (){
if(this.currentImages.length > 0){
this.imageContainer.style.visibility = "visible";
this.imageSource = this.currentImages[this.imageIndex][0];
this.imageText = this.currentImages[this.imageIndex][1];
if(this.useFadingOut && (this.slideshowIsPlaying && this.useFadeForSlideshow) || (!this.slideshowIsPlaying && this.useFadeWhenNotSlideshow) && (this.useFadeAtInitialLoad && this.isInitialLoad || !this.isInitialLoad)){
this.fadeOut();
}
else{
this.displayImageCount();
this.imageContainer.setAttribute("src", (this.imagePath + this.imageSource));
this.setImageText();
this.previousLink.style.visibility = (this.imageIndex > 0)? "visible" : "hidden";
this.nextLink.style.visibility = (this.imageIndex < (this.currentImages.length - 1))? "visible" : "hidden";
if((this.useFadeAtInitialLoad && this.isInitialLoad || !this.isInitialLoad) && ((this.slideshowIsPlaying && this.useFadeForSlideshow) || (!this.slideshowIsPlaying && this.useFadeWhenNotSlideshow))){
this.fadeIn();
}
}
if(this.useThumbnails){
this.markCurrentThumbnail();
}
}
else{
this.imageSource = "";
this.imageText = "";
this.displayImageCount();
this.imageContainer.style.visibility = "hidden";
this.setImageText();
}
},

displayImageCount : function (){
    if(this.imageCounter){
this.imageCounter.innerHTML = (((this.currentImages.length > 0)? this.imageIndex : -1) + 1) + " / " + this.currentImages.length;
}
},

nextImage : function (){
if(this.imageIndex < (this.currentImages.length - 1)){
++this.imageIndex;
this.setImage();
}
else if(this.slideshowIsPlaying){
this.stopSlideshow();
this.imageIndex = 0;
this.setImage();
}
},

previousImage : function (){
if(this.imageIndex > 0){
--this.imageIndex;
this.setImage();
}
},

setImageText : function (){
this.imageTextContainer.setAttribute("alt", this.imageText);
    if(this.useImageText && typeof this.imageText == "string"){
this.imageTextContainer.innerHTML = this.imageText;
}
},

startSlideshow : function (){
if(this.currentImages.length > 0){
this.startSlideShowLink.style.display = "none";
this.stopSlideShowLink.style.display = "inline";
this.slideshowIsPlaying = true;
this.fadeTimer = setTimeout("JaS.nextImage()", JaS.timeForSlideInSlideshow);
}
},

stopSlideshow : function (){
if(this.currentImages.length > 0){
this.startSlideShowLink.style.display = "inline";
this.stopSlideShowLink.style.display = "none";
this.slideshowIsPlaying = false;
this.setFadeParams(false, 1, 0);
this.setFade();
clearTimeout(this.fadeTimer);
}
},

fadeIn : function (){
this.setFadeParams(true, 0, 1);
this.functionAfterFade = null;
this.fade();
if(this.slideshowIsPlaying){
this.functionAfterFade = "this.startSlideshow()";
}
},

fadeOut : function (){
this.setFadeParams(false, 1, 0);
this.functionAfterFade = "this.fadeOutDone()";
this.fade();
},

fadeOutDone : function (){
        this.displayImageCount();
this.imageContainer.setAttribute("src", (this.imagePath + this.imageSource));
this.setImageText();
if(this.useFadingIn){
this.fadeIn();
}
else{
this.fadeLevel = 1;
this.setFade();
}
},

fade : function (){
if((this.fadingIn && this.fadeLevel < this.fadeEndLevel) || !this.fadingIn && this.fadeLevel > this.fadeEndLevel){
this.fadeLevel = (this.fadingIn)? this.fadeLevel + this.fadeIncrement : this.fadeLevel - this.fadeIncrement;
// This line is b/c of a floating point bug in JavaScript
this.fadeLevel = Math.round(this.fadeLevel * 10) / 10;
this.setFade();
this.fadeTimer = setTimeout("JaS.fade()", this.fadeInterval);
}
else{
clearTimeout(this.fadeTimer);
if(this.functionAfterFade){
eval(this.functionAfterFade);
}
}
},

setFade : function (){
if(this.useMSFilter){
this.fadeContainer.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + (this.fadeLevel * 100) + ")";
}
else{
this.fadeContainer.style.opacity = this.fadeLevel;
}
},

setFadeParams : function (bFadingIn, intStartLevel, intEndLevel){
this.fadingIn = bFadingIn;
this.fadeLevel = intStartLevel;
this.fadeEndLevel = intEndLevel;
},

createThumbnails : function (){
this.thumbnailContainer.innerHTML = "";
this.thumbnailCollection = [];
    var oThumbnailsList = document.createElement("ul");
var oListItem;
var oThumbnail;
var oCurrentImage;
for(var i=0; i<this.currentImages.length; i++){
        oCurrentImage = this.currentImages[i];
oListItem = document.createElement("li");
oThumbnail = document.createElement("img");
oThumbnail.setAttribute("id", ("jas-thumbnail-" + i));
oThumbnail.setAttribute("src", (this.imagePath + oCurrentImage[0]));
oThumbnail.setAttribute("alt", oCurrentImage[1]);
oThumbnail.setAttribute("title", oCurrentImage[1]);
oThumbnail.onclick = function (oEvent){
JaS.imageIndex = parseInt(this.getAttribute("id").replace(/\D*(\d+)$/, "$1"), 10);
JaS.setImage();
};
this.thumbnailCollection.push(oThumbnail);
oListItem.appendChild(oThumbnail);
oThumbnailsList.appendChild(oListItem);
        }
this.thumbnailContainer.appendChild(oThumbnailsList);
if(this.thumbnailCollection.length > 0){
this.markCurrentThumbnail();
}
if(this.slideshowIsPlaying){
this.stopSlideshow();
}
},

markCurrentThumbnail : function (){
if(this.currentThumbnailSelected){
        this.currentThumbnailSelected.className = "";
// Sometimes, in IE, the image loses its reference to its parent
if(this.currentThumbnailSelected.parentNode){
this.currentThumbnailSelected.parentNode.className = "";
}
}
this.currentThumbnailSelected = this.thumbnailCollection[this.imageIndex];
this.currentThumbnailSelected.className = "selected";
this.currentThumbnailSelected.parentNode.className = "selected-parent";
},

createTagList : function (){
var strCurrentTag;
var arrCurrentTag;
var oRegExp;
for(var i=0; i<this.images.length; i++){
arrCurrentTag = this.images[i][2].replace(/\s*(,)\s*/,  "$1").split(",");
for(var j=0; j<arrCurrentTag.length; j++){
            strCurrentTag = arrCurrentTag[j];
oRegExp = new RegExp(strCurrentTag, "i");
if(this.tags.toString().search(oRegExp) == -1){
this.tags.push(strCurrentTag);
}
            }
        }
this.tagsList = document.createElement("ul");
var oListItem;
var oTagCheckbox;
var oLabel;
for(var k=0; k<this.tags.length; k++){
oTag = this.tags[k];
oListItem = document.createElement("li");
oTagCheckbox = document.createElement("input");
oTagCheckbox.setAttribute("type", "checkbox");
oTagCheckbox.setAttribute("id", ("jas-" + oTag));
oTagCheckbox.setAttribute("value", oTag);
oTagCheckbox.checked = true;
oTagCheckbox.onclick = function (oEvent){
JaS.applyTagFilter();
};
oLabel = document.createElement("label");
oLabel.setAttribute("for", ("jas-" + oTag));
oLabel.innerHTML = oTag;
this.tagsCheckboxes.push(oTagCheckbox);
oListItem.appendChild(oTagCheckbox);
oListItem.appendChild(oLabel);
this.tagsList.appendChild(oListItem);
}
this.tagsContainer.appendChild(this.tagsList);
// This loop is necessary since IE can only mark checkboxes as checked after they've been added to the document
for(var l=0; l<this.tagsCheckboxes.length; l++){
this.tagsCheckboxes[l].checked = true;
}
},

applyTagFilter : function (){
this.currentImages = [];
var arrCurrentTags = [];
var oCheckbox;
for(var i=0; i<this.tagsCheckboxes.length; i++){
        oCheckbox = this.tagsCheckboxes[i];
if(oCheckbox.checked){
arrCurrentTags.push(oCheckbox.value);
}
        }
var oRegExp;
var oImage;
for(var j=0; j<this.images.length; j++){
        oImage = this.images[j];
for(var k=0; k<arrCurrentTags.length; k++){
oRegExp = new RegExp(arrCurrentTags[k], "i");
if(oImage[2].search(oRegExp) != -1){
this.currentImages.push(oImage);
break;
}
}
        }

if(this.useThumbnails){
this.createThumbnails();
}
this.imageIndex = 0;
this.setImage();
},

markAllTags : function (){
for(var i=0; i<this.tagsCheckboxes.length; i++){
this.tagsCheckboxes[i].checked = this.tagsSelectAll;
        }
this.applyTagFilter();
},

closeSession : function (oEvent){
JaS = null;
delete JaS;
},

applyKeyboardNavigation : function (oEvent){
    var intKeyCode = oEvent.keyCode;
    if(!oEvent.altKey){
switch(intKeyCode){
case 32:
this.slideshowIsPlaying = (this.slideshowIsPlaying)? false : true;
if(this.slideshowIsPlaying){
this.startSlideshow();
}
else{
this.stopSlideshow();
}
this.preventDefaultEventBehavior(oEvent);
break;
case 37:
case 38:
this.previousImage();
this.preventDefaultEventBehavior(oEvent);
break;
case 39:
case 40:
this.nextImage();
this.preventDefaultEventBehavior(oEvent);
break;
}
}
},

preventDefaultEventBehavior : function (oEvent){
if(oEvent){
oEvent.returnValue = false;
if(oEvent.preventDefault){
oEvent.preventDefault();
}
}
}
};
// ---
addEvent(window, "load", function(){JaS.init();}, false);
addEvent(window, "unload", function(){JaS.closeSession();}, false);
// ---
// Utility functions
function addEvent(oObject, strEvent, oFunction, bCapture){
if(oObject){
if(oObject.addEventListener){
oObject.addEventListener(strEvent, oFunction, bCapture);
}
else if(window.attachEvent){
oObject.attachEvent(("on" + strEvent), oFunction)
}
}
}
// ---
if(typeof Array.prototype.push != "function"){
Array.prototype.push = ArrayPush;
function ArrayPush(value){
this[this.length] = value;
}
}
