jQuery easyThumb - A PHP / jQuery Thumbnail Generator with Lightbox

The first version of jQuery easyThumb was released today. easyThumb is a plugin that uses both jQuery and PHP to generate thumbnails (to use in galleries etc.) on-the-fly. All you need to do is to make a unsorted list of images. No links or thumbnails are required, the library takes care of this - thumbnails are created automatically and are linked to the full size image. This integrates well with the Lightbox library as is shown in the online demo.

From the author:

jQuery easyThumb is a plugin for jQuery. It turns a list of full-scale images to a list of thumbnails on-the-fly. It uses a php-script to return a thumbnail for each image, and jQuery to generate the list.

Online Demo with Lightbox

Check out the original post to read more about easyThumb and to download the source code.

Making the Most of Java 5.0: Enum Example

Tagged:  

"Hello World!" examples are great for general introductions to a concept, but often tend to lack much depth. So, as a follow-up to the original article on enums in Java 5.0, this article goes into a little more depth with a real-world example.

The Container Enum

Figure 1 below illustrates the enumeration of possible application servers to which an application can deploy. Why is this useful? Many organizations have more than one Java application server in different environments, and an EAR or WAR may need to be redeployed to different servers; or, you may be developing a common framework that will be used in different environments. It is often helpful in these situations to abstract many of the (static) variances between containers so that redeployment to a different environment can be done with a minimum of effort.

Figure 1: The Container enum.

public enum Container {
   WEBSPHERE, WEBLOGIC, JBOSS, NONE;
}

Now, let's say the application being designed requires an application-controlled JTA TransactionManager (if, for example, the standard way of doing XA transactions cannot be used). But how one is acquired varies pretty widely, depending on which environment the code is running. The variances here can be handled with an abstract method added to the enum, as in Figure 2.

Figure 2: The Container enum with factory methods.

public enum Container 
{
     WEBSPHERE() {
        private String[] factoryNames =
           {"com.ibm.ws.Transaction.TransactionManagerFactory",
            "com.ibm.ejs.jts.jta.TransactionManagerFactory",
            "com.ibm.ejs.jts.jta.JTSXA"};
        @Override
	public TransactionManager getTransactionManager() 
            throws Exception {
	     for (int i = 0; i < factoryNames.length; i++)  {
	         Method getTxMgr = null;
		 try {
		   //attempt to get class and method
		   Class<?> txMgrFactory = Class.forName(factoryNames[i]);
		   getTxMgr = txMgrFactory
                      .getMethod("getTransactionManager", null);	
		  } catch (Exception e) { 
		       continue;
		  }
		  //attempt to invoke method (let exception throw...)
                  return (TransactionManager) getTxMgr.invoke(null, null);
	     }
	     //if all else fails
	     return null;   //or throw exception
	}
     },

     WEBLOGIC() {
        @Override
	public TransactionManager getTransactionManager() 
          throws Exception {
           InitialContext ctx = null;
           try {
             ctx = new InitialContext();
             return (TransactionManager) ctx
               .lookup("java:comp/UserTransaction");
           } finally {
              if(ctx!=null) {
                 try { ctx.close(); } catch (NamingException e) {}
              }
           }
        }
     },

     JBOSS() {
      @Override
	public TransactionManager getTransactionManager() 
          throws Exception {
           InitialContext ctx = null;
           try {
             ctx = new InitialContext();
             return (TransactionManager) ctx
               .lookup("java:/TransactionManager");
           } finally {
              if(ctx!=null) {
                 try { ctx.close(); } catch (NamingException e) {}
              }
           }
        }
     },

    // Standalone environ or server w/o TM
    NONE() {
      @Override
	public TransactionManager getTransactionManager() 
          throws Exception {
	   //Use reflection to avoid necessary dependency
	   Class<?> clazz = Class.forName("org.objectweb.jotm.Jotm");
	   Constructor<?> constr = clazz.getConstructor(boolean.class, 
            boolean.class);
	   Object jotm = constr.newInstance(true, false);
	   Method getTxMgr = clazz.getMethod("getTransactionManager", 
            (Class[])null);
	   return TransactionManager.class.cast(getTxMgr
             .invoke(jotm, (Object[])null));
        }
    };

    // abstract method
    public abstract TransactionManager getTransactionManager() 
         throws Exception;
}

Here we are defining an abstract method getTransactionManager() as a factory method for getting or creating a JTA TransactionManager in a manner similar to the Spring Framework's JtaTransactionManager. Each enumeration instance must implement this method. In most cases, a JEE-compliant server will have a JNDI lookup that can be used. For WebSphere, there is no API for gettng a TransactionManager directly, but instead a time-honored backdoor for creating one. In the case of NONE (either a stand-alone environment or a server that has no TransactionManager), JOTM is used. Of course, the enum would be a lot shorter if the calls were delegated to factory classes, but that's an implementation detail.

Since the JMX default domain for most major Java application servers is self-describing, something like the following snippet of code can be used to "auto-sniff" the container environment:

     public Container lookupContainer() {
          String defaultDomain = ManagementFactory
              .getPlatformMBeanServer()
              .getDefaultDomain();
          try {
               return Container.valueOf(defaultDomain.toUpperCase());
          } catch (Exception e) { /*...assume none....*/ }
          return Container.NONE;   // or null if no default behavior
     }

After all of that, the client code to use it is a simple line:

lookupContainer().getTransactionManager():

Conclusion

The Container enum is a good illustration of the power of enumerations in Java compared to their C/C++ counterparts. By associating behavior with each enum instance, a smooth way of dispatching getTransactionManager() to the appropriate implementation has been created. This points out another fact: each enum instance (WEBSPHERE, WEBLOGIC, etc.) is implicitly a subclass of the enum class Container itself. This comes in handy since it means that many other object-oriented design patterns (Abstract Factory, Command, Visitor, and Strategy, to name a few) can be implemented using enums. Those, of course, are left as an exercise to the reader.

Google Chart API - A Real World Example

Tagged:  

You may have seen quite a bit about the new Google Chart API, but you may not have seen a real world example. In the recent release of the Digg Bury Recorder I got some first hand practice in using th Google Chart API. When developing the application I found a few interesting nuances and knowledge of these could help you in using the API in your applications.

One of the most interesting things that I found is that the charting always graphs on a 100x100 basis starting at 0,0. This presented some issues in our application as it needed to graph things like 25 buries and 1200 diggs. The way that I solved this issue was to find the greatest number on each axis and take 100 divided by the greatest number from the points on each axis. Once you get this number you multiply each point it by the appropriate scaler for each axis (although it may not work correctly with points that are less than zero and you would have to adjust the equation to work around that).

The below is an example of an URL that would be used to create a line chart (this is taken directly from the Digg Bury Recorder).

http://chart.apis.google.com/chart?chs=300x225&chd=t:9,16,51,51,51,52,58,59,61,62,63,67,69,69,69,72,74,74,89,93,96,98,100,100|4,8,12,16,20,25,29,33,37,41,45,50,54,58,62,66,70,75,79,83,87,91,95,100&cht=lxy&chxt=x,y&chxr=0,0,155|1,0,24

The parts of this URL that I would like to point out are below:

  • chxr=0,0,155|1,0,24 - This builds the markers of the graph (in our application I used the greatest value for each axis)
  • &cht=lxy - This specifies an X, Y line chart that uses actual points (if you look at the Google Chart API documentation you will see that most examples use helloworld as the points, as each letter has a numeric value, but I prefer to just pass in numbers)
  • chd=t:9,16,51,51,51,52,58,59,61,62,63,67,69,69,69,72,74,74,89,93,96,98,100,100|4,8,12,16,20,25,29,33,37,41,45,50,54,58,62,66,70,75,79,83,87,91,95,100 

    - This is a list of all the points (scaled as I mentioned before). It is important to note that a | is used to separate each axis.

The above Google Chart API URL will result in the below graph.

So now that you've seen my real world example you can check out the official Google Chart API documentation here.

If you make any cool applications using the Google Chart API let us know about it in the comments or you can blog about it on this blog when you sign up for a free account. If your post is considered interesting by the administrators of this site it will appear on the home page, otherwise it will be on your personal blog and under the blogs link.

YUI Based Lightbox [Final] Released

Cuong Tham over at Code Central created a YUI based Lightbox library and has just released the final version. For those of you unfamiliar with Lightbox, check this out.

   

What's New in this release?

The most significant change in this version of the lightbox is that image thumbnails are no longer required for creating lightbox instance. That implies that you can create an image gallery without the presence of image thumbnails. The more exciting aspect of this new feature is that you can virtually grab any image from the internet and include it in your gallery.

Below is the detailed list:

* Ability to view full size and auto-fit version of the image
* Settings for changing background mask opacity and color
* keyboard shortcuts
* Tooltip panel for displaying extra information
* Navigation control toolbar
* Image transition effect
* External stylesheet for styling

Bug Fixes

* Fixed image goes outside of viewport bug
* Removed extra scrollbar when the image can be fit into the viewport

The lightbox has been tested in Firefox 2.0.0.6, IE 7, Opera 9.21.

Check out a demo with thumbnails and without thumbnails [I recommend the black or the white theme as they look best].

One thing to note is that this is a hefty Lightbox implementation, weighing it at around 63KB for all required JavaScript files whereas the original Lightbox library only required about 13KB of JavaScript. That's a high price to pay for a cool gallery. But nevertheless, thanks to Code Central for putting this out, it's nice to see the differences in their implementation. If nothing else, you can download their source and play with it in your sandbox.

Click here to read the full article and download the source code.

Rapping about Ajax, JavaScript, Flex, YouTube, Apple, Social Networking and others...

Tagged:  

Just when you thought you've heard everything, here's a reason to go buy that expensive car stereo system you've always wanted, you can blast this as you cruise.

I'm so sick, ajax, JavaScript
Flex power when I point my pen

This is a hip hop / rap song about all things IT, web 2.0, computer software, you name it... Must be one-of-a-kind, although this song may start a revolution and change the face of hip hop.

Email2HTTP beta open for public registration

Tagged:  

Need to accept email in your web application? Check out Email2HTTP.

You can write simple scripts in languages like PHP and immediately start accepting email in your web apps. Build features like craigslist's anonymous email addresses, TripIt's itinerary gathering, Flickr & Google Docs email uploads, etc. in no time.

Hope to see you there,

TT

Sample PHP script to handle an email & send a reply:

Voices That Matter: GWT - Conversation with Josh Bloch

Video of the "Conversation with Josh Bloch" from Pearson Education's Voices That Matter: Google Web Toolkit 2007 conference.

Josh Bloch is the Chief Java Architect at Google. Previously he was a Distinguished Engineer at Sun Microsystems and a Senior Systems Designer at Transarc. He led the design and implementation of numerous Java platform features, including the JDK 5.0 language enhancements and the Java Collections Framework. He holds a Ph.D. in Computer Science from Carnegie-Mellon University and a B.S. in Computer Science from Columbia University.

Check out more session videos and presentation slides from the conference.

script.aculo.us v1.8.1 released

Tagged:  

New today from script.aculo.us:

This is a bugfix release that bumps script.aculo.us to version 1.8.1. Also included in this release is Prototype 1.6.0.1 beta.

Mainly, this release contains some important bug fixes and optimizations in Prototype, fixes cursor keys in autocompleting text fields for IE and Safari plus fixes an issue with Effect.Morph on IE.

In case you haven't heard of script.aculo.us, it's a JavaScript library built on the Prototype JavaScript Framework, providing dynamic visual effects and user interface elements via the Document Object Model. script.aculo.us includes an animation framework, drag and drop, Ajax controls, DOM utilities, and unit testing.

You can download this latest release at http://script.aculo.us/downloads

Ajaxonomy's Digg Bury Recorder Version Beta 0.2 Released

Tagged:  

We are proud to announce the release of Ajaxonomy's Digg Bury Recorder version Beta 0.2. This new release has a number of new features and fixes some issues that occurred with version Beta 0.1. Below is the list of new features and bug fixes.

New Features

  • Captures all buries for all stories
  • Graphs diggs to buries

Big Fixes

  • Recorder not capturing all buries

The first new feature above is one of my favorites. The tool now captures buries from all stories posted to Digg. The great thing is that you no longer have to leave the application running over night and you won't miss a bury because the application was not started!

The second feature shows a graph of diggs and buries. So, now you can see a graph showing how many diggs you had at the time of each bury. This was created using Google's Chart API.

For fixes this release fixes a bug that was causing some buries to not be captured. This was due to server delays and browser issues. The fix has been tested and appears to be working, but if you notice an issue contact us using the Contact button on this blog.

Well, that is a run down of the new features and fixes with this release, so please let us know of any bugs you find. Also, if you find any interesting information using the tool you can sign up for a free account on this blog and write a post like this one that has a chance to appear on the home page of Ajaxonomy.com (a.k.a. this blog).

In case you don't have the link to application click here to be taken to the application.

Update:
It has been pointed out that the application does not capture 100% of Digg bury data. It does capture 100% of Digg Spy's bury data, which captures all buries for upcoming and popular stories. However, it does not capture buries from stories that have been fully buried as these can no longer make the Digg home or popular pages. So the tool will show you the buries that matter (the buries that keep you off the home page).

Thanks to everyone that pointed out this clarification.

Ajax Pagination Script

Tagged:  

The folks over at Dynamic Drive have put together a nice ajax based pagination script that lets you draw content from multiple pages and display them on demand, using Ajax. Pagination links are automatically created, with each page downloaded only when requested (speeding up delivery and saving on bandwidth. An overview of this script now:

  • The pagination interface for each Ajax Pagination instance is "free floating", meaning it can be positioned
    anywhere on the page and repeated multiple times as well.
  • Each page within the paginated content is fetched individually and only
    when requested for sake of efficiency.
  • The settings for each Ajax Pagination instance is stored neatly in a
    variable object for ease of portability. This variable can be manually
    defined or easily dynamically written out based on information returned from
    the sever, such as via PHP/ MySQL.
  • The entire paginated content can be refreshed with new data on demand,
    with the pagination links updated automatically as well.

This script is ideal for showing multi-page content such as
"user comments" without reloading the rest of the page each time a
comment page is requested.

Click here to visit the site and to download the script.

Dynamic Drive also has a Virtual Pagination Script that lets you "transform long content on your page into a series of virtual pages, browseable via pagination links. The broken up content pieces are separated simply via arbitrary DIVs (or another block level element of your choice) with a shared class name." Read the full post on the Virtual Pagination Script

Let us know your experience with the Ajax Pagination Script or with any other pagination script you've worked with.

Syndicate content