Monday, March 5, 2007

Blending and rotating images using Javascript

I recently can across this interesting website that shows how you can create cross browser fading effects for images. However, I needed to rotate a number of images displayed in addition to the blending effects. Furthermore, I wanted to have 2 or more sets of rotating images in the same page if possible. So I decided to enhance the javascript provided in the above website. There are 3 steps. Firstly, create a html page and include the js.file called, "rotatingImages.js" as below.


<HEAD>
<SCRIPT language="JavaScript" src="rotatingImages.js" type="text/javascript"></SCRIPT>
<TITLE>Test page</TITLE>
</HEAD>


Then include the following DIV tag, A tag and IMG tag in the body of the html file. Although not very elegant, you will have to declare two javascript arrays to store the hyperlinks (when users click on the image) and the tooltips (when users moveover the image). This is necessary if we want to display more than one set of rotating images in a html page.


<div id="rotatingImagesDiv" style="background-repeat: no-repeat;" >
  <a id="linkbanner">
    <img id="rotatingImages" src="http://www.abc.com/images/0.jpg"
    border="0" hspace="0"
    onload="var urls = new Array();
    urls[0]='http://www.0.com';
    urls[1]='http://www.1.com';
    urls[2]='http://www.2.com';
    urls[3]='http://www.3.com';
    urls[4]='http://www.4.com';
    urls[5]='http://www.5.com';
    urls[6]='http://www.6.com';

    var toolTips = new Array();
    toolTips[0]='0 image';
    toolTips[1]='1 image';
    toolTips[2]='2 image';
    toolTips[3]='3 image';
    toolTips[4]='4 image';
    toolTips[5]='5 image';
    toolTips[6]='6 image';

    initImagesRotation('http','www.abc.com/images/',7,urls,toolTips,'rotatingImagesDiv','linkbanner','rotatingImages',10000,2000)" />
  </a>
</div>

<div id="rotatingImagesDiv1" style="background-repeat: no-repeat;">
  <a id="linkbanner1">
    <img id="rotatingImages1" src="http://www.abc.com/images/0.jpg"
    border="0" hspace="0"      
    onload="urls = new Array();
    urls[0]='http://www.one.com';
    urls[1]='http://www.two.com';
    urls[2]='http://www.three.com';
    urls[3]='http://www.four.com';
    urls[4]='http://www.five.com';
    urls[5]='http://www.six.com';
    urls[6]='http://www.seven.com';

    toolTips= new Array();
    toolTips[0]='zero image';
    toolTips[1]='one image';
    toolTips[2]='two image';
    toolTips[3]='three image';
    toolTips[4]='four image';
    toolTips[5]='five image';
    toolTips[6]='six image';

    initImagesRotation('http','www.abc.com/images/',7,urls,toolTips,'rotatingImagesDiv1','linkbanner1','rotatingImages1',5000,1000)" />
  </a>
</div>


Lastly, create the javascript file, "rotatingImages.js" to make it all work. Then enjoy!


function changeOpac(opacity, id) {

  var object = document.getElementById(id).style;
  object.opacity = (opacity / 100);
  object.MozOpacity = (opacity / 100);
  object.KhtmlOpacity = (opacity / 100);
  object.filter = "alpha(opacity=" + opacity + ")";

}

function RotateImageClass(){

  var counter = 1;
  var toggleFlag = false;
  var imageFiles = new Array();
  var timeoutHandler, timer, speed;

  var self = this;

  function fade(clsid, id, speed, opacStart, opacEnd) {

    var percentChange = Math.abs( (opacStart - opacEnd) );
    speed = Math.round( (speed / 100) );

    //determine the direction for the blending, if start and end are the same nothing happens

    var timer = 0, ct;
    if(opacStart > opacEnd) {

      opacEnd -= 1;
      for(ct = opacStart; ct> opacEnd; ct--)
      {
        setTimeout("changeOpac(" + ct + ",'" + id + "')",(speed*timer));
        timer++;
      }

    } else if(opacStart < opacEnd) {

      opacEnd += 1;
      for(ct = opacStart; ct < opacEnd; ct++)
      {
        setTimeout("changeOpac(" + ct + ",'" + id + "')",(speed*timer));
        timer++;
      }
    }
  }

  this.Init = function() {

    timer = parseInt(this.Duration);
    speed = parseInt(this.FadingSpeed);
    if( speed < 100 )
      speed = 100; //Pointless if set too low.

    // Need to do this because IE 7 choke when function parameters contains 'http://'!
    var prefix = "";

    if( this.ProtocolType.indexOf("http",0) > -1 ){
      prefix = 'http://';
    }
    else if( this.ProtocolType.indexOf("file",0) > -1 ){
      prefix = 'file:///';
    }

    for( var i=0; i<this.ImageQuantity; i++ ){
      imageFiles[i] = prefix + this.ImageLocation + i + '.jpg';
    }
  }

  this.GetImage = function(index) { return imageFiles[index]; }

  this.Rotate = function(){

    if( counter < this.ImageQuantity ){
      // do nothing
    }
    else{
      counter = 0;
    }

    // Set tool tips
    setTimeout("document.getElementById('" + this.ImageId + "').title='"
      + this.ToolTipArray[counter] + "'",this.Duration);

    // Set the hyperlink
    setTimeout("document.getElementById('" + this.LinkId + "').href='"
      + this.UrlArray[counter] + "'",this.Duration);

    if( toggleFlag ) {

      fade(this.ImageId,this.ImageId,speed,0,100);
      // Set the DIV background image when it is totally faded
      setTimeout("document.getElementById('" + this.DivId + "').style.backgroundImage='url("
      + imageFiles[counter] + ")'",this.Duration);
    }
    else{
      fade(this.ImageId,this.ImageId,speed,100,0);
      // Set image source when it is totally faded
      setTimeout("document.getElementById('" + this.ImageId + "').src='"
        + imageFiles[counter] + "'",this.Duration);
    }

    timeoutHandler = setTimeout("rotateImageInstances['" + this.ImageId + "'].Rotate()",timer);
    counter++;

    toggleFlag = !toggleFlag;
  }
}

var rotateImageInstances = new Array();

function initImagesRotation(protocolType, imageLocation, numberOfImages, urlArray, toolTipArray, divId, linkId, imageId, duration, fadingSpeed)
{
  // Sanity check
  if( fadingSpeed > duration )
  {
    // Huh?
  }
  else if( numberOfImages<2 ){
    // Huh?
  }
  else if( urlArray.length!=numberOfImages ){
    alert("The list of image URL do not match the number of images given.");
  }
  else if( toolTipArray.length!=numberOfImages){
    alert("The number of tooltips do not match the number of images given.");
  }
  else
  {
    if( typeof(rotateImageInstances[imageId])=="undefined" )
    {
      rotateImageInstances[imageId] = new RotateImageClass();
      rotateImageInstances[imageId].ProtocolType = protocolType;
      rotateImageInstances[imageId].ImageLocation = imageLocation;
      rotateImageInstances[imageId].ImageQuantity = numberOfImages;
      rotateImageInstances[imageId].UrlArray = urlArray;
      rotateImageInstances[imageId].ToolTipArray = toolTipArray;
      rotateImageInstances[imageId].DivId = divId;
      rotateImageInstances[imageId].LinkId = linkId;
      rotateImageInstances[imageId].ImageId = imageId;
      rotateImageInstances[imageId].Duration = duration;
      rotateImageInstances[imageId].FadingSpeed = fadingSpeed;
      rotateImageInstances[imageId].Init();

      document.getElementById(divId).style.backgroundImage = 'url(' + rotateImageInstances[imageId].GetImage(0) + ')';
      document.getElementById(imageId).src = rotateImageInstances[imageId].GetImage(0);

      rotateImageInstances[imageId].Rotate();
    }
  }
}

Roller v3.0 on WebLogic v9.2

After some tinkling, I managed to get Roller v3.0 running on WebLogic 9.2 as well. So here's the steps.


Preparation
1) Download source code for Roller v3.0.
2) Create a temp folder (we shall named it as {temp} from here onwards). Place downloaded source code in '{temp}\roller'.
3) Create a new Dynamic Web Project in WLP 9.2 named 'roller'. Use the default settings for Project Facets selection. Change 'Content Directory' to 'roller' (We will refer to the application directory as 'roller' from here onwards).
4) Rename '{roller}\roller\WEB-INF\web.xml' to '{roller}\roller\WEB-INF\web.bak'
5) Rename '{roller}\roller\index.jsp' to '{roller}\roller\index.bak'. (in case you want to keep it for later).
 
First compilation of roller
(The steps for compiling roller is still the same as before).
 

Setup WebLogic roller
1) Remove the additional filter added by XDoclet.

<filter>
<filter-name></filter-name>
<filter-class>org.apache.roller.ui.webapp.RollerAuthenticationProcessingFilter</filter-class>
</filter>


2) Copy '{roller}\roller\WEB-INF\classes\META-INF\tlds\roller.tld' to '{roller}\roller\WEB-INF'.
3) Open up '{roller}\roller\jsps\tiles\search.jsp', under line 37, change the special character '»' to '&raquo;'.
4) Amend '{roller}\roller\jsps\authoring\spellcheck-entry.jsp' and add the following.
  (Hint: Paste after the </script> tag.)
  <%!
  public static String makeSelect(String word, List words)
  {
    StringBuffer buf = new StringBuffer("<select name=\"");
    buf.append("replacementWords\"style=\"font-size: 10px;\">");
    buf.append("<option selected=\"selected\" value=\"").append(word);
    buf.append("\">").append(word).append("</option>");
    if (words == null || words.size() < 1)
    {
      buf.append("<option value=\"").append(word);
      buf.append("\">No Suggestions</option>");
    }
    else
    {
      for (Iterator it2=words.iterator(); it2.hasNext();)
      {
        word = it2.next().toString();
        buf.append("<option value=\"").append(word);
        buf.append("\">").append(word).append("</option>");
      }
    }
    buf.append("</select>");
    return buf.toString();
  }
  %>
 
  (Hint: Paste after the 'Use Spell Check Results' wordings.)
  <%
    String escapeText = StringUtils.replace( text, "<", "{" );
    escapeText = StringUtils.replace( escapeText, ">", "}" );
    StringBuffer newText = new StringBuffer(escapeText);
    ArrayList events = (ArrayList) session.getAttribute("spellCheckEvents");
    SpellCheckEvent event = null;
    String word = null;
    int start = -1;
    int end = -1;
    String select = null;
    for(ListIterator it=events.listIterator(events.size()); it.hasPrevious();)
    {
      event = (SpellCheckEvent)it.previous();
      word = event.getInvalidWord();
      start = event.getWordContextPosition();
      end = start + word.length();
      select = makeSelect(word, event.getSuggestions());
 
      newText.replace( start, end, select );
    }

    escapeText = StringUtils.replace(newText.toString(), "}", "&gt;" );
    escapeText = StringUtils.replace(escapeText, "{", "&lt;" );
  %>

5) Create the necessary datasource with JNDI name, jdbc/rollerdb" as well as the mail session with JNDI name mail/Session" in WebLogic console.

6) Amend the line, "${catalina.base}/logs/roller.log" in '{roller}\roller\WEB-INF\classes\log4j.properties' to the right place where you want your log to be.

7) Next we need to amend '{roller}\roller\WEB-INF\classes\hibernate.cfg.xml' with the following (See sample below, I'm using Oracle so modify for your DB).
 
  <!-- By default Roller uses a JNDI DataSource -->
  <property name="jndi.url">t3://localhost:7001</property>
  <property name="jndi.class">weblogic.jndi.WLInitialContextFactory</property>
  <property name="connection.datasource">jdbc/rollerdb</property>
  <property name="show_sql">false</property>

  <property name="current_session_context_class">thread</property>

  <!-- select SQL dialect, MySQL 3.X or 4.X by default -->
  <property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>

8) Comment off the line in web.xml as below:
 
  <!--<listener>
  <listener-class>org.apache.roller.ui.core.RollerContext</listener-class>
  </listener>-->

9) Modify '{temp}\roller\src\org\apache\roller\business\utils\UpgradeDatabase.java' at
line 190 if you are using Oracle like me.
 
  PreparedStatement websitesQuery = con.prepareStatement(
    "select w.id as wid, u.id as uuid, u.username as uname from "
    + "website w, rolleruser u where u.id=w.userid");

10) Change the context-root in '{roller}\roller\WEB-INF\weblogic.xml' to "roller" if it is not already so.
 
11) Deploy and enjoy.