1,691 articles and 12,650 comments as of Monday, September 13th, 2010

Thursday, January 15, 2009

Quote of the Day Web Part, Reprised – Part 2

This is the second part of a two part series on how to create a Quote of the Day web part whose quotes are drawn from a SharePoint list. The first article created the foundation for accessing the list. In this section, randomizing the quotes is considered.

Quote of the day

One approach you might’ve thought of is to use cookies to store the quote of the day. Each time the user comes to the page, JavaScript would check whether it’s the first time that this user is visiting the page or not (cookie available or not).

If it’s the first time, it would pick a random quote using the ‘random’ function we have just added to jQuery and then store the choice in the cookie on the user’s computer. On all subsequent visits it would retrieve the quote stored in the cookie instead of retrieving another one. By setting the cookie expiration time to one day you would ensure that another quote will be chosen if the user comes back tomorrow.

The downside of that approach is using cookies. They have a rather bad name because they are often misused to track user’s activity on the Internet. That’s why many users turn them off. Furthermore the approach described above could pick a different quote of the day for each user. As it would use the ‘random’ function there is no guarantee that all users would see the same quote.

While consistency wasn’t a part of our requirements list, it is definitely something you should keep in mind while working with/extending the Web Part.

There is another way though: why not make a large number out of the current date and modulo divide it by the number of quotes? The power of the modulo division is that it returns the remainder of the division (eg. 10%3=1): perfect if you want to retrieve a number from a particular range. So let’s change the ‘random’ function a little using the modulo division concept:

randomByDay: function() {
var now = new Date();
return $(this[now.getFullDate() % this.length]);
}

If you would save the above change, you would get a JavaScript error. Retrieving a large number of out the current date involves a couple of extra lines of code. Writing it inside the ‘randomByDay’ function would make the code unnecessarily complex. Instead I chose to extend the JavaScript Date object:

Date.prototype.getFullDate = function() {
var dateAsString = "";
dateAsString += this.getFullYear();
var month = this.getMonth() + 1;
if (month < 10) {
dateAsString += 0;
}

dateAsString += month;

var day = this.getDate();
if (day < 10) {
dateAsString += 0;
}

dateAsString += day;

return parseInt(dateAsString);
}

Let’s see our code so far:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script type="text/javascript">
jQuery.fn.extend({
randomByDay: function() {
var now = new Date();
return $(this[now.getFullDate() % this.length]);
}
});
</script>

<script type="text/javascript">
Date.prototype.getFullDate = function() {
var dateAsString = "";
dateAsString += this.getFullYear();
var month = this.getMonth() + 1;
if (month < 10) {
dateAsString += 0;
}

dateAsString += month;

var day = this.getDate();
if (day < 10) {
dateAsString += 0;
}

dateAsString += day;

return parseInt(dateAsString);
}
</script>

<script type="text/javascript">
var Imtech = Imtech || {};
Imtech.QuoteOfTheDay = function(listName) {
var selector = "table[class=ms-listviewtable][summary='" + listName + "'] > tbody > tr";
var quote = { text: null, author: null, obj: null };

var renderQuote = function() {
quote.obj.parents("table:first").parents("td:first").html('<blockquote><p>' + quote.text + '</p><p class="author">' + quote.author + '</p></blockquote>')
}

this.init = function() {
var quotes = $(selector).not(":first");
quote.obj = quotes.randomByDay();
quote.text = $("td:first", quote.obj).text();
quote.author = $("td:last", quote.obj).text();
renderQuote();
}
}
</script>
<script type="text/javascript">
var quoteOfTheDay;

$(function() {
quoteOfTheDay = new Imtech.QuoteOfTheDay("Quotes");
quoteOfTheDay.init();
});
</script>

And the results:

jQuery: Quote of the Day

For the clarity I’ve put all the different JavaScript pieces in separate script blocks. Please note that if you would like to reuse the solution across multiple pages, you could move the code of all these script blocks except the last one and save it to an external .js file. Such change would improve the page load as the separate JavaScript file would be cached on the user’s computer and all they would have to download is the small piece of JavaScript which initializes the Web Part.

That’s all. We’ve got our Web Part working.

Extra: Let’s prettify it

While we’re done with our requirements, the output isn’t end user ready if you’d ask me. We could however easily prettify it using a little piece of CSS:

blockquote p { font: italic bold 1.2em/1.2 "Times New Roman" , serif; }
blockquote p.author {
font: normal 0.8em/1.2 sans-serif;
color: #666;
text-align: right;
}


jQuery: Quote of the Day

Looks way better, doesn’t it?

Summary

Using jQuery you can build some great functionality on top of SharePoint. The best part is that it can be achieved without deploying of even a single line of server-side code.

In the example above we’ve stepped through the process of creating a Web Part on top of a List View. We’ve seen how jQuery can retrieve data out of a standard SharePoint List. Additionally we’ve learned how we can extend both jQuery and JavaScript with custom functions and use CSS to change the way the text is being displayed.

Other ideas? Leave a suggestion in the comments and I’ll see what I can do.

jQuery: Quote of the DayWaldek Mastykarz
Innovation Matters
Waldek Mastykarz is a Dutch SharePoint MVP specialized in Web Content Management solutions in Microsoft Office SharePoint Server 2007, web standards and accessibility.

View all entries in this series: WaldekMastykarz-QOTD»
Entries in this series:
  1. Quote of the Day Web Part, Reprised - Part 1
  2. Quote of the Day Web Part, Reprised - Part 2
 

Please Join the Discussion

58 Responses to “Quote of the Day Web Part, Reprised – Part 2”
  1. Alex – By my clock, it took you 14 minutes to figure that one out… not Mensa speed, but not bad :-)

    Glad it’s working for you. — Mark

  2. Alex says:

    I am trying to surround the quotation with a graphic image of an over-sized quote mark. Each end of the quotation would have an openQuote and a closeQuote.

    #openQuote{background-image:url(’http://xxxxxxxxxx.transitchicago.com/xxxxxxxxx/Quote_24×24_Blue.jpg’);}
    #closeQuote{background-image:url(’http://xxxxxxxxxx.transitchicago.com/xxxxxxxxx/Quote_24×24_v2_Blue.jpg’);}

    blockquote p { font: italic bold 1.2em/1.2 “Times New Roman” , serif; }
    blockquote p.author {
    font: normal 0.8em/1.2 sans-serif;
    color: #666;
    text-align: right;
    }

    Inside the javascript to render the quote I have added some new fieldnames for the CSS to apply the background-image to, however, the images never are displayed.

    var renderQuote = function() {

    quote.obj.parents(”table:first”).parents(”td:first”).html(’

    ‘ + quote.text + ” + quote.author + ‘

    ‘)
    }

    You can see that there is an

    and
    at the beginning and end of the html.

    Thanks for the help.
    Alex

    • Alex says:

      the code did not display correctly so here is an addendum to the above image code. I modified the code snippet below so it would display the css entry names and not render the code inside this forum:

      var renderQuote = function

      quote.obj.parents(”table:first”).parents(”td:first”).html

      + quote.text + quote.author +

  3. Alex says:

    openQuote + blockquote + quote.text + quote.author + /blockquote + closeQuote

Trackbacks

Check out what others are saying about this post...



Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!