Populares Et Optimates, A Game Of Rome Part 2

Watching card manipulation by Dan and Dave Buck including those on their site like the demo video of the Akira flourish got me thinking quite a bit about card shuffling. After seeing some of the false shuffles and other manipulations and having read about games where the shuffling algorithm was only pseudo-random, I wanted to make sure that the card shuffling for my game was at least adequate enough to make the game work.

If you’re not familiar with Dave and Dan, check out this video advertisement for their set of DVDs over at Theory 11:

Wikipedia has a good article discussing shuffling cards and computer algorithms for shuffling.

An example shuffle algorithm in Javascript would be this implementation of Durstenfeld’s algorithm, a modern version of Fisher-Yates that looks like this:

function array_shuffle (aArray)
{
    var i, j, mTemp;
    for (i = aArray.length; i;) {
        // mTemp, j initialized here for shorter code.
        j = parseInt (Math.random () * i);
        mTemp = aArray [--i];
        aArray [i] = aArray [j];
        aArray [j] = mTemp;
    }
}

For the random number generation, I prefer this, but I haven’t exercised it in order to see if it makes a difference, though seeing parseInt in the above makes me wonder about its presence.

j = 1 + Math.floor(Math.random() * i);

As for the cards in the game, they are represented in the Javascript as objects and can be either people or actions. People cards are members of one or the other faction or a third group of loosely-aligned Romans who may be swayed to one side or the other. They have attributes including the side they belong to, whether their side may be changed, their name and current rank. Action cards represent the cards that are used during play. Actions include ranks and positions that may be assigned to People and events like riots, assassinations, and plagues. Action cards often have negative or side-effects, sometimes costing the player who uses it as much as his opponent. Other cards require votes from the Senate such as Exile or the appointment of Generals.

There are a variety of collections that I’ll refer to as decks. There are two decks of people, one for each player. Event decks include one hand for each player, the drawing deck and the discard deck. Additionally, there may be individual cards in play that belong to no particular deck.

I considered a number of names for the game including Optimates et Populares, but that doesn’t roll off the tongue. The working title that I came up with is Marius and Sulla after the two men who fought together in the Social War and then became bitter enemies. The game centers around the time where partisans identified themselves less with the espoused philosophies each represented and more with the personalities themselves. The short version of the game covers the six years following the Social War (88 BC – 82 BC).

Comments Off

SPQR Or Pontifex Maximus, A Game Of Rome Part 1

I’ve decided to create a web-based game set in early Rome. It’s intended to be about the leaders of the time with an emphasis on politics rather than military strategy. I want the latter to happen “off-screen” as it were, but with the option for legions to show up at the gates of Rome when needed to influence political events.

The biggest difficulty was selecting a time period that provided the right amount of variety, particularly political in-fighting and manuevering without too much military action (such as the wars with Carthage). In that regard, the early and late periods of the Republic offered some interesting options, as did the time of the First Triumvirate and the period following the death of Caligula, to name but a few points in the turbulent history of the Romans.

I’m particularly fond of the political manueverings described in Imperium by Robert Harris and in the BBC production of I, CLaudius (for which I must confess that I haven’t read the book by Robert Graves). There’s an immediacy to the politics combined with a certain degree of brutality that keeps one from longing overmuch for the good old days. So the more I thought about it, the less Imperial Rome appealed to me and the more I wanted to go back a little further in time. At the same time, Lavinia by Ursula Leguin brings the events of Virgil’s Aeneid to life brilliantly with the interplay between the tribes of the area and the followers of Aeneas.

Out of all the time periods that I think would make for an worthwhile game, the period immediately following the Social War, a crisis point in Roman history, sounded extremely interesting. Sulla’s First Civil War with the struggle between the optimates and populares (and I’m simplifying matters greatly since it wasn’t that black and white) made for some turbulent times with lots of political and military manuevering. Throw in assassinations, exiles, plagues, riots and external threats like Mithridates of Pontus, and you have a good deal of elements to work with.

As they say, plus ça change, plus c’est la même chose. The politics of the Roman Republic and the Roman Empire have much in common with the infighting during the War of the Roses and the gangland warfare of the Roaring Twenties. For that reason, I wanted to capture some of the feel of the Avalon Hill game Kingmaker, minus the board and tediousnous of moving armies around, with the fast-paced play of Family Business, but with a more historical feel and slightly more elaborate mechanics.

Before starting work, I did some research on already existing games that covered both the time period I was interested in with the politics in a card game or simple board game version. I was positive there’d be a plethora of games of all stripes, some very similar to what I had in mind. Surprisingly, the list wasn’t nearly as long as I expected, though I’m sure I missed more than a couple. My short list of games that aren’t strategy games and that otherwise capture some of the elements I was looking for are as follows:

Certainly, some of these games are ones that I’d really like to play, particularly Triumvirate. But before I do that, I’d like to get my game up and running. First up, a paper prototype. Much like website usability testing with paper mockups and wireframes, I plan to make some cards and to try some mechanics so I can see how they play out. I’ll discuss that in my next on this subject.

Comments Off

Javascript Sorting

Not too long ago, I was asked, as a theoretical question, how I might take a string of random alphabetical characters and sort them in order using Javascript. Thus, given NFARAKDMSLSJDQKJKCXLK, find a simple way to turn it into AACDDFJJKKKKLLMNQRSSX. It’s a pretty basic question for anyone who uses Javascript and I immediately thought of splitting and joining the string as an array (a quick and easy way to tokenize the string). However, for some reason, I completely forgot about the Array.sort() function that’s pretty much a universal across languages.

Instead, the first thing that came to mind was the last time I had to sort a collection and started thinking of Java sorting. In the work I’ve done, such sorting usually requires the use of comparators because the default sort order is often not the one that’s desired. As a case in point, we have a set of JSP pages for rendering content including archive and list pages that display in posting date or sequence order derived from the content. For example, here’s some code to sort by a custom “sequence” attribute using the Vignette Content Management API (this particular snippet is the work of the inimitable Yong Chen):

Comparator aComparator = new Comparator(){
	public int compare(Object obj1, Object obj2) {
		int result=0;
		try {
			Integer s1 = (Integer) ((ContentInstance) obj1).getRelations(CT_RELATION_HEALTH_PLAN)[0].getAttribute("sequence").getValue();
			Integer s2 = (Integer) ((ContentInstance) obj2).getRelations(CT_RELATION_HEALTH_PLAN)[0].getAttribute("sequence").getValue();
			result=s1.compareTo(s2);
		} catch (com.vignette.as.client.exception.ApplicationException e) {
		}
		return result;
	}
};

For debugging, I might break it out a little differently to avoid the multiple casts in a single line. I think the Vignette API is fairly robust, but I would still split the ContentInstance cast apart from the Java native Integer cast in this case. But that might just be me.

In any event, while Javascript can also use comparators without much loss of speed, for a task like the one delineated initially, a simple sort will do the job and the whole can even be condensed to a single line function like this:

function order(unsortedString) {
	return unsortedString.split("").sort().join("");
}

Depending on the browser, the sort function will be some variation on a quick sort or a merge sort. It depends on whether the browser architects chose a stable algorithm or opted for some other version based on various considerations. Mozilla used to use a quicksort prior to Firefox 3.5, but they opted for a merge sort instead in more recent versions. In the course of reading about sort implementations, I came across notes on timsort, Python’s default sort implementation, that I found particularly intriguing.

As an aside the return value for a comparator that works in Firefox may fail with Webkit (Chrome and Safari) since you need to return -1 instead of zero (and a boolean false will also fail). You can read more about Webkit’s Array.sort() handling.

With Java, it looks like this:

String unsorted = "xzya";
char[] content = unsorted.toCharArray();
java.util.Arrays.sort(content);
String sorted = new String(content);

With Perl, you can do something like:

print (join “”, sort split //,$_)

In bash, this will do the same job:

echo “teststring” | grep -o . | sort -n |tr -d ‘\n’; echo

All in all, not only did I refresh my memory about good ways to sort strings and arrays in Javascript, I also learned some new things about sort algorithms and implementations of those algorithms.

Comments Off

Creating an RSS Feed in JHTML

Because we use an older version of ATG Dynamo (6.2.0) at my place of employment, we’re sometimes constrained in what we can do and aren’t able to take advantage of features in newer versions of Dynamo. One of those features is the ability to generate an RSS feed from a content repository (which I believe is available now as part of the suite of personalization features ATG offers). If you have the ability to deploy droplet code, there’s certainly an RSSFeed module. But if all you need is a basic RSS feed for a particular collection, the following is what I came up with.

<?xml version="1.0" encoding="UTF-8" ?>
<importbean bean="/atg/targeting/TargetingForEach">
<importbean bean="/atg/dynamo/droplet/Switch">
 
<%-- import files --%> 
<%@ page import="java.util.*, java.text.*" %>
 
<%-- Generate the RSS XML --%>
 
<%-- Set the rss type --%>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/">
   <channel>
      <title>News</title>
      <link>http://www.foobar.com/</link>
      <description>News and information.</description>
   <textInput>
      <title>News</title>
         <link>http://www.foobar.com/</link>
         <description>News and information.</description>
   </textInput>
   <skipHours>
      <hour>0</hour>
   </skipHours>
      <language>en-us</language>
      <webMaster>webmaster@foobar.com</webMaster>
 
      <droplet bean="/atg/targeting/TargetingForEach">
         <param name="targeter" value="bean:/atg/registry/RepositoryTargeters/News/archiveNews">
         <param name="fireContentEvent" value="false">
         <param name="firecontentTypeEvent" value="false">
         <param name="sortProperties" value="-postingDate">
         <oparam name="output">
            <droplet bean="/atg/dynamo/droplet/Switch">
               <param name="value" value="param:element.linkURL">
               <oparam name="unset">
                  <item> 
                     <title><valueof param="element.title"/></title>
                     <description><valueof param="element.description"/></description>
                     <link>http://www.foobar.com/news/news.jhtml?reposid=<valueof param="element.repositoryId"/></link>
                     <pubDate><valueof param="element.postingDate" converter="Date" date="EEE, dd MMM yyyy HH:mm:ss Z"/></pubDate>
                  </item>
               </oparam>
               <oparam name="default">
                  <item> 
                     <title><valueof param="element.title"/></title>
                     <description><valueof param="element.description"/></description>
                     <link><valueof param="element.linkURL"/></link>
                     <pubDate><valueof param="element.postingDate" converter="Date" date="EEE, dd MMM yyyy HH:mm:ss Z"/></pubDate>
                  </item>
               </oparam>
            </droplet>
         </oparam>
         <oparam name="empty">
            <p>No archived news</p>
         </oparam>
      </droplet>
   </channel>
</rss>

A couple of the important things with an RSS feed is to have a properly formatted date and to properly include the various elements and the like. Some readers are more forgiving than others. The date version here is the RSS 2.0-compatible RFC822 and not the older ISO8601, though you can read all about the ins and outs of RSS dates. Many elements are optional but the output may display strangely depending on the reader and are included here primarily for consistent display with the built-in readers on IE and Firefox.

Comments Off

A Breadcrumb Story

Where I work, one of the site features is a breadcrumb trail on all pages allowing linking through the content hierarchy. All of the breadcrumbs in the breadcrumb trail was generated using a rather lengthy Javascript file. The main reason for the length was due how the folders were named and the number of exceptions or special cases. As a note, for this to work all directory names were CamelCase (lowerCamelCase, to be precise) except where they were legacy items or inconsistently named (increasing the number of special cases that needed handling).

But it worked better than much breadcrumb code I’ve seen, so all was well and good until two things happened. The first was that mysterious 404 errors began to crop up in our logs. I finally traced them back to bots crawling the site, coming across the pieces of the Javascript that constructed the links in the breadcrumbs and indexing them as valid (not processed) links. So our logs were littered with failures to find pages like about_gh/.*/badministrator/b.*)/i, or /health_plans/+howmany[i+2]+. The second thing that occurred was we began developing a new version of one of our sites and it didn’t make sense to use the existing Javascript since the majority of it’s special cases were for our main site. Further, we would just be perpetuating the log errors caused by misbehaving seach engine bots.

So, for the new site, I rewrote the Javascript as a JHTML include. Since we’re using Dynamo and haven’t migrated any of our dynamic pages to be JSP pages (and encountered some problems with that due to the older version we’re running on), I learned some interesting things about using Java inline on a single page like this.

The first part of the page requires declaring any imports, like so:

<java type="import">
	java.util.regex.*;
</java>

The second part of the page is the main Java code that gets the URL and performs some operations on it:

<java>
	String originalURL = request.getRequestURL().toString();
 
	if (originalURL.indexOf("somejavaAppPathID") != -1) {
		if (originalURL.indexOf("javaApp") != -1) {
			breadcrumbPathString += divider + "<a href=/somespecialidentifierParent/index.jhtml>JavaAppParent</a>" + divider + "<a href=/somejavaAppPathID/javaApp/JavaAppMethod?forwardUrl_success=/someAppResultLocation/javaApp/index.jhtml>JavaApp</a>";
		}
	} else if (originalURL.indexOf("pageNameWithParam.jhtml") != -1) {
			//itemKey is the parameter that has the path to the content
			String paramKey = "paramname";
			breadcrumbPathString = makeTrail(request.getParameter( paramKey ), baseLoc, divider);
	} else {
		breadcrumbPathString = makeTrail(request.getRequestURI(), baseLoc, divider);
	}
 
	breadcrumbPathString = fixDirectories(breadcrumbPathString);
 
	out.print(breadcrumbPathString);
</java>

Originally, my thought was to use the Request Scheme like this:

String thisRequestScheme = request.getScheme();
if (thisRequestScheme.startsWith("https") == true) {
	baseLoc ="https://"+ request.getServerName() ;
} else{
	baseLoc ="http://"+ request.getServerName() ;
}
if (request.getServerPort() != 0) {
	baseLoc += ":"+request.getServerPort();
}

But since our server configuration includes F5 load balancers, that was incorrect and the request object contains different information than the URL we’re looking for. I’d prefer to use this implementation, but the previous one starting with request.getRequestURL() will work.

Lastly, I created some methods for handling special cases and doing some other work on the URLs:

<java type="class">
	public String makeTrail(String breadCrumb, String urlPath, String thisDivider) throws IOException {
		urlPath += "/";
		String outputString =  "<a href=\""+urlPath+"index.jhtml\">Home</a>";
		String linkName = "";
		String linkString = breadCrumb;
		breadCrumb = removeDirectories(breadCrumb);
		if (breadCrumb != null) {
			String[] breadCrumbArr = breadCrumb.split("/");
			String[] linkStringArr = linkString.split("/");
			if(breadCrumbArr.length!=0) {
				for(int i=1; i<linkStringArr.length-1; i++) {
					urlPath += linkStringArr[i]+"/";
					if (breadCrumbArr[i] != null && breadCrumbArr[i].length() > 0) {
						linkName = makeProper(breadCrumbArr[i]);
						outputString +=  thisDivider+"<a href=\""+urlPath+"index.jhtml\">"+linkName+"</a>" ;
					}
				}
			}
		}
		return outputString;
	}
 
	public String makeProper(String theString) throws IOException {
		StringReader in = new StringReader(theString);
		boolean precededBySpace = true;
		boolean precededByCap = true;
		StringBuffer properCase = new StringBuffer();
		while(true) {
			int i = in.read();
			if (i == -1)  break;
			char c = (char)i;
			if (Character.isSpaceChar(c)) {
				properCase.append(c);
				precededBySpace = true;
			} else if (Character.isUpperCase(c)) {
				if (precededByCap) {
					properCase.append(c);
				} else {
					properCase.append(' ');
					properCase.append(c);
				}
				precededByCap = true;
			} else if (c == '-'||c == '_') {
				properCase.append(' ');
				precededBySpace = true;
			} else {
				if (precededBySpace) {
					properCase.append(Character.toUpperCase(c));
				} else {
					properCase.append(Character.toLowerCase(c));
				}
				precededBySpace = false;
				precededByCap = false;
			}
		}
		return properCase.toString();
	}
 
	public String removeDirectories(String theString) {
		//completely remove these directories from the breadcrumbs
		theString = replaceWith(theString,"ignore/","/");
		theString = replaceWith(theString,"anotherDirectoryToSkip/","/");
		return theString;
	}
	public String fixDirectories(String theString) {
		//replace these nonsense names with real words
		//    theString.replaceWith("(?i)\\babout[ _]us\\b","About Us"); //A weird special case since the directory name is not CamelCase
		theString = replaceWith(theString,"(?i)\\bpeople\\splaces\\b","People &amp; Places");
		theString = replaceWith(theString,"(?i)\\babbr\\b","Full Unabbreviated Directory Name");
		return theString;
	}
 
	private static String replaceWith(String aPath, String aPattern, String aReplacement ){
		Pattern pattern = Pattern.compile(aPattern, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(aPath);
		return matcher.replaceAll(aReplacement);
	}
</java>

In reviewing this code, one thing I was unsure about was whether using

String originalURL = request.getRequestURL().toString();

was the correct way to go or if I should have used

String path = request.getPathTranslated();
path = replaceBacklash(path);

I realized that, for the way the site functions, we may pass an item parameter and we want to properly build the path to that item, not the page rendering the item. Using getRequestURL handles both situations.

Comments Off

The Anti-Resume

The term anti-resume is used in several different senses, most commonly refer to a narrative resume in the fashion of Anne Sexton’s Resume 1965. My own profile is a reasonable example of this form of resume.

The other sense of the term is that mentioned in Nassim Nicholas Taleb’s book The Black Swan where the author comments, “People don’t walk around with anti-resumes telling you what they have not studied or experienced.” For computer geeks, this seems to be doubly true since it’s often a point of pride about the depth of knowledge in a particular area one has, whether it’s a computer language, a code framework, or some particular anime director’s corpus of work.

To list all the things one doesn’t know, even in the broadest sense, would still be a ridiculously large list, not to mention a rather pointless intellectual exercise. But there would actually seem to be quite a bit of value in analyzing one’s abilities in terms of what one aspired to learn (but might never learn due to lack of aptitude or limitations of time) or what one planned to learn for a job role (a variation on the, “where do you see yourself in five years” question). In the latter, the anti-resume becomes a tool for planning one’s personal or career growth.

My first take on a personal anti-resume looks something like this:

  • Foreign language (Japanese and Mandarin Chinese). Despite having had two years in college on the former and taking some lessons in the latter, my ability to speak these languages is below the level that might be considered functional. I comprehend enough Japanese to get the gist of conversations when my daughter’s friends speak Japanese with their parents and I can occasionally puzzle out words in katakana. My Mandarin is stuck pretty firmly at the preschool level, though I know all the words to the children’s song “Liang zhi lao hu” (“two tigers”, sung to the tune of “Frere Jacques”).
  • The .NET web technology stack (IIS, C#.NET, SQLServer). I know just enough of these technologies to be dangerous, having worked off and on with IIS and deployed ASP pages, built at least one app with C# and used SQLServer on the desktop for Vignette. But I’d like to know more and I’d like to be able to build full-featured data-driven web applications with this technology with the same proficiency that I do with other technologies (LAMP and Java).
  • Functional programming languages. Ever since first being exposed to them in a meaningful way at No Fluff Just Stuff in 2008, I’ve been excited about functional programming languages like Erlang or Clojure. In addition to learning more about those languages (pick one), I’m still fuzzy on concepts like lambda calculus and curried functions and would like to learn more, particularly when it comes to applying some of those concepts to the Javascript work I do.
  • Probability. Having completed a course in statistics, I feel like I have some better tools to further improve my understanding of probability and things like Bayesian analysis. There are so many applications for probability in the computer field and I feel like I’ve barely scratched the surface with my reading.
  • Geography and GIS. I have a real fondness for maps and geography along with the ways we use maps in ways beyond getting directions somewhere. The use of maps on the web and other technology like GPSes are of particular interest where they overlap with ideas of space over time and human relations to space (such as human migrations and land use, urban development, and community building). I may not be quite the GIS maven that Scott Davis is, but I have his book GIS for Web Developers and I plan to read it all the way through sometimerealsoonnow.
  • Javascript and jQuery. I’ve been writing Javascript for years, though it’s only recently I’ve begun to explore its real capabilities, as enhanced by the various frameworks out there including YUI, prototype, jQuery and DOJO. I’ve had the ability to dive pretty deeply into jQuery in recent months and want to master its capabilities.
  • Computer Security. With the recent concern about PCI compliance and working in an industry where we deal with confidential health records, security of our data, our applications and our servers (the latter two, respectively, accessing and storing the data) is a major concern. Among our many concerns are making sure we’re in compliance with regulations, checking that the site isn’t vulnerable to things like XSS attacks and ensuring that the applications are secure. We also work closely with the IT group that manages the servers to avoid inadvertently introducing security holes and exposing data.
  • Algorithms and Design Patterns. My first serious exposure to design patterns was with my Java certification, though I discovered I’d been using some variation of various patterns without knowing what they were specifically. Having the knowledge and using it in a systematic fashion has made me want to learn more about patterns I haven’t used. The same holds true with algorithms such as sorting data and lists, traversing trees, and compressing data.
  • Aikido. I’m currently a member of the Tsubomi Seishin Kan Dojo, but time constraints and finances have limited my ability to take aikido lessons right now. I hope to continue classes in the near future, probably as soon as I’m not spending as much time with school and learning some of the previous things in this list. Of the martial arts I’ve studied, aikido resonates with me, combining the breathing and moving meditation of tai chi with the discipline and weapons practices of karate. Not only that, but the people in my dojo are a really great bunch of folks I like spending time with.
  • Writing. I’ve written extensively throughout my life and in number of different modes including fiction, poetry, technical documentation and this blog. There’s always room for improvement and learning. I’d love to write a book, perhaps a novel, and some short fiction, either fantasy or science fiction.

That’s just a quick take, but probably more than enough to keep me occupied for the next five years.

Comments Off

Hashtables and form labels with jQuery forms

Javascript implements hash tables in a limited and somewhat unwieldy fashion as associative arrays. The jQuery.field plugin has some useful functions including a formHash() function that returns all the elements of the form with the field ids as the hash keys and the form values as the hash values corresponding to those keys.

Some people consider treating associative arrays as hash tables as being downright bad since they appear to have all the characteristics one would expect, but in fact, do not. For example, the way one iterates over the array and the ability to determine the size of the array (array.length).

This custom implementation solves those problems rather handily (and there’s an implentation in the comments with the Ajaxian post linked in the previous paragraph). I believe this is what people refer to when they recommend using objects rather than simple associative arrays (since arrays are, themselves, objects in Javascript).

For the purposes of the work I was doing, where it’s not intended for production and where performance (or scalability) is not a consideration, but rapid prototyping and the ability to easily correlate form fields with labels, this implementation seems to work just fine:

jQuery.fn.labelList = function(){
	var strValueList = [];
	var label = $(this).find("label");
	label.each( function (index) {
		var id = $(this).attr('for') || 'undefined';
		if (id) {
				labelText = $(this).text();
				if (labelText.substr(0,1)=="*") { labelText = labelText.substring(1, labelText.length); }
				if (labelText.substr(labelText.length-1,1) == ":") { labelText= labelText.substring(0, labelText.length-1); }
				strValueList[id] = labelText;
		}
	});
	return( strValueList );
}

Which is then used in a function something like the following which is called using:

$("#yourFormID").collectResults();
 
jQuery.fn.collectResults = function(){
	var currentForm = "";
	var myResults=$(this).formHash();
	var myLabelresults=$(this).labelList();
 
	currentForm += "
<ul>";
	$.each(myResults, function(i,item) {
		itemName = myLabelresults[i];
		if(itemName != undefined &amp;&amp; itemName != "") {
			currentForm += "
	<li>"+ itemName + ": " + item + "</li>
\n";
		}
	} );
	currentForm += "</ul>
";
	$("#outputContainerID").append(currentForm);
}

Comments Off

jquery Image Rotator

I had the opportunity to finally get my feet wet with jQuery recently and quite enjoyed the experience. One of the big parts of the site functionality that the designer was looking for was the ability to rotate through a potentially large number of logos, fading in and out from the set in order between three or four “image “slots” on the page.

What I came up with, building heavily on the work of Torsten Baldes and others, is nothing more than building an array of images within a container and then cycling through that collection by swapping items in a second array of image spots. This is the function that performs that work where “elements” is the array of images and “#logoimage”+slot is the id of a div from the list of divs we created based on how many images the user wants to display on the page at one time.

    $.imageslide.next = function(container, elements, settings, slot, addelement) {
 
		slot = slot + 1;
		if(slot > settings.count) {
			slot=1;
		}
		addelement = addelement + 1;
		if (addelement > elements.length-1) {
			addelement = 0;
		}
 
        if (settings.animationtype == 'slide') {
            $('#logoimage'+slot).slideUp(settings.speed, function() {
			$('#logoimage'+slot).empty();
			$('#logoimage'+slot).append($(elements[addelement]));
			});
            $('#logoimage'+slot).slideDown(settings.speed);
        } else if (settings.animationtype == 'fade') {
            $('#logoimage'+slot).fadeTo(settings.speed, 0, function() {
			$('#logoimage'+slot).empty();
			$('#logoimage'+slot).append($(elements[addelement]));
			});
            $('#logoimage'+slot).fadeTo(settings.speed, 1);
        } else {
            alert(settings + 'imageslide-animationtype must either be \'slide\' or \'fade\'');
			return false;
		}
 
        setTimeout((function() {
            $.imageslide.next(container, elements, settings, slot, addelement);
        }), settings.timeout);
    };

The script is invoked using

 		<script type="text/javascript">
			$(document).ready(
				function(){
					$('#slideImages').imageslide({animationtype: 'fade', speed: 750, timeout: 2000, count: 4 });} );
		</script>

and, in this case, addresses a container with an id of “slideImages” that contains a list of images.

You can download the script or see it in action if you’re so inclined.

Comments Off

Downloads and Response Headers

One of the developers ran into a problem with a servlet he was working on recently. In his app, he was displaying a link that would cause the app to deliver a text file that the user would be prompted to save.

All was well and good with Firefox with the following code:

private final static String MIME_TYPE = "text/plain";
ByteArrayOutputStream myDataOutputStream = (ByteArrayOutputStream)writeResultsToStream(myData);
response.setContentType(MIME_TYPE);
String filename = "downloadfile.txt";
response.addHeader("Content-disposition","attachment; filename=" + filename);
response.setContentLength(myDataOutputStream.size());
response.getOutputStream().write(myDataOutputStream.toByteArray());
response.getOutputStream().flush();

Because the data may contain confidential information, options like saving it out as a flat file were precluded. All well and good except that our in-house users who would be accessing the servlet primarily use Internet Explorer 6.

One of the other developers suggested the following change that fixed the issue when the servlet was running on Tomcat (which we use for our desktop development):
response.addHeader("Content-disposition","attachment; filename=" + filename); to
response.addHeader("Content-disposition","attachment;filename=" + filename);

Unfortunately, the problem reoccurred when the application was deployed on our Dev server running ATG Dynamo.

We determined that part of the problem also lay in some of the headers likely being passed from ATG, where this note was helpful:
“The MIME types “text/plain” and “application/octet-stream” are termed ambiguous because they generally do not provide clear indications of which application or CLSID should be associated as the content handler.”
http://msdn.microsoft.com/en-us/library/ms775147.aspx
Which I read to mean that it attempts to derive the file name from the URL, even though we’ve passed a name in the header.
Also, ‘The main problem is that Internet Explorer strictly interprets a combination of SSL (https) and “cache-control: no-cache” as “do not save encrypted pages to disk.”’
http://www.alagad.com/go/blog-entry/error-internet-explorer-cannot-download-filename-from-webserver

My suggestion (per my research) was to make the following additional changes to the header:

response.addHeader("Pragma", "public");
response.addHeader("Cache-Control", "max-age=0");

I haven’t dug into the respective application server headers and settings, but I’m definitely hoping to get the chance to compare the server configurations and the headers the browser receives.

Comments Off

Erlang or What I Learned at No Fluff Just Stuff

I just wanted to hit some of the high points from the No Fluff Just Stuff Java conference I attended over the weekend in April of 2008. A presentation I attended was on improving code quality and the presenter specifically commented that sending people to conferences is a good option. But he also made the point that the people who attend need to follow up with something like a trip report. His case in point was a company that was sending its “technical leaders” to the Java One conference, but they never reported back on the information they had gained and the things they had learned.

Not that I’m a technical leader by any stretch, but there was some really good stuff that I really want to share with everyone here. So what does that have to do with Erlang? And what the heck does Erlang have to do with UX?

Quite simply, it’s all about closures, something found in Erlang and going back to Smalltalk. That is, “…a closure is a function that is evaluated in an environment containing one or more bound variables.” (http://en.wikipedia.org/wiki/Closure_(computer_science)). Again, who cares? Well, not only are closures coming to Java (probably in Java 7 – http://fishbowl.pastiche.org/2003/05/16/closures_and_java_a_tutorial), but they already exist in Javascript. In fact, you may have used them without knowing what they are. It’s one of the ways to make Javascript object oriented since you can have this idea of functions as data and a whole host of other things. That’s part of what drives libraries (frameworks, call them what you will) like prototype, DOJO, YUI etc. http://www.jibbering.com/faq/faq_notes/closures.html

With all the talk around here about AJAX and SOA, I definitely had to get my fill of that. What I found fascinating were the side-by-side comparisons of the things you could do with DOJO, prototype and YUI (just to name a few of the Javascript frameworks out there). Tools like YSlow played a big part in looking at the overhead (page weight and all that) for using those frameworks and considerations on when to use them. There was a definite emphasis on when you might only use something on an intranet due to size constraints and only using stuff judiciously.

Another interesting thing was the difference of opinion on what constituted AJAX. One of the sessions was everything you ever wanted to know about JSON and that was seriously useful. You can do all the things that you might consider strictly AJAX-y (strict in the sense of using XML), but use JSON instead. Not only that, but using JSON actually performs better and carries less overhead since JSON converts directly to native Javascript objects like arrays. Consider this bit of sample code that calls a prototype.js function:

function validate3() {
    new Ajax.Request('/DesigningForAjax/json', {
        method: "get",
        evalJSON: true,
        sanitizeJSON: true,
        parameters: {zip: $F('zip'), city: $F('city'), state: $F('state'), secure: 'true'},
        onComplete: function(request) {
            showResults2(request.responseJSON);
        }
    })
}

Guess what? That’s JSON. But you probably knew that already. I didn’t and it really opened my eyes on how to do some really fascinating things and also some of the security issues inherent with Javascript and cross-site scripting (XSS). But JSON isn’t limited to JavaScript. It’s language-agnostic. In fact, there are a number of converters that can take JSON and convert it to XML or vice-versa. It’s equally simple to do the conversion on the client end and is a nicely defined (standards-based) way to convert stuff for use by Javascript. For example, if you want to do some things with an RSS feed on a page: http://blogs.msdn.com/shahpiyush/archive/2007/04/12/2103116.aspx (edit: previously linked to a project on John Resig’s site that’s no longer extant http://ejohn.org/blog/json-and-rss/).

Which leads me to the last session of the weekend, GIS for Web Developers. Which was pretty much a whirlwind (World Wind?) tour through all the things you can do with maps without using the Google Maps API. If you want to see how you can mash up maps to do some cool things, definitely check out OpenLayers:http://openlayers.org/

It gets even cooler if you run your own map server and everything you might want to know was covered in the session and can be as simple as deploying a WAR file on an application server. I’ll let you know when I get my custom maps up and running sometime.

We also covered a variety of things like tools to use for working with JavaScript and both Felix and John went to sessions for stuff like Spring and Maven. I also got to see some examples of rapid prototyping (live demos in the space of these hour and a half presentations of working sites with RESTful servlets and AJAX front ends) using tools like Grails.

If you’re interested in any of these topics and want to talk to me further about, I’d really enjoy that.

Incidentally, if you’re feeling left out, one of the presenters pointed out the Yahoo! Developer Network Theater wherein you can view, download, or subscribe as a podcast, to talks by some really amazing people. http://developer.yahoo.net/blogs/theater/

————————-
Previously posted on my internal work blog at Group Health on April 23, 2008 as part of a weekly UXTech build session.

Comments Off