Getting vCard info into a QR code using the Google Chart API

How to get vCard info into a QR code using the Google Chart API? This question has been coming up occasionally and it can be a little quirky. I thought I might document my process of making this work with the Google Chart API.

1. Create the unencoded vCard info. Sample Below:

BEGIN:VCARD VERSION:3.0
N:Clark;Jason
FN:Jason Clark
ORG:MSU Library
TITLE:Team Leader/Digital Initiatives Librarian [Associate Professor]
TEL;TYPE=WORK,VOICE:(406) 994-6801
EMAIL;TYPE=PREF,INTERNET:jaclark@montana.edu
URL:http://www.jasonclark.info
REV:20111013T195243Z
END:VCARD

2. Run the unencoded vCard info through a utility or programming function. In this example, we are using the online “URI Encoder / Decoder” tool http://andrewu.co.uk/tools/uriencoder/. Some common functions in programming languages that would do the same thing are: Server.URLEncode() in ASP, urlencode() in PHP, and encodeURI() in Javascript. After pushing the unencoded vCard string through the “URI Encoder / Decoder” tool, we get a resulting string like this:

BEGIN%3AVCARD%0D%0A%09%09
VERSION%3A3.0%0D%0A%09%09N%3AClark%3BJason%0D%0A%09%09
FN%3AJason+Clark%0D%0A%09%09ORG%3AMSU+Library%0D%0A%09%09
TITurLE%3ATeam+Leader%2FDigital+Initiatives+Librarian+%5BAssociate+Professor%5D%0D%0A%09%09
TEL%3BTYPE%3DWORK%2CVOICE%3A%28406%29+994-6801%0D%0A%09%09EMAIL%3BTYPE%3DPREF%2CINTERNET%3Ajaclark%40montana.edu%0D%0A%09%09
URL%3Ahttp%3A%2F%2Fwww.jasonclark.info%0D%0A%09%09
REV%3A20111013T195243Z%0D%0A%09%09
END%3AVCARD

A potential gotcha here is the URL value in the vCard. Make sure the URL value in the vCard is encoded and has changed from

URL:http://www.jasonclark.info

to something that looks like:

URL%3Ahttp%3A%2F%2Fwww.jasonclark.info%0D%0A%09%09

3. Next, we place the encoded string in the Google Chart API to generate the QR code. Put your encoded vCard string in the URL below after the “&chl=”. For more info, see the online wizard tool and documentation for the Google Chart API. Check the link below to see the generated QR code.

http://chart.apis.google.com/chart?chs=200x200&cht=qr&chld=|0&chl=BEGIN%3AVCARD%0D%0A%09%09VERSION%3A3.0%0D%0A%09%09N%3AClark%3BJason%0D%0A%09%09FN%3AJason+Clark%0D%0A%09%09ORG%3AMSU+Library%0D%0A%09%09TITLE%3ATeam+Leader%2FDigital+Initiatives+Librarian+%5BAssociate+Professor%5D%0D%0A%09%09TEL%3BTYPE%3DWORK%2CVOICE%3A%28406%29+994-6801%0D%0A%09%09EMAIL%3BTYPE%3DPREF%2CINTERNET%3Ajaclark%40montana.edu%0D%0A%09%09URL%3Ahttp%3A%2F%2Fwww.jasonclark.info%0D%0A%09%09REV%3A20111013T195243Z%0D%0A%09%09END%3AVCARD

4. If everything works, the Google Chart API returns a link to a QR code image with the vCard info encoded. Place this URL in an HTML <img> tag and you’ll have a QR code on your site that will have vCard data. Note: You will need to add your specific contact vCard data in Step 1.


Mapping your location with Google Static Maps API (tutorial)

The Google Static Maps API  (code.google.com/apis/maps/documentation/staticmaps/) allows for a dead simple way to embed maps showing a specific location for mobile and desktop environments. The real advantage of the Google Static Maps API is that the embed comes in the form of an HTML image <img> tag. In this quick codelab tutorial, I’m going to show you how to create a static map and set a location using the Google Static Maps API. If you have a familiarity with HTML, the markup for the image should be familiar.

<img src=”http://maps.google.com/maps/api/staticmap?center=Bozeman,MT&zoom=13&size=310×310&markers=color:blue|45.666671,-111.04859&mobile=true&sensor=false” />

As I mentioned earlier, it is a simple <img> tag with a call linking into the Google Static Maps API. In order to assign a specific location we need to pass a few parameters to the Google Static Maps API. Included among the customizations:

  1. A central location for the map
  2. A zoom level for the map
  3. A size for our map image
  4. A marker color and position using latitude and longitude
  5. Set the map to display for mobile settings without a sensor

The necessary pieces to enter are a central location and your specific latitude and longitude. Enter your hometown for the central location in the format of {city, state or principality}. To get your latitude and longitude, visit gmaps-samples-v3.googlecode.com/svn/trunk/geocoder/getlatlng.html and type in your library address. Copy the latitude and longitude values that are returned. Enter these position values as a comma separated string {latitude,longitude}.

Here’s the image src= markup with cues for where to add your values.

http://maps.google.com/maps/api/staticmap?center={YOURHOMETOWN}&zoom=13&size=310×310&markers=color:blue|{YOUR LATITUDE/LONGITUDE}&mobile=true&sensor=false

Once you have the link filled out add it to your image <img> tag on a live HTML page and you will have a local map to your library or any other specific location.

msu library bozeman mt


Mobile Web Design – Working Code, Tips, Best Practices

Taking a web site to the small screen comes with a host of considerations: device width, available bandwidth, touch versus click interfaces, browsers with limited functionality, etc. At the same time, the simplicity of these mobile browsing environments lowers the barrier to entry for developers. Some basic HTML and CSS is all that is required to get started. In my research, I have learned a few things and decided to put the learning into action by creating a mobile web template available for anyone to download, remix, and reuse.

Demo: http://www.lib.montana.edu/~jason/files/m/
Download: http://www.lib.montana.edu/~jason/files/m.zip
Read Me: http://www.lib.montana.edu/~jason/files/m/_readme.txt

The above template is using HTML, CSS, Javascript, and PHP, but you could substitute any server side language for the programming logic. I also have it in my head that I can build an even simpler template with just HTML and CSS. I’ll keep people updated…

Here are some tips, best practices, and design conventions I learned along the way.

  • One column is a design convention worth following (See m.facebook.com, or m.youtube.com, or m.twitter.com).
  • Pick the essence or core pieces of your site to deliver to your mobile users. Think abridged version.
  • Follow the “m” URL conventions (m.delicious.com OR amazon.mobi OR lifeonterra.com/m/).
  • Minify and optimize your CSS (See Clean CSS ).
  • Minify and optimize your javascript (see JSLint).
  • Plan for low bandwidth – Keep images close to 1KB or under.
  • Test on multiple mobile browsers and emulators.
  • Don’t plan on javascript being available – the above template still works when it’s turned off.
  • Build your app so that it loads only necessary data when requested (Use Ajax or Server-Side includes).

I’m interested in any feedback or questions so please share in the comments. I’ve also created a more robust mobile application example for TERRA: The Nature of Our World available at lifeonterra.com/m/. If anyone is interested, I’m happy to share some of that code as well.


Blip.tv API and YouTube API Code Samples – Library Mashups

My chapter “Blip.tv and Digital Video Collections in the Library” for the recently released Library Mashups edited by Nicole Engard was in need of some code samples. I wanted to show how to use the APIs I kept mentioning in the writing which focused on the digital library mashup of TERRApod. So… here they are in their basic, rudimentary glory.

The complete code is available for download from my code archive. Think of these examples as the raw materials for building mashups with the blip.tv API and YouTube API. The blip.tv example relies on PHP 5, but I made the YouTube PHP4 compatible and you could adapt the code from there for the blip.tv API. I also included some CURL code in the comments of the files just in case your host requires it. If you have questions or improvements, drop a comment.

A quick word about the book: If you are at all interested in mashups and web services, take a closer look. The book covers one profession’s (the librarian) application of web services to library data problems. Contributions from industry leader’s like John Blyberg, Ross Singer and Karen Coombs make this an interesting read for anyone interested in how web services and open data are changing the nature of web development for libraries.

<end bookplug />


Computers in Libraries 2009

Computers in Libraries starts tomorrow and it’s always a great time. I arrived in DC earlier today from an uneventful flight which is always a good thing.  Met up with Karen Coombs and Michael Sauers for some SuperHappyTerrific sushi and now I’m collecting my thoughts regarding my upcoming workshops and presentation.

Web Services for Libraries (with Karen)
Sunday, March 30 from 1:00PM – 4:00 PM
Delicious for subject guides, Flickr for library displays, YouTube for library orientation …Mashups and APIs (application programming interfaces) are becoming staples of modern web design. Libraries, as repositories of data, have a wealth of information that could be placed within the mashup context. With new tools and scripts available daily, it’s becoming easier and easier to bring pieces of the web together and enable users to find and build new web services with library data. This workshop focuses on what an API is and what it can do, the standard components of web services, how to build a simple mashup with JavaScript, how to work with PHP to consume a web service and create a mashup, what web services and mashups mean for libraries, and how to start consuming and creating web services for your library with available tools and scripts. Come learn how open data standards and a little “know-how” can change your library services. Hear what others are doing and what you can do too. (Participants should be comfortable with HTML markup and have an interest in learning about web scripting and programming.)

Widgets, Gadgets, and Mobie Apps for Libraries (with Karen and Michael)
Sunday, March 30 from 9:00 AM – 12:00 PM
As web content continues to grow and the noise-to-signal ratio increases, it has become important for libraries to find ways to get into users’ common web paths: the social networking sites such as Facebook, the web portals such as iGoogle, learning management systems such as Blackboard, even mobile devices such as the iPhone. Our panel of experts looks at creating widgets or gadgets that allow users to have basic library search and browse functions in these new user environments free from the catalog or library website. They demo and teach how to build live applications that provide gateway searching for library journals, books, articles, and much more. Come learn how to play in these new environments and to give users options for searching and consuming library materials in their own learning spaces.

The Portable Library: Going “Atomic” with Library Web Services
Monday, March 30 from 10:30 AM – 11:45 AM
There is an opportunity for libraries to braodcast into our users’ common web paths (like Facebook and iGoogle) and to create mobile library apps that allow users to have basic library search functions in these new user environments.  Live applications from MSU Libraries illustrate: a Google Gadget that allows gateway searching for library journals, books, and articles and a series of OpenSearch plugins that let patrons search library content from within the web browser. Come learn about the simple steps you can take to make these widgets and research tools happen at your library.

Presentation files and handouts for all sessions are available at http://www.lib.montana.edu/~jason/talks.php.

Demos and “Downloadables” for all sessions are available at http://www.lib.montana.edu/~jason/files.php.

I’m also trying to track the official tags and hashtags for the conference.  It’s looking like “#cil2009” for twitter and “cil2009” for all other tagging.  See everyone around Crystal City or teh Internets…


Unix Global Find and Replace (using find, grep, and sed)

Finding and replacing strings and characters can be a dicey operation for a web developer. Too much can lead to breaking your web site. Too little can lead to missing that piece of HTML needing to be updated or deleted. Many tools exist that can help you in the process – Dreamweaver, Homesite, and many text editors have powerful interfaces for searching and replacing. (E.g., Use cntrl-f on windows or cmd-f on mac to see the Find and Replace window in Dreamweaver.) But there’s some really great functionality on the command line for Unix/Linux users that shouldn’t be overlooked. I’ve been experimenting with a procedure for making these global matches and replaces within the Unix shell environment and I wanted to document the process somewhere. This seems like as good a place as any…

Important: All the commands below must be run from the shell environment on a Unix or Linux system. If you aren’t sure what I’m talking about, check the wikipedia reference for shell.

Step 1: Find the pattern needing to be replaced or updated, print out files needing change

find . -exec grep ‘ENTER STRING OR TEXT TO SEARCH FOR’ ‘{}’ \; -print

*Note: I’m using the “find” and “grep” commands to search for a matching pattern which will print out a list of files and directories that need changes. If I’m at the top level of my web site the “.” in the find command will search for the pattern down through any directories below. On a large site, the process can take some time.

Step 2: Move/copy files into test directory to test expression; preserve owners, groups, timestamps

cp -p -r test test-backup

*Note: These directories would be named according to the directories or files you need to change based on the results from Step 1. The “-p” will preserve owners groups and timestamps in the copied directory. The “-r” will copy recursively down through any associated sub-directories. I do this so I can compare the new directory to the original directory after I’ve test run the global changes.

Step 3: Run test on find and replace expression in /test-backup/ directory

find . \( -name “*.php” -or -name “*.html” \) | xargs grep -l ‘ENTER STRING OR TEXT TO SEARCH FOR’ | xargs sed -i -e ‘s/ENTER OLD STRING OR TEXT TO REPLACE/ENTER REPLACEMENT STRING OR TEXT/g

*Note: I’m using the “find .” command to search for .php and html files in the current working directory as I only want to target the files that need to be touched (you should change according to your requirements), next I’m piping that result to the “grep” command which searches for the string or text specified and holds only the matched files in memory, and finally I’m passing the grep result to the “sed” command which matches the string or text and replaces it with the new string or text value.

Step 4: Test files and applications to ensure changes didn’t break functionality and that owners, groups, timestamps were preserved

Step 5: After testing, run expression from Step 3 in ALL the directories or files needing the changes. Delete /test-backup/ directory

Steps 1 and 3 are the heart of the matter. I’m learning the power of these commands, so I’m pretty cautious about backing up and testing on directories and files that aren’t live. Once I have the expression dialed in, I’ll run it on a more global scale. So, there you have it – my find and replace process in a nutshell. Use at your own discretion and feel free to share your thoughts in the comments.


Ajax Workshop – Internet Librarian 2007

My preconference,”AJAX for Libraries”, with Karen Coombs went really well. It’s always great working with Karen. She’s cool, composed, and “wicked” knowledgeable. For the second year in a row, we had a great group of participants. It’s nice to see a growing interest in emerging web programming frameworks and how they might be applied to libraries.

Here are the updated slides and links:

“AJAX for Libraries” Presentation
“AJAX for Libraries” Handout (Code Samples and Explanations)
“AJAX for Libraries” Code Downloads

And some additional examples of libraries using AJAX:


Globally match and replace text or string with MySQL query

In doing some research looking into possible ways to batch replace MSU Library URL strings in our various MySQL databases, I was able to construct this little nugget that will do the trick:

UPDATE table_name SET column_name = REPLACE(column_name, ‘old_string/text’, ‘new_string/text’);

A quick explanation:

table_name is the database table you need to edit.
column_name is the database table column name to edit.
old_string/text is the original string or text to match and replace.
new_string/text is the new string or text you want to add.

It’s short, sweet, and delightfully efficient. The longevity and active development around MySQL and SQL always surprise me. If you have a business problem, chances are there is a function or built procedure already in the code ready to answer the problem.

Tips and tricks just like this can be found pretty regularly by trolling the MySQL manual and forums. Another method for keeping up and learning is “tagwatching” on del.icio.us. Some possibilities for watching the tag “mysql”:

HTML page: http://del.icio.us/tag/mysql

RSS feed: http://del.icio.us/rss/tag/mysql

That’s right. With that last RSS URL, you can subscribe to a tag and watch as the latest posts come into your feedreader of choice. (del.icio.us has a feed for all of its tags.) Good stuff for keeping the learning going.


Anatomy of a Function

It’s been a little while since my last post. My recent work schedule and Turkey Day played a part in that. I’ve been working .com hours on a super cool project. (I mentioned the TERRA group in an earlier post.) I’ve learned so much in the last couple of weeks. It’s amazing what a hard deadline and a shifting set of requirements will do to your web programming skills. All the hard work is about to bear fruit as as the new TERRA web site is about to go live. Have a look at a different kind of digital library.

But, that’s not the point of this post… I wanted to share a little code that made some data conversion very simple over the course of the TERRA project. It’s a simple little php function that converts a MySQL timestamp into an RFC 822 date format (For the project, we stored the item update fields as timestamps and then converted them when we generated our various XML feeds. RFC 822 or RFC 2822 are necessary for valid feeds.) Here’s the php function in all its glory:

//function converts mysql timestamp into rfc 822 date
function dateConvertTimestamp($mysqlDate)
{
$rawdate=strtotime($mysqlDate);
if ($rawdate == -1) {
$convertedDate = ‘conversion failed’;
} else {
$convertedDate = date(‘D, d M Y h:i:s T’,$rawdate);
return $convertedDate;
}
}
//end dateConvertTimestamp

You call the function by including it on the page and using the following code:

$newPubdate = dateConvert(“$stringToConvert”);
echo $newPubdate;

Where $stringToConvert would be any MySQL timestamp value that needs conversion.

In the end a string like this “2005-05-17 12:00:00” looks something like this “Tue, 17 May 2005 12:00:00 EST”. You could also reverse the conversion using this php function:

//function converts rfc 822 date into mysql timestamp
function dateConvert($rssDate)
{
$rawdate=strtotime($rssDate);
if ($rawdate == -1) {
$convertedDate = ‘conversion failed’;
} else {
$convertedDate = date(‘Y-m-d h:i:s’,$rawdate);
return $convertedDate;
}
}
//end dateConvert

NOTE: If/when you copy and paste the above code, make sure all ” (double quotes) and ‘ (single quotes) are retyped. WordPress is doing a number on the proper format.

I just wanted to share the wealth a bit. If you’ve got questions or suggestions, don’t be shy about dropping a comment. I’ll be home in Wisconsin for the next several days, but I’ll have limited internet access there.  I’ll try to answer questions if they arise.


Proof of concept – Ajax page update

Yesterday, Karen Coombs and I had the opportunity to conduct an “Ajax for Libraries” workshop at Internet Librarian. The workshop went pretty well and it was encouraging to work with a group of attendees who were engaged and willing to learn. (Note to self: create a cross-domain Ajax query to show workshop attendees.) I wanted to start with Ajax basics so I created a simple Ajax example that pulls WorldCat data and a WorldCat “find in a library” search form onto a page. It’s very basic, but it showcases the fundamentals of the Ajax method – take a look at the demo here.

The example uses the XMLHttpRequest object to make a micro-HTTP GET request behind the scenes creating a seamless date update without a full page reload. Feel free to download a zip of the sample files in an active server directory. Use modern browsers – Mozilla, Firefox, IE 6 and up.

Just wanted to share a bit, dig in and learn…

Update: Karen has posted links to the workshop files: presentation (.ppt) AND handout (.pdf)