Thursday, November 12, 2009

Access Yahoo's Weather API via YQL and jQuery

Let me start off by saying that if you want a basic demo of YQL by grabbing an RSS feed check out my first blog post on YQL. In this post I am going to make a little weather widget that grabs the current temperature, weather condition, wind speed and direction, create a link to the full forecast and lastly drop a pretty weather condition graphic as the background of the widget. Then, once I have all that data I am going to display it via jQuery.

So let's get started! Pull up the YQL developer console: https://developer.yahoo.com/yql/console/ and type in:

select * from weather.forecast where location=29201

Select JSON and click test. This shows you the weather data for Columbia, SC in JSON format. The good stuff is located in the within data.query.results.channel. In there you have access to the current temperature, humidity, wind, wind direction and even sunrise and sunset times. So let's start off simple.

Notice the rest query url in YQL console? It reads:
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20location%3D29201&format=json&callback=cbfunc

That is a little tough to work with if you ask me so I like to bring in a little jquery to make this JSON url a little easier to work with and read. Here is a little piece of jquery that does just that for you:

$.YQL = function(query, callback) {
    var encodedQuery = encodeURIComponent(query.toLowerCase()),
        url = 'http://query.yahooapis.com/v1/public/yql?q='
            + encodedQuery + '&format=json&callback=?';
    $.getJSON(url, callback);
};


I generally include this little snippet in a file called jquery.yql.js. After that we can place our YQL query just like in the console. Here is our sample query:

$.YQL("select * from weather.forecast where location=29201",function(data){
            var w=data.query.results.channel;
            $('#weatherTemp').html(w.item.condition.temp+"°");
            $('#weatherText').html(w.item.condition.text);
       });  

This call grabs the weather information for Columbia, SC and injects the temperature and condition text to their corresponding divs. So data.query.results.channel.item.condition.temp = current temperature. and data.query.results.channel.item.condition.text = current condition.

So that was easy, let's grab all the information we want for this demo!

$.YQL("select * from weather.forecast where location=29406",function(data){
            var w=data.query.results.channel;
            var weatherImage="url(http://l.yimg.com/a/i/us/nws/weather/gr/"+w.item.condition.code+"d.png)";
            var wd=w.wind.direction;
            if(wd>=348.75&&wd<=360){wd="N"};if(wd>=0&&wd<11.25){wd="N"};if(wd>=11.25&&wd<33.75){wd="NNE"};if(wd>=33.75&&wd<56.25){wd="NE"};if(wd>=56.25&&wd<78.75){wd="ENE"};if(wd>=78.75&&wd<101.25){wd="E"};if(wd>=101.25&&wd<123.75){wd="ESE"};if(wd>=123.75&&wd<146.25){wd="SE"};if(wd>=146.25&&wd<168.75){wd="SSE"};if(wd>=168.75&&wd<191.25){wd="S"};if(wd>=191.25 && wd<213.75){wd="SSW"};if(wd>=213.75&&wd<236.25){wd="SW"};if(wd>=236.25&&wd<258.75){wd="WSW"};if(wd>=258.75 && wd<281.25){wd="W"};if(wd>=281.25&&wd<303.75){wd="WNW"};if(wd>=303.75&&wd<326.25){wd="NW"};if(wd>=326.25&&wd<348.75){wd="NNW"};
            $('#weatherWidget').css("background-image",weatherImage);
            $('#weatherTemp').html(w.item.condition.temp+"&deg;");
            $('#weatherText').html(w.item.condition.text);
            $('#weatherWind').html(wd +" "+w.wind.speed+"mph");
            $('#weatherLink').html("<a href='"+w.item.link+"'>Full Forecast</a>");
        });

OK, let's go line by line. First off you wil notice that I created weatherImage variable. Yahoo does not give you the full url to the image. I have to build the url and insert the condition code to display the right image. So to make the weatherImage I take the string "http://l.yimg.com/a/i/us/nws/weather/gr/" and add the condition code "30" to it and append the string ".png" to that you get: http://l.yimg.com/a/i/us/nws/weather/gr/30d.png

Yahoo does not give you the text wind direction. It gives you the degree. So if w.wind.direction might equal "90" which equals East. But I actually want to display E or NE. etc... So I wrote a series of if statements to check the direction number and output a string. I know, I know. I could have written a regular expression, but hey, I am a designer. Cut me some slack!

The rest of it just injects all the data into the corresponding divs. So here is a working example:


Please note there is NO server side coding going on. This is just javascript, HTML, and a little css. Speaking of which, here is the html as well:

<div id="weatherWidget" style="background: rgb(51, 51, 51) none no-repeat scroll 0% 0%; border: 10px solid rgb(17, 17, 17); height: 150px; position: relative;">
<div id="weatherDescription" style="left: 200px; position: absolute; top: 40px;">
<div id="weatherTemp" style="font-size: 200%; font-weight: bold;"></div>
<div id="weatherText"></div>
<div id="weatherWind"></div>
<div id="weatherLink"></div>
</div>
</div>

Pretty simple stuff if you ask me. I am going to post some flickr, youTube, upcoming.org, and twitter YQL widgets in the near future. So stay tuned!

Friday, October 23, 2009

YQL allows you to query the entire web

Leave no RSS, XML document, or web 2.0 api untouched! You literally can grab content from anywhere, turn it into JSON data and display the desired information using my old fiend jQuery.
First off check out the YQL developer console: https://developer.yahoo.com/yql/console/
There you can run test queries and view many community tables using popular api's and file formats doing very useful things. For example, if I want to grab the latest 3 posts from my blog I would just put in:
select * from atom where url='http://graphicallyherdingthemasses.blogspot.com/feeds/posts/default' limit 3

And BAM. Right there in the console you can see the feed. If you select JSON and run the test again and copy the generated url you get this...
https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20atom%20where%20url%3D'http%3A%2F%2Fgraphicallyherdingthemasses.blogspot.com%2Ffeeds%2Fposts%2Fdefault'%20limit%203&amp;format=json&amp;callback=cbfunc
That's great but how can I put that on MY site? Well, first we need to bring in a little jquery to make this JSON url a little easier to work with and read. Here is a little piece of jquery that does just that for you:

$.YQL = function(query, callback) {
    var encodedQuery = encodeURIComponent(query.toLowerCase()),
        url = 'http://query.yahooapis.com/v1/public/yql?q='
            + encodedQuery + '&format=json&callback=?';
    $.getJSON(url, callback);
};

So now all we need to do is grab the data and display it using a little jquery. First we grab the first 3 posts by our YQL call. Once we get the data we are going to find the individual blog posts and grab the title and the link and append it to the called bloggerWidget.

$.YQL("select * from atom where url='http://graphicallyherdingthemasses.blogspot.com/feeds/posts/default' limit 3",function(data){
            var blogPost=data.query.results.entry;
            $.each(blogPost,function(index, blogPost){
                $('#bloggerWidget').append("<li><a href='"+blogPost.link[4].href+"'>"+blogPost.title.content+"</a></li>");
            });    
        });

Here is it in action:


    No ASP, PHP, JSP, proxies, or cross domain errors... You can do this with ANY feed on ANY site. I am currently working on a site that pulls in data from the yahoo weather api, the flickr api, blogger atom feeds, twitter rss 2.0 feeds, and the youtube api.

    Thursday, October 8, 2009

    As the page folds

    Found a great article that talks a problem that I run into all the time. Clients, especially older ones, want everything to fit on one page with no scrolling or to use a print term, "above the fold". Everytime I explain that they have too much information to fit into that space and that it many extremely successful brands have pages with content way below the fold.

    This artcle not only addresses the "popular brands approach:


    It also takes hundreds of hours of eye tracking user testing. Here is a heat map of a site with content mainly above the fold and another with less content above the fold, think large rotating banner image at the top.

    The article also has an example of how to encourage users to explore below the fold. Simple things like don't make a large header that is 100% of the content area's width and "chop off" the page. Also, I would suggest using a subtle vertical gradient to draw the eye naturally downward.

    Another thing to think about to cut down on page scrolling is using columns. Not only does it help with the page height, but it also reduces wasted space and extremely wide copy. Everyone knows 72 characters is the "perfect" width so at 11px font size at 900px width. Two columns is almost perfect for real body text. You can even go to 3 columns on the homepage with short news headlines, event names and announcements.

    Check out the full article "The myth of the page fold":
    http://www.cxpartners.co.uk/thoughts/the_myth_of_the_page_fold_evidence_from_user_testing.htm

    Tuesday, September 29, 2009

    Need a quick quote?

    I found a great article by Brian Fling, although it is kind of old, about pricing design based projects. Please adjust the dollar amounts for inflation ;)
    Here are some interesting excepts from the article...

    1 mockup x time(1×10 hours) x $100 = $1,000
    Three mockups would look like this:
    3 mockups x time(1×10 hours) x $100 = $3,000
    A slightly more complex mockup might look like this:
    3 mockup x time(1.5×10 hours) x $100 = $4,500
    And a complex or challenging mockup might look like this:
    3 mockups x time(2×10 hours) x $100 = $6,000
    And so on. Start with a three-point complexity scale using the quarter points if necessary (e.g. 1.25, 1.5, 1.75 etc). If you feel you need to use a five-point scale or even a ten-point scale I would imagine you haven’t figured out your hourly rate.
    He even answers an often asked question...What is my hourly rate?

    (expenses + salary) ÷ hrs worked per yr. + margin = hourly rate
    Liked what you saw? Check out the full article here:
    http://www.blueflavor.com/blog/2006/apr/25/pricing-project/

    Friday, September 25, 2009

    Google Maps on Gameday



    I am been playing with Google maps alot lately. Mainly the API but I have also been playing with google maps proper. My maps is a pretty sweet feature. I used it to map out ~40 locations around the midlands for a client map and I decided that the average user could do some neat things.

    I live in Canalside and I decided to bike to the South Carolina vs Mississippi football game last night. I mapped the 6.7 mile round trip and placed a picture I uploaded from the game in less than 2 minutes...

    Wednesday, September 23, 2009

    Google Chrome Frame

    Google just released pretty interesting plugin for Internet Explorer called Google Chrome Frame. It is aimed at IE 6, 7, and 8 users on Windows XP and Vista. These users are typically the corporate desktop users that have not upgraded because of legacy IE6 applications or lazy IT staffs or both. When users install this plugin they will have full HTML5 support in their browser while maintaining IE6 compatibility with their legacy applications.

    So legacy IE users download it here:
    http://www.google.com/chromeframe/eula.html

    Now, designers and developers. Place this little meta tag on your page and this will enable google chrome frame for your websites and web applications.

    <meta http-equiv="X-UA-Compatible" content="chrome=1">

    If google chrome frame is there, then it will switch to the chrome webkit rendering engine. If not... it will work just like it did before. Google has also give us some handy tools to check to see if google chrome frame is installed and if not, prompt the user to download it...

    <script type="text/javascript"
    src="http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js">
    </script>

    <div id="placeholder"</div>

    <script>
    CFInstall.check({
    node
    : "placeholder",
    destination
    : "http://www.waikiki.com"
    });
    </script>

    Check out the full developer guide:
    http://code.google.com/chrome/chromeframe/developers_guide.html

    So what does this really mean. Well, it really depends on google really. If google starts requiring HTML5 support for HQ youtube videos and some advanced features in picasa web, blogger, gmail and google docs. Then this Google Chrome Frame will be huge. But perhaps this will force microsoft to push out an update to IE6 or that offers a "legacy" mode and a modern mode. I am in favor for either one... As long as we can move these neglected users out of the dark ages of web browsing.