/*  Classes and functions specific for the Ontwerpfontein site  Author: Theo M. Gerrits (tmg)  Dependencies: Logger.js          Timer.js          Images.js          Layer.js          ScrollableLayer.js          Scrollbar.js  Copyright (C) 2005-2007 Ontwerpfontein*//*  Description     : Point constructor; class for encapsulating a point/vector  Parameters      : the coordinates of the point in pixels  Properties      :    x    y*/function Point (x, y){  this.x = x;  this.y = y;}// Description     : create a new point from an existing one, translated by a given vector// Parameters      : the translation vector coordinates in pixels// Returns         : the new PointPoint.prototype.createTranslatedPoint = function (dx, dy){  return new Point(this.x + dx, this.y + dy);}// Description     : create a new point from an existing one, translated by a given vector// Parameters      : a translation vector (Point object)// Returns         : the new PointPoint.prototype.createTranslatedPointByVector = function (vector){  return new Point(this.x + vector.x, this.y + vector.y);}/*  Description     : constructor; this class is responsible for the message 'ticker'  Parameters      : id: Ticker id  Properties      :    id    layer: the ticker Layer    timer: the ticker Timer    speed: the ticker speed in pixels per second    tickStep    tickDuration    imageLeft    imageRight    textWidth    pos*/function Ticker (id){  this.id = id;  this.layer = new Layer(this.id);  this.layer.clip();  this.timer = new Timer(this.id + "Timer");  this.speed = this.DEFAULT_SPEED;  this.tickDuration = this.DEFAULT_TICK;  this.tickStep = this.speed*this.tickDuration;  LOG.debug("Ticker step: " + this.tickStep + ", duration: " + this.tickDuration);  this.imageLeft = new Layer("img" + this.id + "Text1");  this.imageRight = new Layer("img" + this.id + "Text2");  this.textWidth = this.imageLeft.width;  this.pos = 0;  this.placeImages();}Ticker.prototype.DEFAULT_SPEED = 50; // pixels per secondTicker.prototype.DEFAULT_TICK = .04; // pixels per secondTicker.prototype.BETWEEN_SPACE = 0; // pixels// Description     : position the images// Parameters      : none// Returns         : void// Remark          : private functionTicker.prototype.placeImages = function (){  var rightPos = this.pos + this.textWidth + this.BETWEEN_SPACE;  if (rightPos < 0)  {    this.pos = rightPos;    rightPos = this.pos + this.textWidth + this.BETWEEN_SPACE;  }  this.imageLeft.moveTo(this.pos);  this.imageRight.moveTo(rightPos);}// Description     : start the ticker// Parameters      : none// Returns         : void// Remark          : private functionTicker.prototype.doTick = function (){  this.pos -= this.tickStep;  // LOG.info("Tick: " + this.pos);  this.placeImages();  this.start();}// Description     : start the ticker// Parameters      : none// Returns         : voidTicker.prototype.start = function (){  this.timer.start(this.tickDuration, this.doTick, null, this);}// Description     : stop the ticker// Parameters      : none// Returns         : voidTicker.prototype.stop = function (){  this.timer.stop();}/*  Description     : constructor; this class is responsible for positioning a layer in its containing box, with constraints    - define minimum and maximum values for each margin around the layer;    - if more room is available than the minimum margin needed, enlarge the margin proportionally until the maximum is reached.    - To measure the size of the complete body in both Internet explorer and Mozilla, the following must be met:       - Measure width and height with a child element of BODY with width:100% and height:100%       - the BODY tag must have height:100%  Parameters      : layer: Layer to position  Properties      :    layer: the Layer to position    parent: containing element    minimumMarginLeft    minimumMarginTop    minimumMarginRight    minimumMarginBottom    maximumMarginLeft    maximumMarginTop    maximumMarginRight    maximumMarginBottom*/function FloatingLayer (layer, parent){  this.layer = layer;  this.parent = parent;  this.setMinimumMargins(0, 0, 0, 0);  this.setMaximumMargins();}// Description     : set the minimum values for each margin// Parameters      : the margin values// Returns         : voidFloatingLayer.prototype.setMinimumMargins = function (top, right, bottom, left){  this.minimumMarginTop = top;  this.minimumMarginRight = right;  this.minimumMarginBottom = bottom;  this.minimumMarginLeft = left;}// Description     : set the maximum values for each margin// Parameters      : the margin values (null means no maximum)// Returns         : voidFloatingLayer.prototype.setMaximumMargins = function (top, right, bottom, left){  this.maximumMarginTop = top;  this.maximumMarginRight = right;  this.maximumMarginBottom = bottom;  this.maximumMarginLeft = left;}// Description     : position the layer// Parameters      : none// Returns         : voidFloatingLayer.prototype.place = function (){  LOG.debug("size: " + this.parent.offsetWidth + "x" + this.parent.offsetHeight);  var availableMarginWidth = this.parent.offsetWidth - this.layer.width - this.minimumMarginLeft - this.minimumMarginRight;  var availableMarginHeight = this.parent.offsetHeight - this.layer.height - this.minimumMarginTop - this.minimumMarginBottom;  if (availableMarginWidth < 0)    availableMarginWidth = 0;  if (availableMarginHeight < 0)    availableMarginHeight = 0;  var x = this.minimumMarginLeft + availableMarginWidth/2;  var y = this.minimumMarginTop + availableMarginHeight/2;  if (x > this.maximumMarginLeft)    x = this.maximumMarginLeft;  if (y > this.maximumMarginTop)    y = this.maximumMarginTop;  this.layer.moveTo(x, y);}/*  Description     : constructor; this class is responsible for choosing and presenting an item from a PortfolioClient  Parameters      : none  Properties      :    client: currently selected client    currentItemIndex: index of the currently selected item    selectorLayer: layer containing the selector controls    selectorKnobs: array of the specific item selector knob layers    selectedKnob: layer containing the selected item knob    itemImage: image showing the current item    itemLayer: layer containing the item image    contentWidth: width of layer containing the item layer in pixels    contentHeight: height of layer containing the item layer in pixels  properties used for centering the item images:    referenceImage: known image used for checking if an item image has been loaded (size: 1x1)    measuringTimer: timer with which to check the measurements*/function ItemSelector (){  this.client = null;  this.currentItemIndex = -1;  this.selectorLayer = new Layer(this.SELECTOR_LAYER_ID);  this.selectorKnobs = new Array();  for (var i = 0; i < this.MAX_NUM_SELECTOR_KNOBS; i++)    this.selectorKnobs[i] = new Layer(this.SELECTOR_KNOB_LAYER_ID_PREFIX + i);  this.selectedKnob = new Layer(this.SELECTED_KNOB_LAYER_ID);  this.itemImage = document.getElementById(this.ITEM_IMAGE_ID);  this.loadingLayer = new Layer(this.LOADING_LAYER_ID);  this.itemLayer = new Layer(this.ITEM_LAYER_ID);  this.htmlItemLayer = new Layer(this.HTML_ITEM_LAYER_ID);  var contentLayer = new Layer(this.CONTENT_LAYER_ID);  this.contentWidth = contentLayer.width;  this.contentHeight = contentLayer.height;  this.referenceImage = new Image();  this.referenceImage.src = this.REFERENCE_IMAGE;  this.measuredWidth = 0;  this.measuredHeight = 0;  this.measuringTimer = new Timer("measuringTimer");}ItemSelector.prototype.SELECTOR_LAYER_ID = "KnopEnBolletjesOnderContentvlak";ItemSelector.prototype.SELECTOR_KNOB_LAYER_ID_PREFIX = "selector";ItemSelector.prototype.SELECTED_KNOB_LAYER_ID = "selectedKnob";ItemSelector.prototype.MAX_NUM_SELECTOR_KNOBS = 19;ItemSelector.prototype.SPACING_BETWEEN_KNOBS = 10;ItemSelector.prototype.CONTENT_LAYER_ID = "ContentCurrentItem";ItemSelector.prototype.LOADING_LAYER_ID = "PortfolioItemLoading";ItemSelector.prototype.ITEM_LAYER_ID = "PortfolioCurrentItem";ItemSelector.prototype.HTML_ITEM_LAYER_ID = "layerPortfolioCurrentHtmlItem";ItemSelector.prototype.ITEM_IMAGE_ID = "imgPortfolioCurrentItem";ItemSelector.prototype.REFERENCE_IMAGE = "images/Spacer.wit.gif";ItemSelector.prototype.LOAD_CHECK_TIME = 0.01;// Description     : center the PortfolioItem image in the content area// Parameters      : none// Returns         : void// Remark          : private functionItemSelector.prototype.centerItem = function (){  var w = this.itemImage.offsetWidth;  var h = this.itemImage.offsetHeight;  LOG.debug("Now: " + w + "x" + h);  if (w == 1 || h == 1)  {    this.measuringTimer.start(this.LOAD_CHECK_TIME, this.centerItem, null, this);    return;  }  var x = (this.contentWidth - w)/2;  var y = (this.contentHeight - h)/2;  if (x < 0)    x = 0;  if (y < 0)    y = 0;  this.itemLayer.moveTo(x, y);  this.loadingLayer.hide();  this.itemLayer.show();}// Description     : select and show a PortfolioItem in the content area.//                   an item may be an image or an html page that should be loaded into an IFRAME.// Parameters      : index of the item// Returns         : voidItemSelector.prototype.showItem = function (index){  this.currentItemIndex = index;  this.selectedKnob.moveTo(index*this.SPACING_BETWEEN_KNOBS);  this.itemLayer.hide();  var item = this.client.getItem(index);  if (item.isImage)  {    this.htmlItemLayer.hide();    this.loadingLayer.show();    var url = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + this.client.longName + "/" + item.url;    // init image with a reference image that has been loaded previously, and is thus available immediately    this.itemImage.src = this.referenceImage.src;    // now start loading the requested image    this.itemImage.src = url;    LOG.debug("Image to load size: " + this.itemImage.offsetWidth + "x" + this.itemImage.offsetHeight);    this.measuringTimer.start(this.LOAD_CHECK_TIME, this.centerItem, null, this);  }  else  {    var url = Portfolio.prototype.PORTFOLIO_CONTENT_PATH + item.url;    this.htmlItemLayer.htmlElement.src = url;    this.loadingLayer.hide();    this.htmlItemLayer.show();  }}// Description     : determine whether the current item is the first one// Parameters      : none// Returns         : true if the current item is the first oneItemSelector.prototype.isFirst = function (){  return this.currentItemIndex == 0;}// Description     : determine whether the current item is the last one// Parameters      : none// Returns         : true if the current item is the last oneItemSelector.prototype.isLast = function (){  return this.currentItemIndex == this.client.items.length - 1;}// Description     : select the previous item, if available// Parameters      : index of the item// Returns         : voidItemSelector.prototype.previous = function (index){  if (!this.isFirst())    this.showItem(this.currentItemIndex - 1);}// Description     : select the next item, if available// Parameters      : none// Returns         : voidItemSelector.prototype.next = function (){  if (!this.isLast())    this.showItem(this.currentItemIndex + 1);}// Description     : hide the item selector// Parameters      : none// Returns         : voidItemSelector.prototype.hide = function (){  this.selectorLayer.hide();  for (var i = 0; i < this.MAX_NUM_SELECTOR_KNOBS; i++)    this.selectorKnobs[i].hide();}// Description     : initialise the selector for a certain client/project// Parameters      : a PortFolioClient// Returns         : voidItemSelector.prototype.prepareForClient = function (client){  this.client = client;  this.showItem(0);  var numItems = this.client.items.length;  if (numItems == 1)    this.hide();  else  {    for (var i = 0; i < numItems; i++)      this.selectorKnobs[i].show();    for (var i = numItems; i < this.MAX_NUM_SELECTOR_KNOBS; i++)      this.selectorKnobs[i].hide();    this.selectorLayer.show();  }}/*  Description     : constructor; this class is responsible for handling 1 item of 1 client in the Portfolio  Parameters      : the url of the image or html page for this item  Properties      : url: the url of the image or html for this item                    description: the description of the item*/function PortfolioItem (url){  this.isImage = (url.substring(url.length - 3) != "htm");  this.url = url;  this.description = "";}/*  Description     : constructor; this class is responsible for handling a single Portfolio client/project  Parameters      : client long and short name; these names are used to find images that conform to the naming convention:            <Portfolio-image-path> <longName> / <shortName> <image type>  Properties:    longName    shortName    items: list of PortFolioItems    labelRollover    labelSelected    labelRolloverImage    labelSelectedImage    description*/function PortfolioClient (longName, shortName){  this.longName = longName;  this.shortName = shortName;  this.items = new Array();  this.labelRollover = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + this.longName + "/" + this.shortName + this.ROLLOVER_SUFFIX;  this.labelSelected = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + this.longName + "/" + this.shortName + this.SELECTED_SUFFIX;  this.description = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + this.longName + "/" + this.shortName + this.DESCRIPTION_SUFFIX;  this.labelRolloverImage = new Image();  this.labelSelectedImage = new Image();}PortfolioClient.prototype.ROLLOVER_SUFFIX = ".tekst.roll.gif";PortfolioClient.prototype.SELECTED_SUFFIX = ".tekst.sel.gif";PortfolioClient.prototype.DESCRIPTION_SUFFIX = ".content.gif";// Description     : add a PortfolioItem to the client// Parameters      : the PortfolioItem// Returns         : voidPortfolioClient.prototype.add = function (item){  this.items.push(item);}// Description     : get the PortfolioItem with index i// Parameters      : index// Returns         : the PortfolioItemPortfolioClient.prototype.getItem = function (i){  return this.items[i];}// Description     : preload the rollover and selected text label images// Parameters      : none// Returns         : voidPortfolioClient.prototype.preloadLabelImages = function (){  this.labelRolloverImage.src = this.labelRollover;  this.labelSelectedImage.src = this.labelSelected;  LOG.debug("Label images loaded for: " + this.longName);}/*  Description     : constructor; this class is responsible for the highlight and rollover effects of the Portfolio overview            the thumbnail positions are constructed from hard coded data  Parameters      : none  Properties      :    thumbnailRolloverLayer    thumbnailLabelRolloverLayer    thumbnailLabelRolloverImage    thumbnailSelectedLayer    thumbnailLabelSelectedLayer    thumbnailLabelSelectedImage    clientIndex: associative array of the order number (index) of each client    selectedClient: index of the selected client (-1: no client selected)    thumbnailPositions    thumbnailLabelPositions*/function PortfolioHighlight (){  this.thumbnailRolloverLayer = new Layer("clientHighlight"); // border:2px solid #947361; background-color:Transparent; visibility: hidden;  this.thumbnailLabelRolloverLayer = new Layer("clientLabelHighlight"); // background-color:Transparent; visibility: hidden;  this.thumbnailLabelRolloverImage = document.getElementById("imgClientLabelHighlight");  this.thumbnailSelectedLayer = new Layer("clientSelected"); // border:1px solid #DC1070; background-color:Transparent; visibility: hidden;  this.thumbnailLabelSelectedLayer = new Layer("clientLabelSelected"); // background-color:Transparent; visibility: hidden;  this.thumbnailLabelSelectedImage = document.getElementById("imgClientLabelSelected");  this.thumbnailPositions = [new Point(155, 1), new Point(155, 50), new Point(155, 99), new Point(155, 148), new Point(155, 197),                             new Point(155, 246), new Point(155, 295), new Point(155, 344), new Point(155, 393), new Point(155, 442),                             new Point(155, 491)  ];  this.thumbnailLabelPositions = new Array();  // Rollover ThumbnailLabel are at thumbnailPos + (-122, +4)  for (var i = 0; i < this.thumbnailPositions.length; i++)    this.thumbnailLabelPositions[i] = this.thumbnailPositions[i].createTranslatedPoint(-122, 4);  this.selectedClient = -1;  // TODO send bug report: change cursor style doesn't work in Mozilla if an image map is over the image where the cursor should have a changed shape!}// Description     : hide rollover components// Parameters      : none// Returns         : voidPortfolioHighlight.prototype.clearRollover = function (){  this.thumbnailRolloverLayer.hide();  this.thumbnailLabelRolloverLayer.hide();}// Description     : hide selection components// Parameters      : none// Returns         : voidPortfolioHighlight.prototype.clearSelection = function (){  this.selectedClient = -1;  this.thumbnailSelectedLayer.hide();  this.thumbnailLabelSelectedLayer.hide();}// Description     : preload dummy image to prevent stretching of image that will be loaded next//                   (helper function in case of Safari browser)// Parameters      : image object to prepare// Returns         : voidfunction prepareForSafari (img){  if (environment.isSafari)  {    img.src = ItemSelector.prototype.REFERENCE_IMAGE;  }}// Description     : show client selected// Parameters      : a client// Returns         : voidPortfolioHighlight.prototype.select = function (client){  prepareForSafari(this.thumbnailLabelSelectedImage);  this.thumbnailLabelSelectedImage.src = client.labelSelected;  var clientIndex = this.clientIndex[client.longName];  this.selectedClient = clientIndex;  var x = this.thumbnailPositions[clientIndex].x;  var y = this.thumbnailPositions[clientIndex].y;  this.thumbnailSelectedLayer.moveTo(x, y);  x = this.thumbnailLabelPositions[clientIndex].x;  y = this.thumbnailLabelPositions[clientIndex].y;  this.thumbnailLabelSelectedLayer.moveTo(x, y);  // set event handlers to the same values as the corresponding image map area, for consistent behaviour  var doOnClick = new Function("portfolio.selectClient(\"" + client.longName + "\");");  this.thumbnailSelectedLayer.htmlElement.onclick = doOnClick;  this.thumbnailLabelSelectedLayer.htmlElement.onclick = doOnClick;  this.thumbnailSelectedLayer.show();  this.thumbnailLabelSelectedLayer.show();  this.clearRollover();}// Description     : highlight a client// Parameters      : a client// Returns         : voidPortfolioHighlight.prototype.highlight = function (client){  LOG.debug(client.longName + ": " + client.labelRollover);  var clientIndex = this.clientIndex[client.longName];  if (clientIndex != this.selectedClient)  {    prepareForSafari(this.thumbnailLabelRolloverImage);    this.thumbnailLabelRolloverImage.src = client.labelRollover;    var x = this.thumbnailPositions[clientIndex].x;    var y = this.thumbnailPositions[clientIndex].y;    // Rollover is at thumbnailPos + (-1, -1)    this.thumbnailRolloverLayer.moveTo(x - 1, y - 1);    x = this.thumbnailLabelPositions[clientIndex].x;    y = this.thumbnailLabelPositions[clientIndex].y;    this.thumbnailLabelRolloverLayer.moveTo(x, y);    // set event handlers to the same values as the corresponding image map area, for consistent behaviour    var doOnClick = new Function("portfolio.selectClient(\"" + client.longName + "\");");    var doMouseOver = new Function("portfolio.highlightClient(\"" + client.longName + "\");");    var doMouseOut = new Function("portfolio.highlight.clearRollover();");    this.thumbnailRolloverLayer.htmlElement.onclick = doOnClick;    this.thumbnailRolloverLayer.htmlElement.onmouseover = doMouseOver;    this.thumbnailRolloverLayer.htmlElement.onmouseout = doMouseOut;    this.thumbnailLabelRolloverLayer.htmlElement.onclick = doOnClick;    this.thumbnailLabelRolloverLayer.htmlElement.onmouseover = doMouseOver;    this.thumbnailLabelRolloverLayer.htmlElement.onmouseout = doMouseOut;    this.thumbnailRolloverLayer.show();    this.thumbnailLabelRolloverLayer.show();  }}/*  Description     : constructor; this class is responsible for handling a complete client/project portfolio  Parameters      : none  Properties      :    clients: list of PortfolioClients    menuItems: list of menu item clients    highlight: PortfolioHighlight object    currentClient: reference to the current PortfolioClient object    clientNames: array of client names in the portfolio    descriptionImage: image showing the current client description    descriptionLayer: layer containing the description image*/function Portfolio (){  this.build();  this.initMenu();  this.highlight = new PortfolioHighlight();  this.itemSelector = new ItemSelector();  this.descriptionImage = document.getElementById(this.DESCRIPTION_IMAGE_ID);  this.descriptionLayer = new Layer(this.DESCRIPTION_LAYER_ID);  this.clearHighlight();  this.initPortfolioOverview();}Portfolio.prototype.PORTFOLIO_IMAGE_PATH = "images/Portfolio/";Portfolio.prototype.PORTFOLIO_CONTENT_PATH = "content/"Portfolio.prototype.PORTFOLIO_AREA_PREFIX = "areaClient";Portfolio.prototype.DESCRIPTION_LAYER_ID = "TekstOnderContentvlak";Portfolio.prototype.DESCRIPTION_IMAGE_ID = "imgPortfolioClientText";// Description     : initialise image map areas of Portfolio overview from hardcoded data// Parameters      : none// Returns         : voidPortfolio.prototype.initPortfolioOverview = function (){  this.clientNames = [    "WSP",	"RVD",	"C-Logic",    "GateFoundation",    "NN",    "Thion",    "Ontwerpfontein",	"NVFD",	"Tekstpraktijk",    "BalletstudioSylvia",    "SpruitAdvies"  ]  this.highlight.clientIndex = new Array();  for (var i = 0; i < this.clientNames.length; i++)    this.highlight.clientIndex[this.clientNames[i]] = i;  var areas = document.getElementsByTagName("AREA");  for (var i = 0; i < areas.length; i++)  {    if (areas[i].id.substr(0, this.PORTFOLIO_AREA_PREFIX.length) == this.PORTFOLIO_AREA_PREFIX)    {      var clientArea = areas[i];      var index = parseInt(areas[i].id.substr(this.PORTFOLIO_AREA_PREFIX.length));      LOG.debug("Client area " + index + " found, assigning to: " + this.clientNames[index]);      clientArea.href = "javascript:portfolio.selectClient(\"" + this.clientNames[index] + "\");";      clientArea.onmouseover = new Function("portfolio.highlightClient(\"" + this.clientNames[index] + "\");");      clientArea.onmouseout = new Function("portfolio.highlight.clearRollover();");    }  }}// Description     : clears any client highlight and client selection// Parameters      : none// Returns         : voidPortfolio.prototype.clearHighlight = function (){  this.highlight.clearRollover();  this.highlight.clearSelection();}// Description     : highlight a client thumbnail area// Parameters      : client name// Returns         : voidPortfolio.prototype.highlightClient = function (clientName){  this.highlight.highlight(this.clients[clientName]);}// Description     : select a portfolio client// Parameters      : client name// Returns         : voidPortfolio.prototype.selectClient = function (clientName){  this.clearMenuItems();  this.currentClient = this.clients[clientName];  this.highlight.select(this.currentClient);  this.descriptionImage.src = this.currentClient.description;  this.descriptionLayer.show();  this.itemSelector.prepareForClient(this.currentClient);}// Description     : select a portfolio client// Parameters      : none// Returns         : voidPortfolio.prototype.clearClientDescription = function (clientIndex){  this.itemSelector.hide();  this.descriptionLayer.hide();}// Description     : sets all menu items to their initial settings// Parameters      : none// Returns         : void// Remark          : private functionPortfolio.prototype.clearMenuItems = function (){  for (var itemName in this.menuItems)  {    var item = this.menuItems[itemName];    item.isSelected = false;    if (item.buttonImage.restore)      item.buttonImage.restore();    item.buttonImage.onmouseover = item.onmouseover;    item.buttonImage.onmouseout = item.onmouseout;    item.buttonImage.onclick = item.onclick;    item.buttonImage.style.cursor = "pointer";    // hide animations    for (var animationIndex = 0; animationIndex < item.animations.length; animationIndex++)    {      item.animations[animationIndex].hide();    }  }}// Description     : select a menu item// Parameters      : the name of the menu item// Returns         : voidPortfolio.prototype.selectMenuItem = function (itemName){  var item = this.menuItems[itemName];  if (!item.isSelected)  {    this.currentClient = item;    this.clearClientDescription();    this.itemSelector.prepareForClient(this.currentClient);    this.clearHighlight();    this.clearMenuItems();    item.isSelected = true;    imagesObject.swap(item.buttonImage.id, item.buttonImage.selectedUrl);    item.buttonImage.src = item.buttonImage.selectedUrl;    item.buttonImage.onmouseover = null;    item.buttonImage.onmouseout = null;    item.buttonImage.onclick = null;    item.buttonImage.style.cursor = "default";    // show corresponding animations    for (var i = 0; i < item.animations.length; i++)    {      var animation = item.animations[i];      animation.show();      animation.animationImage.src = animation.animationImageSrc;    }  }}// Description     : initialise the menu items from hardcoded values// Parameters      : none// Returns         : void// Remarks         : new properties are added specific for menu items only://                     buttonImage: The menu button image//                     onmouseover: the associated mouseover handler//                     onmouseout: the associated onmouseout handler//                     onclick: the associated onclick handler//                     animations: array of associated animationsPortfolio.prototype.initMenu = function (){  var doRestore = new Function("this.restore();");  for (var itemName in this.menuItems)  {    var item = this.menuItems[itemName];    item.buttonImage = document.getElementById("img" + itemName);    item.buttonImage.selectedUrl = "images/" + itemName + ".selected.gif";    item.onmouseover = new Function("imagesObject.swap(this.id, 'images/" + itemName + ".rollover.gif');");    item.onmouseout = doRestore;    item.onclick = new Function("doMenuItem('" + itemName + "');");  }  // init animations  var animation1a = new Layer("WatVoorWieAnimation1a");  animation1a.animationImage = document.getElementById("imgAnimation1a");  animation1a.animationImageSrc = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + "OntwerpfonteinInfo/Animation.1a.gif";  var animation1b = new Layer("WatVoorWieAnimation1b");  animation1b.animationImage = document.getElementById("imgAnimation1b");  animation1b.animationImageSrc = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + "OntwerpfonteinInfo/Animation.1b.gif";  var animation2a = new Layer("HoeContactAnimation2a");  animation2a.animationImage = document.getElementById("imgAnimation2a");  animation2a.animationImageSrc = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + "OntwerpfonteinInfo/Animation.2a.gif";  var animation2b = new Layer("HoeContactAnimation2b");  animation2b.animationImage = document.getElementById("imgAnimation2b");  animation2b.animationImageSrc = Portfolio.prototype.PORTFOLIO_IMAGE_PATH + "OntwerpfonteinInfo/Animation.2b.gif";  this.menuItems["Wat"].animations = [animation1a, animation1b];  this.menuItems["Hoe"].animations = [animation2a, animation2b];  this.menuItems["VoorWie"].animations = [animation1a, animation1b];  this.menuItems["Referenties"].animations = [animation2a, animation2b];  this.menuItems["FAQ"].animations = [animation1a, animation1b];  this.menuItems["Contact"].animations = [animation2a, animation2b];  LOG.info("Menu items initialised");}// Description     : creates the Ontwerpfontein Portfolio from hardcoded data// Parameters      : none// Returns         : voidPortfolio.prototype.build = function (){  this.clients = new Array();  // BalletstudioSylvia Syl  10  jpg  var client = new PortfolioClient("BalletstudioSylvia", "Syl");  client.add(new PortfolioItem("Syl.1.jpg"));  client.add(new PortfolioItem("Syl.2.jpg"));  client.add(new PortfolioItem("Syl.3.jpg"));  client.add(new PortfolioItem("Syl.4.jpg"));  client.add(new PortfolioItem("Syl.5.jpg"));  client.add(new PortfolioItem("Syl.6.jpg"));  client.add(new PortfolioItem("Syl.7.jpg"));  client.add(new PortfolioItem("Syl.8.jpg"));  client.add(new PortfolioItem("Syl.9.jpg"));  client.add(new PortfolioItem("Syl.10.jpg"));  this.clients[client.longName] = client;  // C-Logic CLogic  10  gif  client = new PortfolioClient("C-Logic", "CLogic");  client.add(new PortfolioItem("CLogic.1.gif"));  client.add(new PortfolioItem("CLogic.2.gif"));  client.add(new PortfolioItem("CLogic.3.gif"));  client.add(new PortfolioItem("CLogic.4.gif"));  client.add(new PortfolioItem("CLogic.5.gif"));  client.add(new PortfolioItem("CLogic.6.gif"));  client.add(new PortfolioItem("CLogic.7.gif"));  client.add(new PortfolioItem("CLogic.8.gif"));  client.add(new PortfolioItem("CLogic.9.gif"));  client.add(new PortfolioItem("CLogic.10.gif"));  this.clients[client.longName] = client;  // GateFoundation Gate  13  gif; 5 png  client = new PortfolioClient("GateFoundation", "Gate");  client.add(new PortfolioItem("Gate.1.gif"));  client.add(new PortfolioItem("Gate.2.gif"));  client.add(new PortfolioItem("Gate.3.gif"));  client.add(new PortfolioItem("Gate.4.gif"));  client.add(new PortfolioItem("Gate.5.png"));  client.add(new PortfolioItem("Gate.6.gif"));  client.add(new PortfolioItem("Gate.7.gif"));  client.add(new PortfolioItem("Gate.8.gif"));  client.add(new PortfolioItem("Gate.9.gif"));  client.add(new PortfolioItem("Gate.10.gif"));  client.add(new PortfolioItem("Gate.11.gif"));  client.add(new PortfolioItem("Gate.12.gif"));  client.add(new PortfolioItem("Gate.13.gif"));  this.clients[client.longName] = client;  // WSP  8  gif  client = new PortfolioClient("WSP", "WSP");  client.add(new PortfolioItem("WSP.1.gif"));  client.add(new PortfolioItem("WSP.2.gif"));  client.add(new PortfolioItem("WSP.3.gif"));  client.add(new PortfolioItem("WSP.4.gif"));  client.add(new PortfolioItem("WSP.5.gif"));  client.add(new PortfolioItem("WSP.6.gif"));  client.add(new PortfolioItem("WSP.7.gif"));  client.add(new PortfolioItem("WSP.8.gif"));  this.clients[client.longName] = client;  // NN   9   gif  client = new PortfolioClient("NN", "NN");  client.add(new PortfolioItem("NN.1.gif"));  client.add(new PortfolioItem("NN.2.gif"));  client.add(new PortfolioItem("NN.3.gif"));  client.add(new PortfolioItem("NN.4.gif"));  client.add(new PortfolioItem("NN.5.gif"));  client.add(new PortfolioItem("NN.6.gif"));  client.add(new PortfolioItem("NN.7.gif"));  client.add(new PortfolioItem("NN.8.gif"));  client.add(new PortfolioItem("NN.9.gif"));  this.clients[client.longName] = client;  // Ontwerpfontein OntwF 10  1-6 gif; 7-10 png  client = new PortfolioClient("Ontwerpfontein", "OntwF");  client.add(new PortfolioItem("OntwF.1.gif"));  client.add(new PortfolioItem("OntwF.2.gif"));  client.add(new PortfolioItem("OntwF.3.gif"));  client.add(new PortfolioItem("OntwF.4.gif"));  client.add(new PortfolioItem("OntwF.5.gif"));  client.add(new PortfolioItem("OntwF.6.gif"));  client.add(new PortfolioItem("OntwF.7.png"));  client.add(new PortfolioItem("OntwF.8.png"));  client.add(new PortfolioItem("OntwF.9.png"));  client.add(new PortfolioItem("OntwF.10.png"));  this.clients[client.longName] = client;  // Handle menu items in a separate client list  this.menuItems = new Array();  // Wat  1  gif  client = new PortfolioClient("OntwerpfonteinInfo", "Wat");  client.add(new PortfolioItem("Wat.content.gif"));  this.menuItems[client.shortName] = client;  // Hoe  1  gif  client = new PortfolioClient("OntwerpfonteinInfo", "Hoe");  client.add(new PortfolioItem("Hoe.content.gif"));  this.menuItems[client.shortName] = client;  // VoorWie  1  gif  client = new PortfolioClient("OntwerpfonteinInfo", "VoorWie");  client.add(new PortfolioItem("VoorWie.htm"));  this.menuItems[client.shortName] = client;  // Referenties  3  gif  client = new PortfolioClient("OntwerpfonteinInfo", "Referenties");  client.add(new PortfolioItem("Ref1.htm"));  client.add(new PortfolioItem("Ref2.htm"));  client.add(new PortfolioItem("Ref3.content.gif"));  this.menuItems[client.shortName] = client;  // FAQ  3  gif  client = new PortfolioClient("OntwerpfonteinInfo", "FAQ");  client.add(new PortfolioItem("FAQ1.htm"));  client.add(new PortfolioItem("FAQ2.htm"));  client.add(new PortfolioItem("FAQ3.content.gif"));  this.menuItems[client.shortName] = client;  // Contact  1  gif  client = new PortfolioClient("OntwerpfonteinInfo", "Contact");  client.add(new PortfolioItem("Contact.htm"));  this.menuItems[client.shortName] = client;  // SpruitAdvies Spruit  7  1-5 gif; 6-7 jpg  client = new PortfolioClient("SpruitAdvies", "Spruit");  client.add(new PortfolioItem("Spruit.1.gif"));  client.add(new PortfolioItem("Spruit.2.gif"));  client.add(new PortfolioItem("Spruit.3.gif"));  client.add(new PortfolioItem("Spruit.4.gif"));  client.add(new PortfolioItem("Spruit.5.gif"));  client.add(new PortfolioItem("Spruit.6.jpg"));  client.add(new PortfolioItem("Spruit.7.jpg"));  this.clients[client.longName] = client;  // Tekstpraktijk Tekstpr    11  gif  client = new PortfolioClient("Tekstpraktijk", "Tekstpr");  client.add(new PortfolioItem("Tekstpr.1.gif"));  client.add(new PortfolioItem("Tekstpr.2.gif"));  client.add(new PortfolioItem("Tekstpr.3.gif"));  client.add(new PortfolioItem("Tekstpr.4.gif"));  client.add(new PortfolioItem("Tekstpr.5.gif"));  client.add(new PortfolioItem("Tekstpr.6.gif"));  client.add(new PortfolioItem("Tekstpr.7.gif"));  client.add(new PortfolioItem("Tekstpr.8.gif"));  client.add(new PortfolioItem("Tekstpr.9.gif"));  client.add(new PortfolioItem("Tekstpr.10.gif"));  client.add(new PortfolioItem("Tekstpr.11.gif"));  this.clients[client.longName] = client;  // Thion Thion  7  gif  client = new PortfolioClient("Thion", "Thion");  client.add(new PortfolioItem("Thion.1.gif"));  client.add(new PortfolioItem("Thion.2.gif"));  client.add(new PortfolioItem("Thion.3.gif"));  client.add(new PortfolioItem("Thion.4.gif"));  client.add(new PortfolioItem("Thion.5.gif"));  client.add(new PortfolioItem("Thion.6.gif"));  client.add(new PortfolioItem("Thion.7.gif"));  this.clients[client.longName] = client;  // RVD   2   gif  client = new PortfolioClient("RVD", "RVD");  client.add(new PortfolioItem("RVD.1.gif"));  client.add(new PortfolioItem("RVD.2.gif"));  this.clients[client.longName] = client;  // NVFD  8   gif  client = new PortfolioClient("NVFD", "NVFD");  client.add(new PortfolioItem("NVFD.1.gif"));  client.add(new PortfolioItem("NVFD.2.gif"));  client.add(new PortfolioItem("NVFD.3.gif"));  client.add(new PortfolioItem("NVFD.4.gif"));  client.add(new PortfolioItem("NVFD.5.gif"));  client.add(new PortfolioItem("NVFD.6.gif"));  client.add(new PortfolioItem("NVFD.7.gif"));  client.add(new PortfolioItem("NVFD.8.gif"));  this.clients[client.longName] = client;}function preloadOntwerpfonteinImages(){  imagesObject.preload(    "images/Wat.rollover.gif",    "images/Wat.selected.gif",    "images/Hoe.rollover.gif",    "images/Hoe.selected.gif",    "images/Voorwie.rollover.gif",    "images/Voorwie.selected.gif",    "images/Referenties.rollover.gif",    "images/Referenties.selected.gif",    "images/FAQ.rollover.gif",    "images/FAQ.selected.gif",    "images/Contact.rollover.gif",    "images/Contact.selected.gif");  LOG.info("Ontwerpfontein images loaded");}function preloadPortfolioClientLabels (){  for (var client in portfolio.clients)    portfolio.clients[client].preloadLabelImages();}function doMenuItem (itemName){  portfolio.selectMenuItem(itemName);}function selectFirstClient (){  portfolio.selectClient(portfolio.clientNames[0]);  portfolioScrollbar.jumpTo(null, 0);}/*  Description     : constructor; this class is responsible for storing information about the browser environment  Parameters      : none  Properties      :    platform    browser    version*/function Environment (){/*  - INFO: --platform: MacPPC (string)  - INFO: --platform: Win32 (string)  Internet Explorer 5.2:  --userAgent: Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC) (string)  Safari:  --userAgent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; nl-nl) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312 (string)  Firefox:  --userAgent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6 (string)  Netscape:  --userAgent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (string)  Internet Explorer 6.0:  --userAgent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322) (string)  Firefox PC:  --userAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 (string)*/  var userAgent = navigator.userAgent;  var browserCodePos;  var startOfVersionPos;  this.isSupported = true;  this.platform = navigator.platform;  if ((browserCodePos = userAgent.search(/MSIE/)) != -1)  {    this.browser = "Internet Explorer";    startOfVersionPos = browserCodePos + 5;    var endOfVersionPos = userAgent.indexOf(";", startOfVersionPos);    // format of version: n.n[n]    this.version = userAgent.substring(startOfVersionPos, endOfVersionPos);  }  else if ((browserCodePos = userAgent.search(/Firefox/)) != -1)  {    this.browser = "Firefox";    startOfVersionPos = browserCodePos + 8;    // format of version: n.n.n    this.version = userAgent.substring(startOfVersionPos);  }  else if ((browserCodePos = userAgent.search(/Netscape/)) != -1)  {    this.browser = "Netscape";    startOfVersionPos = browserCodePos + 9;    // format of version: n.n[.n]    this.version = userAgent.substring(startOfVersionPos);  }  else if ((browserCodePos = userAgent.search(/Safari/)) != -1)  {    this.browser = "Safari";    startOfVersionPos = browserCodePos + 7;    // format of version: nnn    this.version = userAgent.substring(startOfVersionPos);  }  else  {    this.browser = "Other Browser";    this.version = "";  }  this.isInternetExplorer = (this.browser == "Internet Explorer");  this.isFirefox = (this.browser == "Firefox");  this.isNetscape = (this.browser == "Netscape");  this.isSafari = (this.browser == "Safari");  this.isSupported &= !(this.isInternetExplorer && this.platform == "MacPPC");  LOG.note(this.platform + "; " + this.browser + " " + this.version + ": " + (this.isSupported ? "" : "not ") + "supported");}// Description     : show message (or at least try to show) that the current environment is not supported// Parameters      : none// Returns         : voidEnvironment.prototype.doUnsupported = function (){  document.open();  document.write("<html>");  document.write("<head>");  document.write("<title>Ontwerpfontein: Browser wordt niet ondersteund</title>");  document.write("</head>");  document.write("<body>");  document.body.style.fontFamily = "Arial, Helvetica, sans-serif";  document.body.style.fontSize = "16pt";  document.body.style.color = "#DC1070";  document.write("Deze site werkt niet goed met uw huidige web browser.<br>");  document.write("<br>");  document.write("Gebruik alstublieft Firefox of Internet Explorer 5.5 of hoger als u Microsoft Windows of Linux gebruikt;<br>");  document.write("of Safari of Firefox als u een Macintosh gebruikt.<br>");  document.write("</body>");  document.write("</html>");  document.close();}// Description     : do specific things for specific environments// Parameters      : none// Returns         : voidEnvironment.prototype.doSpecifics = function (){  if (this.isInternetExplorer && parseFloat(this.version) >= 6)  {    LOG.info("Do special things for Internet Explorer 6 and higher");    // hide browser window scrollbars    // this must be done in script, otherwise Safari on the Mac wouldn't work!    var htmlElement = document.getElementsByTagName("HTML")[0];    htmlElement.style.overflow = "hidden";  }}// preload images, set content data, portfolio links, selection dots and content areafunction initialisePage (){  LOG.clear();  environment = new Environment();  environment.doSpecifics();  imagesObject = new Images(document);  preloadOntwerpfonteinImages();  // Activate content centering script  mainLayer = new FloatingLayer(new Layer("BackgroundAll"), document.getElementById("BackgroundSizeMeasurer"));  mainLayer.setMinimumMargins(53, 27, 0, 27);  mainLayer.setMaximumMargins(53);  mainLayer.place();  window.onresize = new Function("mainLayer.place();");  // Portfolio is loaded only once, since there is only 1 page.  portfolio = new Portfolio();  var portfolioOverview = new ScrollableLayer("PortfolioOverzicht", 1, 153, 232, 295);  portfolioScrollbar = new Scrollbar("PortfolioScrollbar", true, portfolioOverview);  ticker = new Ticker("Ticker");  ticker.start();  // add these event handlers by JavaScript, to prevent script errors when the page has not fully loaded yet  var areaUp = document.getElementById("imgArrowUp");  var areaDown = document.getElementById("imgArrowDown");  areaUp.onmousedown = new Function("e", "if (e && e.preventDefault) e.preventDefault(); portfolioScrollbar.up();");  areaDown.onmousedown = new Function("e", "if (e && e.preventDefault) e.preventDefault(); portfolioScrollbar.down();");  var stopScrolling = new Function("portfolioScrollbar.stop();");  areaUp.onmouseup = stopScrolling;  areaDown.onmouseup = stopScrolling;  areaUp.onmouseout = stopScrolling;  areaDown.onmouseout = stopScrolling;  doMenuItem("Wat");  // preload these last, to prevent initial heavy download  preloadPortfolioClientLabels();}