Archive for the 'WebLinks' Category

Juicing Up Photo Viewing Experience: Part I

on this blog, on your wordpress site, or anywhere else. This series is a result of my recent craze with scripting/programming and photo ideas.

Screenshot of Fotobook Highslide

Previous Next Close
Fotobook Highslide - Mash up of Wordpress, Facebook Photos & Highslide JS

1. Photo Gallery
I tried a couple of wordpress plugins in the past: Gallery2, Simple Extended Gallery, Flickr….

They were perhaps good, but perhaps complex, lacking and I didn’t seem to like it. Then I created PhotoZip and even though Photozip plugin had its short comings (eg. perhaps a little slow due to batch processing), I’m glad Tim have the interest to improve it so much better than I would.

It is only recently I found out about Aaron Harp’s Fotobook, an integration/mashups of Facebook’s photos into your blog. So I tried it, and it works.

The integration is good (since I use facebook too), the layout neat, the configuration all done with much ease. It seems like it was something I tried looking so hard before, now that I found it, I love it. My photo gallery can be viewed by clicking on the Photos tab.

2. Highslide
Tim’s improved PhotoZip supports LightBox, so does Fotobook. No doubt it gives great effect and I like it too when used appropriately. Even my cousin’s portfolio uses it to enhance viewing experiences.

However, a reason why I don’t use it? Perhaps it was due to some negativity when I experienced it on some sites. But when I come across the Highslide javascript library, I thought I would use it for the following reason
1. At the first impression it reminds of LightBox- to expand an image in the same window.
2. However, unlike Lightbox, it is less obstructive. The background is not grayed out, and window can still scroll, and the expanded image can be dragged around.
3. It seems more reactive.

Not only it good to find the right tool for the right job, it good to find the best package available. So I’m using Highslide Wordpress plugin. Since fotobook was written in a way it was simple to customise it, I created a style/theme similar to Aaron’s lightbox style, except it works with highslide. Check out one of my gallery for example.

(Tip: You can use arrow buttons on your keyboard to navigate through the photos. You can also click/expand more than one photo at a time too.)

Click here to download Highlight Style for Fotobook.

Instructions:
Ensure you have Fotobook and Highslide plugin working.
Copy the highslide folder into fotobook styles folder
(eg. /wordpress/wp-content/plugins/fotobook/styles)
Select the highslide style under fotobook options.
View your photo gallery, test and enjoy!

Blog Posts on a Timeline

Its 2008, so wishing all readers here a very happy new year!

Yesterday, I touched about glancing back at a previous year (2007) , and one good way is to retrieve all the posts on your blog and place visualise it on a timeline. Of course there are other ways, say looking and sharing photo albums with friends could be a better way to bring back memories.

My Blog on the Timeline

I revisited Dandelife (A Social Biography Network?), and found that they have made more features and progress, compared to the last time I tried using it. Some features include importing “life streams” from flickr, facebook, blogs, feeds etc… anyway I didn’t manage to import my blog so I moved on.

Next I tired SIMILE Timeline plugin for Wordpress. Pretty good it seems, but I encountered couple of problems which i didn’t bother to troubleshoot and fix much. I considered implementing my own wordpress plugin when I got the idea to create a client which uses MetaWeblog API, so that it can work not only for my blog, but any wordpress blogs, blogger sites etc.

I will use the metaWeblog.getRecentPosts method to retrieve the post from the webservice. Since metaweblogapi is based on xmlrpc, I used the library phpxmlrpc. The data returned is then formatted as timeline xml to be used the timeline api (in my case I chose to truncate blog contents too). Pretty simple right?

Here’s my source code which I glued together quickly, isn’t too pretty, but works dandy for me. I’ve placed the script online, so you may want to try it.


<?php
/* by http://zz85.is-a-geek.com/ 31 December 2007 */
session_start();
if ($_POST['login']) {
	$reponse = blogconnect ($_POST['blogaddr'],1, $_POST['username'],$_POST['password']);
	if ($reponse->errno=="0") {
		$_SESSION['blogaddr'] = $_POST['blogaddr'];
		$_SESSION['posts'] = $_POST['posts'];
		$_SESSION['username'] = $_POST['username'];
		$_SESSION['password'] = $_POST['password'];
		showhtml();
	} else {
		echo "login failed";
		showform();
	}
} elseif ($_GET['js']) {
	$_SESSION['username'].$_SESSION['password'];
	printxml(blogconnect($_SESSION['blogaddr'],$_SESSION['posts'], $_SESSION['username'],$_SESSION['password']));
	exit;
}else {
	showform();
}

function blogconnect($link, $posts, $username, $password) {
	//requires xmlrpc.inc from http://phpxmlrpc.sourceforge.net/
	require_once('lib/xmlrpc.inc');

	// Using metaWeblogApi http://www.xmlrpc.com/metaWeblogApi
	$client = new xmlrpc_client($link);
	 $client->return_type = 'phpvals';
	 //$client->setDebug(1);

	 $params[] = new xmlrpcval("n/a");
	$params[] = new xmlrpcval($username);            //your wordpress login
	$params[] = new xmlrpcval($password);
	$params[] = new xmlrpcval($posts);
	 $msg    = new xmlrpcmsg("metaWeblog.getRecentPosts",$params);
	$response = $client->send($msg);
	return $response;
}
function printxml($response) {
	header('Content-type: text/xml; charset=utf-8');
	echo "<data date-time-format=\"iso8601\">";
	foreach ($response->val as $entry) {
		/*
		['dateCreated']
		['userid']
		['postid']
		['description']
		['title']
		['link']
		['permaLink']
		['categories']
		['mt_keywords']
		['wp_author_display_name']
		['date_created_gmt'] -8
		*/

		$description = htmlentities (substr($entry['description'],0,255)."...");
		?>
<event
        start="<?=$entry['dateCreated'];?>"
        end="<?=$entry['dateCreated'];?>"
	link="<?=$entry['link'];?>"
        title="<?=htmlentities($entry['title']);?>"
        >
	<?=htmlentities ($description);?>
        <?=htmlentities('<br/>by '.$entry['wp_author_display_name'].'');?>
</event>
		<?php
	}
	echo "</data>";
}

function showform(){
?>
<form method="post">
Blog Address: <input name="blogaddr" value="http://yoursite/blog/xmlrpc.php" size="40"/><br/>
No. of posts: <input name="posts" value="100" /><br/>
Username: <input name="username" /><br/>
Password: <input name="password" type="password" /><br/>
<input name="login" type="hidden" value="1"/>
<input type="submit"/>
</form>
<a href="http://zz85.is-a-geek.com/">http://zz85.is-a-geek.com/</a>
<?php } 

function showhtml() {
?>
<html>
  <head>
  <title>Wordpress (MetaWeblog) API and Timeline API Integration</title>
   <link rel='stylesheet' href='http://simile.mit.edu/timeline/docs/styles.css' type='text/css' />
    <script src="http://simile.mit.edu/timeline/api/timeline-api.js" type="text/javascript"></script>
    <script>
    	var tl;
	var eventSource = new Timeline.DefaultEventSource();

	function onLoad() {
		createTimeline();
	}

function createTimeline() {
  var bandInfos = [

   Timeline.createBandInfo({
        width:          "25%",
	//timeZone: 8,
	eventSource:    eventSource,
        intervalUnit:   Timeline.DateTime.DAY,
        intervalPixels: 50
    }),
    Timeline.createBandInfo({
	showEventText:  true,
	eventSource:    eventSource,
	width:          "60%",
        intervalUnit:   Timeline.DateTime.WEEK,
        intervalPixels: 100
    }),
    Timeline.createBandInfo({
        width:          "15%",
	eventSource:    eventSource,
	showEventText:  false,
        intervalUnit:   Timeline.DateTime.MONTH,
        intervalPixels: 95
    }),

  ];

  // sync bands
  bandInfos[1].syncWith = 0;
  bandInfos[1].highlight = true;
  bandInfos[2].syncWith = 1;
  bandInfos[2].highlight = true;

  tl = Timeline.create(document.getElementById("my-timeline"), bandInfos);

  Timeline.loadXML("<?php echo $PHP_SELF; ?>?js=1", function(xml, url) { eventSource.loadXML(xml, url); });
}

var resizeTimerID = null;
function onResize() {
    if (resizeTimerID == null) {
        resizeTimerID = window.setTimeout(function() {
            resizeTimerID = null;
            tl.layout();
        }, 500);
    }
}

  </script>
  </head>
  <body onload="onLoad();" onresize="onResize();">
  	<h2>Laying Out a Year (2007) Full of Blog Posts on the Timeline</h2>
	Using Simile Timeline Library, Wordpress API/MetaWeblog API, and PHP to translate that into Timeline XML. <br/>
	<div id="my-timeline" style="height:450px; border: 1px solid #aaa"></div>
	<a href="http://zz85.is-a-geek.com/">http://zz85.is-a-geek.com/</a>
  </body>
</html>
<?php } ?>

So now, I can have twitter and blog posts displayed on the timeline. If I have the time, calendars and metadata would be next. But there’s also too many other data sources around. Emails- run a search on gmail. On handphone, view the calendar data and smses for a year. Photos: Run time view in Picasa. Diary: read. Gps: Color tag them on googlemaps? Too many! so I’ll be satisfied with the blogs posts on the timeline for now.

Happy revisiting your posts!

Timeless Belt Of Time: How I Integrated Twitter in Timeline

using JSON, PHP, CURL, JS, and of course HTML, and APIs of Simile Timeline and Twitter.

Timeline Twitter Mash up
Looks a little like a seismograph?

My first little personal project in this year was dealing with time, used by myself and view daily by my colleges in TAD. Later in the year, I brainstormed several other ideas that I hope to implement as a web 2.0 application. I stumbled on the Simile Timeline project earlier, thought it was a good idea, but never tried it until today. But it was also the fun using Twitter that sparked the interest to use Timeline and to integrate them.

However, given the large interest in twitter and mash ups, I would have expected someone else to have done before. Still there are handful of resources with the knowledge required to hack the pieces together. So let me outline what I did.

1. Prepare a php script to call Twitter’s API to retrieve Twitter posts using CURL. To do as little coding as possible, I decided to use JSON format (over XML), pass it self as an object into the (html) client’s javascript method.
2. The javascript method would iterate each of twitter’s data then generate the events in Timeline’s format.
3. Initialize and run Timeline’s API to render.

twitter.php The server side script.


<?php
/* 29 Dec 2007, http://zz85.is-a-geek.com/ */
// Edit your twitter's username and password
$username = 'USERNAME';
$password = 'PASSWORD'; 

// The twitter API address
//$url = 'http://twitter.com/account/archive.json'; // Each archive API call could return 80 statuses,
								// but there seem to be an error on Twitter's side so I'll use
								// the User timeline call which returns only the last 20 posts.

$url = 'http://twitter.com/statuses/user_timeline.json';

$curl_handle = curl_init();
curl_setopt($curl_handle, CURLOPT_URL, "$url");
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERPWD, "$username:$password");
$buffer = curl_exec($curl_handle);
curl_close($curl_handle);

echo "timeline_data($buffer);"; // timeline_data is the javascript method to be execute
?>

time.html The Client side html

<html>
  <head>
  <title>Timeline API and Twitter API Integration</title>
   <link rel='stylesheet' href='http://simile.mit.edu/timeline/docs/styles.css' type='text/css' />
    <script src="http://simile.mit.edu/timeline/api/timeline-api.js" type="text/javascript"></script>
    <script>
    	var tl;
	var eventSource = new Timeline.DefaultEventSource();

	function onLoad() {
		var scriptTag = document.createElement('script');
		scriptTag.src = "http://CHANGEME_DOMAIN/twitter.php"; // Change to URL of your php script
		document.body.appendChild(scriptTag); // Runs the contents from the URL being called as javascript
	}

function createTimeline() {
  var bandInfos = [

   Timeline.createBandInfo({
        width:          "65%",
	timeZone: 8, // I have to adjust the time as I live in GMT +8
	eventSource:    eventSource,
        intervalUnit:   Timeline.DateTime.HOUR,
        intervalPixels: 80
    }),
    Timeline.createBandInfo({
	    showEventText:  false,
	eventSource:    eventSource,
	width:          "20%",
        intervalUnit:   Timeline.DateTime.DAY,
        intervalPixels: 70
    }),
    Timeline.createBandInfo({
        width:          "15%",
	showEventText:  false,
        intervalUnit:   Timeline.DateTime.MONTH,
        intervalPixels: 100
    }),

  ];

  // sync bands
  bandInfos[1].syncWith = 0;
  bandInfos[1].highlight = true;
  bandInfos[2].syncWith = 1;
  bandInfos[2].highlight = true;

  tl = Timeline.create(document.getElementById("my-timeline"), bandInfos);
   //tl.loadJSON("cubism.js", function(json, url) { eventSource.loadJSON(json, url); });
}

var resizeTimerID = null;
function onResize() {
    if (resizeTimerID == null) {
        resizeTimerID = window.setTimeout(function() {
            resizeTimerID = null;
            tl.layout();
        }, 500);
    }
}

function timeline_data(tjson) { // method called after response of twitter.php is exectured
	for (entries in tjson) {
		 var dateEvent = new Date(tjson[entries]["created_at"]);
		 var urlbase = 'http://twitter.com/' ;
		var evt = new Timeline.DefaultEventSource.Event(
		dateEvent, //start
		dateEvent, //end
		dateEvent, //latestStart
		dateEvent, //earliestEnd
		 true, //instant
		 tjson[entries]["text"], //text
		 '<a href="'+ urlbase + tjson[entries]["user"]["name"] + '/">' +
		 '<img src="' + tjson[entries]["user"]["profile_image_url"] + '" />'
		 + tjson[entries]["user"]["name"] +'</a>' + ' '
		  + tjson[entries]["text"] +
		 '<br /><a href="' + urlbase + 'statuses/' +tjson[entries]["id"]+'">Source:</a>'+ tjson[entries]["source"] + ''
		 //description
		);
		eventSource.add(evt);
	}
	createTimeline();
 }    </script>
  </head>
  <body onload="onLoad();" onresize="onResize();">
  	<h2>Zz85 Integration Test of Timeline API with Twitter API</h2>
	<div id="my-timeline" style="height:450px; border: 1px solid #aaa"></div>
	<br />version 1 by <a href="http://zz85.is-a-geek.com/">http://zz85.is-a-geek.com/</a>
  </body>
</html>

Well, I hope this would work for you, or at least help you to do something better. At least if you managed to do what I did, you would be able to visualise what you were doing on the dynamic scrollable timeline. Of course, the timeline javascript library issnt perfect, and I wish there were features like: adding events by clicking on the timeline, dragging the duration, zooming in&out and dragging the events around. Anyway I have some ideas, that I’m likely not to do it, but its implementable.

  • Integrate Photos eg. Flickr/Fackbook + Blogs + MAps + …
  • Integrate Calendars (eg. Google Calendars)…
  • Automatic Widening/Narrowing
  • Import and usage of own database with metadata
  • Layered Rows for Different events.
  • Integrate with other time applications like countdown counter
  • Integrate ToDo List

Have timeless fun! Drop me a note if you manage to do something satisfying after reading this article, or if you have some other cool ideas too =)

Further Readings

  1. Tutorial on using Timeline
  2. About JSON
  3. Posting to Twitter using PHP and CURL
  4. twitter api
  5. Google’s method of dynamic json data import
  6. a json inspector
  7. Creating timeline from (blog) feeds

Activity & Status Streams

Perhaps some keep a journal so they can remember what they have done in the past. Perhaps many nowadays use a blog for that purpose too. Twitter, which appeared in my previous post, a social networking site based mainly on activity streams could now be the synonym for “what am/was/are I/you doing”.

Twitter Ninja

Twitter’s API allows many implementation of getting twitter service, eg. this twitter balloon.

A similar feature exist in Facebook, and is perhaps the more popular among many is to announce their status or what they are doing. Recently I read that the first thing one would do after a relationship break off is to change their status on Facebook. Perhaps you are not that extreme, but might still be guilty of complaining, or showing off via your online messaging nick, status or personal message.

Talking about streams, no one can deny the power of RSS feeds, whether its a blog, twitter, or facebook, they all have them. And my preferred method for reading blogs, and my favorites sites.

And lastly, even Google must have realise the potential of these lifestreaming activities and acquired Twitter’s competitor Jaiku. Even though there are already a couple of Google Services eg. Maps/Earth + Twitter Mashups, it would be interesting to see what Google has in store for all of us (perhaps integrate gcalendars too).

Visitors Around The World

Alright, for a little fun with toys here’s a tracker which shows where in the world, my web visitors are from on the world map. If you have noticed too, the wordpress engine, plugins and themes I’m using now are updated.

Here’s the statistics page and map from http://whos.amung.us/.