Posts Tagged ‘Javascript’

Jeff asked about sortable tables…


And how I would do one with Javascript.. so I did. Here's a list of some books I've read semi-recently. The scores are not super well-considered.

show 4 per page
show all

You can have more than one per page, and it's easy to add them. This line of code will do it:
var table = new SortableData( data, headings, settings );

  • data is a list of data objects. Each object corresponds directly to a row in the table. An example of the data object:
    { author: 'Alastair Reynold', score: 8, book: 'Chasm City' }

     
  • headings is an array of data objects. Each describes a column of the table. An example of a heading data object:
    { key: 'author', value: 'Author', type: 'String' }

     
  • settings is an object whose values are used to overwrite the SortableData object's defaults. You can specify fields like page_size, and page. An example of a settings object:
    { page_size: 5 }

     

The SortableData.js file must be included, as it describes the object.

So for each table we instantiate a new SortableData object. That guy takes care of writing and updating HTML, and the paging. But how do we reference the object for the necessary onclick events (clicking a heading to sort by a column, or a page link to view that page)? I chose to do is maintain a static instances array within SortableData. On instantiation, each object assigns itself a unique ID, and adds itself to the instance array.
Static SortableData functions handle the click events. Each function takes, as one of its parameters, a SortableData instance ID and calls the appropriate functions on the instance with that ID. And it even works! First try, in fact!

Then some CSS to style the HTML outputted, and that's it! We're done.

It'd be easy to write a wrapper object that loads data via AJAX, ideally receiving appropriately formatted JSON, but I am pretty lazy. And really, what use do I have for a sortable table?

A Flash gallery frontend

 

I wrote a flash gallery front-end a week or so back. There’s a picture of it above. Just kidding it’s an actual instance! Some of the thumbnails might take a while to load. That is because they are not thumbnails but giant, giant images.

It uses ExternalInterface and Javascript to display the descriptions in the HTML. I’ll post the relevant code with an explanation next time, but let me tell you right now – having more than one gallery per page doesn’t pose a problem ( programmatically ).

The gallery is described by XML, and added to a page with a simple Javascript call.

Using ExternalInterface to communicate between Javascript and Actionscript 3: Or, I want Paypal buy now buttons in Flash

The statement that Flash TextAreas ( TextFields, etc. ) can display HTML can be deceptive. They can certainly display a subset of HTML. But this is a very limited subset, and for good reason.

While it’s easy to understand why this is the case, it can still be frustrating. Say, for example, you’re building an image gallery and would like to have some of Paypal’s buy-now buttons in image descriptions. A Paypal button can be perhaps a deceptive thing – it’s tiny forms whose only visible element is the buy-now image – which cannot easily be accurately displayed by Flash.

But don’t worry, especially if your Flash will be displayed within a browser, for that is a thing built to display HTML. In fact, it’s one of its primary and most useful purposes.

The trick here is to get Flash to communicate to the browser what HTML to display, and how to do it. It turns out this is relatively easy to accomplish.

Here we make the following assumption: Your SWF file knows what HTML to display, and when. In my mind, this is a pretty safe assumption to make.

Okay, so I’ll break the method down into steps:
Step 1: Flash tells javascript to display some HTML.

Okay that’s about it.

You’ll have to write the Javascript to display the HTML where you want it, but that’s easy enough.

Flash provides an External Interface class ( flash.external.ExternalInterface ) that allows for communication between Actionscript 3 and the Flash Player container – in this case the web page and its Javascript.

You’ll have to include the ExternalInterface in your class file, and there are some checks you can (and probably should) diligently perform, but the important Actionscript 3 is:

import flash.external.ExternalInterface;
...
var html:String = "

This is some html.

";
if (ExternalInterface.available) {
	ExternalInterface.call("writeHTML", html );
}

The Javascript function writeHTML will be called with the parameter html. So it’d probably be good if there was such a function:

function writeHTML( str ) {
	document.write( str );
}

A better Javascript function would be, well.. better.. but, you know, brevity and all that.

That’s basically all there is to it. Next time blog I’ll provide a more concrete example of ExternalInterface in use (one that uses multiple parameters in its Javascript call). And if you want, post the applicable code?

As a side note: if you’re loading the HTML via XML, always remember to wrap it in CDATA.

A sliding drawer type thing feat. jquery

A while ago a friend of mine realized he had so many employees that listing them all on a single page would make for one of great length. A strange problem to have.
Using some simple CSS and Javascript we can hide the bulk of the information and show only what is necessary. You know, for increased usability and all that:

A definitions list provides the perfect data structure for our purposes:

A bird
This is a picture of a bird sitting an a tree, and looking quite proud of that.
A cave
This is the description of the cave.. Tor lives here, and is a Zombie.
A zombie
Poker was pretty popular for a while, even the zombies got into it.
Bobby
This is a picture of bobby. I actually have a giant version of this framed on a wall over to the right.

For each entry, we have a title (dt) and the data itself (dd). After the definition list, we have an empty div identified as info_container. This is where we’ll display the appropriate data.

The HTML itself is pretty minimal and hopefully clear, which is just the way we like it.

The javascript is a bit more complicated:

google.load("jquery", "1");	// We want jquery... let's say version 1?
google.setOnLoadCallback( // Once google tells us JQuery has finished loading, we can do some stuff
	function() { // This is the annonymous function google will call-back
		$('dl.drawerify dt').click( //Every time we click a dt in the drawerified definitions list
			function() {
				var new_one = $('dl.drawerify dt').index(this);
				if (selected == new_one) return;  // Don't do anything if we've clicked on the one that's already open
				$('dl.drawerify dt:nth('+selected+')').removeClass('current');
				selected = new_one;
				$(this).addClass('current');
				show_info($(this).next('dd').html() ); // Fill the info_container
			}
		);
		$('dl.drawerify dt:first').click(); // Initially, we want the first one shown (so we just fake-click on it)
	}
);

var selected = -1; // The index of the currently displayed entry in the definitions list

// Fill the info_container with the appropriate data
function show_info( desc ) {
	var container = $('#info_container');
	if (container.html().length > 0) {

	// Animate the drawer retracting
	  container.animate({
		width: "0px"
	  }, 300, "swing", function() { container.html(''); show_info( desc ); } );

	} else {
		container.html("
" + desc + "
"); // Fill the container // Animate the drawer extending container.animate({ width: "250px" }, 300, "swing" ); } }

The first line is us telling Google that we want to use JQuery. We could just include JQuery ourselves, but man we are way too lazy for that.

We want only one dt tag to have the current class applied to it at a given time. Lines 8 removes the class from the previously selected dt and line 10 adds it to the new one, using various jquery selector strings.
In line 11, we pass the contents of the dd immediately following the current dt to the show_info function.

Now comes the animation part. Jquery provides a function called animate. We can use it to animate things!
Starting at line 23, the logic goes a little something like this:
If there there is already information in the info_container, we want to retract the drawer. If not, we’re good to extend it once we’ve filled it with the new content.

A lot of jquery functions take callbacks as optional parameters, which is useful for us because once a drawer has closed we’d like to clear it of content and then fill it with new content and open it. That last part sounds an awful lot like what we’d do anyway if the drawer were empty. So maybe all we really have to do is clear it of content, and then have the show_info function call itself with its original parameters? Sounds good to me, and we can totally do it with another anonymous function. That’s what line 28 is about.

And now the Javascript is done! That wasn’t so complicated? I am a big fan of anonymous functions.

Next comes the CSS. This is where we’ll define what the drawer-thing looks like:

dl.drawerify, #info_container {
	height: 108px;
	background-color: #fff;
	padding: 10px;
}
dl.drawerify {
	width: 140px;
	float: left;
	margin: 0px;
}
dl.drawerify dt.current {
	color: #ffffff;
}

dl.drawerify dd {
	display: none;
}
dl.drawerify dt {
	cursor: pointer;
	font-weight: bold;
	background: #324e63;
	color: #b3c4d2;
	font-family: arial, verdana;
	padding: 3px;
	padding-left: 10px;
	margin-bottom: 1px;
	font-size: 16px;
}
dl.drawerify dt:hover {
	background-color: #233544;
}
#info_container {
	width: 0px;
	float: left;
	overflow: hidden;
	font-family: verdana;
	font-size: 8pt;
	padding-left: 0px;
	color: #324e63;
}
#info_container .inner {
	width: 220px;
}
#info_container img {
	margin-right: 10px;
	float: left;
}
body {
	background-color: #EDEFF0;
}

The most important parts of the css are:
Line 7 and 8 let us display info_container to the left of the definitions list, rather than below it.
Line 19 tells the browser to display the little hand icon when you mouse-over the definition titles instead of an arrow (like when you mouse-over a link).
Line 35 and 42 allow the animation to work nicely. 35 tells the browser to clip anything that exceeds the dimensions of the info_container, and 42 sets the width of the inner div. By setting it, we prevent its width from automatically changing to fit within info_container. That way its content doesn’t get re-arranged during the animation.

The complete code is available, though everything important can be found above.

.