Portfolio is iPhone ready

I now have my portfolio at christopherwardphotography.com iPhone ready. The site is heavy on javascript, and loads a lot of images at once. Makes for a slow 3G iphone experience. And the images were too small once safari scaled them. So I fixed that.

After hearing David mention a lightroom gallery plugin that was made for the iPhone, and trying to show someone that site (no flash on the iPhone), and my own (too slow), I thought I should do something. I don’t have lightroom. I have Aperture, but have never tried the web sites it can create. I just decided to create something on my own.

I wanted it to be simple, and not to use javascript. I also wanted it to look iPhoneish, and look good when the iPhone was vertical or horizontal. Also, just like wptouch that I wrote about yesterday, I wanted it to come up automaticly for iPhone users.

If you go there now with an iPhone you will see the iPhone specific site. If you don’t have an iPhone, this is what it looks like:

iphonealbums iphoneblue

On the left is the first page displaying the albums in vertical mode. The horizontal mode shows all four in a row. On the right is the blue album in horizontal mode. In vertical mode the images are two wide, and you scroll a bit more. Press an image and you see just that image in the browser. I didn’t make pages for each image. Each album has that nav bar at the bottom like the bottom of the first page.

Continue reading

Intro To Java Classes Revisited

This entry is part 3 of 13 in the series Intro to Java

This lesson will look more at class concepts in Java: Extending, overriding, composition, and inner classes. It was created as a lesson for a class room setting. I have converted it to a post here.

Is a Class just a Class?

I recently heard that the classic contractor response to a question is “Well, it depends.” That might just apply here. There are several different types of classes. There are regular classes, like we have been using, there are inner classes, and there are anonymous inner classes. In all cases though, they behave just the same. They still need to be instantiated, and they still contain variables and methods. What we will look at here is what those different types are, and when you might use them.

To do this, we will once again revisit the Robot. This time we will be adding a head that rotates to the Robot. We will look at placing the code directly into the Robot without using another class, using an inner class to Robot, and using containment to hold another class.

Before we get to that, lets revisit the parent/child relationship that exists when a class is extended and how casting works. Then we will get to the RobotHead.
Sun Trails Index: http://java.sun.com/docs/books/tutorial/index.html
Link into Objects and Classes Trail: (nested classes) http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

Continue reading

Intro to Java and Static Stuff

This entry is part 2 of 13 in the series Intro to Java

This lesson will cover some basic concepts in Java related to static variables and methods. It was created as a lesson for a class room setting. I have converted it to a post here.

What does static mean?

Lucky for us, static has nothing to do with statics, a class I had to take in Engineering about the forces on objects that are not moving.

What is does have to do with, seems to go against the concepts we talked about in the Classes vs. Objects lesson. If you followed along there, we talked about how the Class was the blueprint, and the Object was a concrete, instantiated, “built” Class. Its variables were its own, and the methods belonged to this Object.

When something is static, it means that it belongs to the class, and not the object. Every object has access to this item, but it is not unique to the object.

Sun Trails

Index: http://java.sun.com/docs/books/tutorial/index.html

Link into OO Trail: http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html
Continue reading

Intro to Java Objects and Classes

This entry is part 1 of 13 in the series Intro to Java

This lesson will cover some basic concepts in Java related to classes and objects. It was created as a lesson for a class room setting. I have converted it to a post here.

Class vs Object

Definition from page 10, Java A Beginner’s Guide (Herbert Schildt)

A class defines the form of an object. It specifies both the data and the code that will operate on that data. Java uses a class specification to construct objects. Objects are instances of a class. Thus, a class is essentially a set of plans that specify how to build an object.

The code and data that constitute a class are called members of the class. Specifically, the data defined by the class are referred to as member variables or instance variables. The code that operates on that data is referred to as member methods or just methods.

Sun Trails

Index: http://java.sun.com/docs/books/tutorial/index.html

OO Trail: http://java.sun.com/docs/books/tutorial/java/javaOO/index.html
Continue reading

New Java Lesson on Static Stuff

JavaI taught a new lesson this week on Static Stuff, which has been posted on this website. This is part 2 of the series Intro to Java that I have been creating. In this lesson we look at static methods and static class variables. There are several code examples to go with the lesson. The feedback in class has been pretty good. Hopefully some others will find in helpful as well.

Moving Pictures via Javascript

Ok, I had promised to let anyone know that happened to be reading before Christmas, that I would talk about the collage script that I am using on the Christoper Ward Photography site. I am using the lytebox script when you click on an image, but the collage image that moves the pictures around the screen is all mine.

You can get the html source from that page. Here is the Javascript and the CSS files that are used. You can use this code, but please leave the Javascript comment header with my name on it.

/*
	collage javascript
	
	You are free to use this script provided you include this header

	Created by Chris Ward
	veggie2u@cyberward.net
	http://www.cyberward.net/blog/
*/

function Collage(pName) {
	this.name = pName;
	this.state = "closed";
	Collage.list[Collage.quantity] = this;
	Collage.quantity += 1;
}

Collage.prototype.open = function() {
	Collage.closeAll();
	for( i=0; i < this.endPoints.length; i++ ) {
		$image = this.name+'img'+(i+1);
		new Effect.Move($($image), { x:this.endPoints[i][0], y:this.endPoints[i][1], mode: 'absolute' });
	}
	this.state = "open";
}

Collage.prototype.close = function() {
	for( i=0; i < this.endPoints.length; i++ ) {
		$image = this.name+'img'+(i+1);
		new Effect.Move($($image), { x:this.startPoint[0], y:this.startPoint[1], mode: 'absolute' });
	}
	this.state = "closed";
}

Collage.prototype.swap = function() {
	if( this.state == "closed" ) {
		this.open();
	} else {
		this.close();
	}
}

Collage.closeAll = function() {
	for( i=0; i < Collage.quantity; i++ ) {
		var $aCollage = Collage.list[i];
		if( $aCollage.state == "open" ) {
			$aCollage.close();
		}
	}
}

function doOnLoad() {
	$$('img.collageImg').each(function(s) {
		s.show();
	});
	collage1.swap();
}

Collage.quantity = 0;
Collage.list = new Array();

var collage1 = new Collage("g1");
collage1.endPoints = [ [280, 80], [300, 180], [400,100], [580,120], [500,200], [280,400], [340,320], [540,290], [480,380], [620, 440] ];
collage1.startPoint = [4, 60];

var collage2 = new Collage("g2");
collage2.endPoints = [ [220, 100], [360, 120], [280,220], [300,390], [380,300], [580,100], [500,180], [470,420], [560,330], [660, 420] ];
collage2.startPoint = [4, 180];

var collage3 = new Collage("g3");
collage3.endPoints = [ [280, 80], [240, 230], [400,100], [460,180], [280,400], [340,320], [540,290], [600, 400], [580, 130], [480,380] ];
collage3.startPoint = [4, 300];

var collage4 = new Collage("g4");
collage4.endPoints = [ [280, 80], [300, 230], [400,100], [540,120], [580,200], [340,400], [280,320], [480,290], [540,380], [700, 110], [650, 350] ];
collage4.startPoint = [4, 420];
body {
	background: black;
	margin:0;
	padding:0;
	height:100%;
}

#albums {
	position:absolute;
	top:10px;
	left:20px;
}

#about {
	position:absolute;
	top:530px;
	left:10px;
}

#about img {
	border:0;
}
#about a {
	text-decoration:none;
}

#title {
	position:absolute;
	top:10px;
	left:220px;
}

#collages {
	background-image:url("./images/albums_background.png");
	position:absolute;
	left:0;
	top:0;
	width: 180px;
	height: 100%;
	margin-top:0px;
	margin-bottom:0px;
}
#collages img {
	margin: 10px;
}

#content {
	margin-left:180px;
	color:white;
}
#content img {
	border:0;
	display:block;
	margin-left:auto;
	margin-right:auto;
}

.collageImg {
	border: 1px solid white;
}

.collageThumb {
	opacity:0.4;filter:alpha(opacity=40);
	border: 1px solid white;
}

#g1img1, #g1img2, #g1img3, #g1img4, #g1img5, #g1img6, #g1img7, #g1img8, #g1img9, #g1img10, #g1img11 {
	position: absolute; top: 60px; left: 4px;
}
#g1img11 {
	opacity:0.4;filter:alpha(opacity=40);
}

#g2img1, #g2img2, #g2img3, #g2img4, #g2img5, #g2img6, #g2img7, #g2img8, #g2img9, #g2img10, #g2img11 {
		position: absolute; top: 180px; left: 4px;
}
#g2img11 {
		opacity:0.4;filter:alpha(opacity=40);
}

#g3img1, #g3img2, #g3img3, #g3img4, #g3img5, #g3img6, #g3img7, #g3img8, #g3img9, #g3img10, #g3img11 {
		position: absolute; top: 300px; left: 4px;
}
#g3img11 {
		opacity:0.4;filter:alpha(opacity=40);
}

#g4img1, #g4img2, #g4img3, #g4img4, #g4img5, #g4img6, #g4img7, #g4img8, #g4img9, #g4img10, #g4img11, #g4img12 {
		position: absolute; top: 420px; left: 4px;
}
#g4img12 {
		opacity:0.4;filter:alpha(opacity=40);
}

The way that it is implemented is pretty simple. In order to make this work, I relied on a naming convention. Lets look at one image:


The id of the image is set to g1 for 'gallery 1', img1 for 'image 1'. If you look at the html, I had to add this logical id to every image. This is a very tedious process. There is also the code for lytebox, namely the rel="lytebox[one]" to launch the lytebox script when the image is clicked, and link all the 'one' galleries together. The other thing on this line is the style="display:none;" part. This bugs me, but it appears to be a css limitation I can't get around. Because all the images are stacked, they all appear in turn as they are downloaded without this. If I put this style in the css, then javascript can't turn it back on! It has to be an inline style. I would love to hear a solution for this.

Then we have one more line from the html file to look at.


This line is the last line in each gallery, and is the last image repeated. This is the one that will not move, and forms the thumbnail for the gallery. Via css, the transparency is lowered when the collage is out. This image contains the onClick call to move the images.

Now onto the javascript. Look at this bit of code that defines a collage:

var collage1 = new Collage("g1");
collage1.endPoints = [ [280, 80], [300, 180], [400,100], [580,120], [500,200], [280,400], [340,320], [540,290], [480,380], [620, 440] ];
collage1.startPoint = [4, 60];

This defines gallery 1 ("g1"). All those numbers are the end points for where each image will be when the collage is expanded. Again, this is a pain, and it can be confusing which image you are adjusting when changing the numbers.

So lets look at the open function:

Collage.prototype.open = function() {
	Collage.closeAll();
	for( i=0; i < this.endPoints.length; i++ ) {
		$image = this.name+'img'+(i+1);
		new Effect.Move($($image), { x:this.endPoints[i][0], y:this.endPoints[i][1], mode: 'absolute' });
	}
	this.state = "open";
}

This is pretty simple. Once I found the Effect.Move() function of scriptaculous, this simply loops over the images in the gallery, and tells the Move function to move the images from where it is (stacked with the others), to the endpoint. The close is similar. It moves the images from where they are (the endpoints) to the start point that was defined in the gallery definition.

The rest of the script is pretty simple. The other methods show all the images (doOnLoad), or set up the swap.

What could be improved? A lot. I don't like defining the galleries and the images through the id field. The user of the collage js has to have intimate knowledge of how the script works in order to set it up. Not only that, but you need matching elements defined in CSS correctly. Having the end point definitions in the js is a pain too. Would would be better, is to come up with a way to have the javascript scan the html and look for images to use, much like how lytebox does it via the rel attribute. Well, guess what? That is exactly what I am working on!

Javascript Speed Tests

As part two of yesterdays Javascript Speed post, I have an interresting link. MooTools, another Javascript library, has a speed comparison page up here. I had looked at MooTools a while back when I put up the slideshow piece on the front page of the site. I didn’t look into it too much, but it seemed small and compact. Anyway, the speed comparison is interresting. If you go to the site, press the “start tests” button in the upper right to see the differences. I got here while I was looking into jQuery. Prototype gets smacked in the speed test. Yikes.

This post is from 2007, but was already complaining that WordPress was going to use Prototype instead of jQuery for version 2.0. (which was just released a month ago) It would appear to me though that WordPress went and switched to jQuery. Looking at the WordPress docs, I found this page on AJAX, and it talks about jQuery.  When I look at the source of one of the admin pages, there is jQuery references all over, but nothing about prototype.

Looks like WordPress has switched to jQuery, and if I am looking at making plugins for wordpress, I might want to think about moving to jQuery.

Javascript Speed

I have been working on a new script that will “fly” collages out from an album. It was using an effect from script.aculo.us. I am much closer, and am in the process of gathering images to post before I call it done. I tested it with Safari, Windows Explorer 6, and Firefox 3.0. I have to say, it was crazy smooth in Safari and Explorer. I was disapointed in Firefox. It is a little jerky. It was in development, but I figured that was just something to live with until I tried the other browsers.

There is hope. Firefox 3.1 is in beta (as of October), and it is supposed to have Tracemonkey support among other things. All the browsers have been madly working on their javascript kung fu it would appear. I haven’t tried the beta, but here’s hoping for a smoother ride once it hits prime time.

Javascripting

So I started playing with Javascript a bit more recently. I looked for a library that could do some cross browser animation stuff. The lightbox script was based on prototype and script.aculo.us for effects. I have only scratched the surface of what these librarys can do, but they seem pretty cool.

The project I am working on is an upgrade to the single collage that I have up at christopherwardphotography. The idea is that you would pick an album, and the images would fly out from the album. What I wanted was something that would move an image. The scriptaculous Effect.move class provides this. The really cool thing I found was that the javascript interpreter does not stop and wait for the move to finish. It keeps going. If you call out several in a row, all the images will move on the screen at the same time. Very cool.

I will have more about this “flyout collage” later when I am finished. It will apear at christopherwardphotography when it is done.

The image overlay effect

On ChristopherWardPhotography.com, when you click on an image, it pops up the image in a floating panel above the other images. I think this is pretty cool. I have done something similar in code that I had written to tarken the screen, put up a “glass pane” (you can’t click on links), and place content in an overlayed div. This library works really slick though.

I first started with lightbox. It is pretty popular, and quite a few people use it, although I don’t think it is over used. This works pretty well. It has a few dependancies, such as prototype, and scriptaculous. These libraries on there own add quite a bit of functionality to javascript, but they aren’t lightweight.

Then I found lytebox. This project shrinks down the code by “borrowing” just what is needed for the lightbox effect. Then he has improved it. The images will automatilcy resize to fit the browser screen, and it will also allow html documents in these pop ups, not just images. This is what I went with.

I kind of wish that lightbox had the same image scaling and html content that lytebox has, because I have some more plans for some sriptaculous scripting…