Refreshing a Page Section with a User-selected Interval Set with jQueryUI’s Slider

I’m still doing lots of work with SharePoint 2007, even while many of my compatriots have moved on almost exclusively to 2013 work. The new shiny stuff is fun and all, but just because it’s new doesn’t mean that all the good work is there. Both SharePoint 2007 and 2010 are still providing valuable collaborative toolsets in organizations out there.

When you work with an older version of the product, you get the benefit of hindsight as well as knowledge of new trends in user interfaces and development approaches.

One of my clients wanted to create and auto-refresh capability for a SharePoint 2007 page that they use as a sort of dashboard. Many of the people in the organization keep the page open all day, and hitting refresh all the time is tedious. They also forget sometimes and can mistakenly be looking at stale content.

In SharePoint 2010, Data View Web Parts (DVWPs) provide this capability simply by checking a box on the ribbon (which usually works). I’ve rarely seen anyone enable the feature in 2010, but it’s there. To make this work in 2007, I had to build it with script.

To improve the situation, and therefore the general user experience (UX), we decided to give the user control over the auto-refresh capability. It wasn’t that much extra work to do it this way, and by allowing them the set their own refresh interval, they feel that they have more control of the page. This makes them more satisfied with the solution, which increases adoption. All goodness.

Page Map

It took some iteration to decide how to lay things out ideally, so what I’m showing here is closer to the end result than the starting point. I was able to take advantage of a function I had written earlier called refreshElement, which I wrote about in my prior post entitled Refreshing a Web Part Without a Postback Using jQuery’s AJAX Function.

The first step is to ensure that we have references to jQuery, jQueryUI, and jQueryUI’s CSS in the page. I’m also using jQuery cookie to set a cookie with the value in the slider that the user sets, thus making it possible to persist the value between sessions. In this particular case, we have references to the script libraries in the master page because we’re using them pervasively.

Next, I added a little markup to the page. My thinking on this was that by adding the markup at the top on the PlaceHolderMain rather than where the slider actually ended up, I could ensure that the data which drives the refresh will always be in the same place that I always put my script references, thus easy to find. If we decide to put the slider somewhere else in the page, I can just change the script, with no need to change the markup in the page itself. (We’re using this capability in four sites at the moment, with more to come.) There’s a div containing the slider info and then a second div wrapped around the area of the page I’d like to refresh. The refresh div can really surround anything in the page. I’m using AJAX to grab the full page, and I can simply parse out whatever is in the div. In this case, it contains the complex DVWP and one other Web Part. Note that the first div has a data attribute (how very HTML5 of me) which “points” to the div we want to actually refresh.

</pre>
<div id="aaa-refresh-control" data-to-refresh="aaa-listing"></div>
<div id="aaa-listing"><!-- ... DVWP, etc. ... --></div>
<pre>

Next comes the script. Hopefully the comments inline are clear enough, but if you have questions feel free to ask them in the comments section.

$(document).ready(function() {

  // If there is an element with the id aaa-refresh-control, we'll refresh what it indicates at a user-specified interval
  var refreshControl = $("#aaa-refresh-control");
  var toRefresh = refreshControl.data("to-refresh");

  // If there is a request to refresh an element...
  if(toRefresh !== undefined) {

    $("div[id$='QuickLaunchNavigationManager']").append(refreshControl);

    // Add the elements to the page that we need for the functionality to work
    refreshControl.append("<div id='refreshInfo'>" +
      "<label for='refreshInterval'>Refresh every</label>  " +
      "<input type='text' id='refreshInterval'/>minutes " +
      "<label id='refreshTime'></label></div>");
    refreshControl.append("<div id='refreshSlider'></div>");
    refreshControl.append("<div id='refreshNow'></div>");

    // Get the refresh interval value the user has set by retrieving the cookie
    var refreshInterval = $.cookie("refreshInterval");

    // If the refreshInterval hasn't been set, default to 5 minutes
    if(refreshInterval == 0 || refreshInterval == undefined) refreshInterval = 5;
    $("#refreshInterval").val(refreshInterval);
    $("#refreshTime").html("Last refreshed: " + getNow());

    // Set up the refresh behavior using a timer
    var refreshListing = setInterval(function(){
      refreshElement(toRefresh, "", "Please wait...", "Refreshing...");
      $("#refreshTime").html("Last refreshed: " + getNow());
    }, 1000 * 60 * refreshInterval);
    $("#aaa-listing").css("clear", "both");

    // Adjusting the slider allows the user to set the refresh interval to their own needs
    $("#refreshSlider").slider({
      value: refreshInterval,
      min: 5,
      max: 60,
      step: 5,
      slide: function(event, ui) {
        $("#refreshInterval").val(ui.value);
      },
      change: function(event, ui) {

        // Set a cookie with the refresh interval so that we can reload it when we return
        $.cookie("refreshInterval", ui.value);
        clearInterval(refreshListing);

        // Re-initialize the timer
        refreshListing = setInterval(function(){
          refreshElement(toRefresh, "", "Please wait...", "Refreshing...");
          $("#refreshTime").html("Last refreshed: " + getNow());
        }, 1000 * 60 * ui.value);
        $("#aaa-listing").css("clear", "both");
      }
    });
  }

});

// Refreshes an element's contents on a user action, showing a modal dialog during the refresh
// elementId  The id of the container element
// qs      The Query String to append to the current URL
// msg      The message to show in the dialog
function refreshElement(elementId, qs, title, msg) {

  var elementObj = $("#" + elementId);
  var infoDialog = $("<div><div>" + msg + "</div><div class='aaa-please-wait'></div></div>").dialog({
    open: function(event, ui) {
      $(".ui-dialog-titlebar-close").hide();  // Hide the close X
      $(this).css("overflow-y", "visible");  // Fix for the scrollbar in IE
    },
    autoOpen: false,
    title: title,
    modal: true,
    position: { my: "center", at: "center", of: window }
  });
  infoDialog.dialog("open");

  elementObj.fadeOut("slow", function() {
    $.ajax({
      // Need this to be synchronous so we're assured of a valid value
      async: false,
      url: window.location.pathname + qs,
      complete: function (xData) {
        newHtml = $(xData.responseText).find("#" + elementId).html();
        elementObj.html(newHtml);
      }
    });

  }).fadeIn("slow", function() {
    infoDialog.dialog("close");
  });
}

// Helper function which gets the current time and formats it in HH:MM format
function getNow() {
  var d = new Date();
  var curr_hour = d.getHours();
  var curr_min = d.getMinutes() >= 10 ? d.getMinutes() : "0" + d.getMinutes();
  return curr_hour + ":" + curr_min;
}

And voila. We have a little slider right under the main links in the Quick Launch which the user can slide to set their own refresh interval. Every time the timer hits that interval, the dialog pops up with info about the refresh, the content is refreshed, and the time above the slider changes to tell the user how fresh the content is.
jQueryUI Slider

Similar Posts

6 Comments

      1. Hi Marc, thank you for your reply. I was just in the middle of trying this when I read this. Marc do you know if there is any way for me to refresh a CEWP without refreshing the entire page? I’, having a difficult time find a solution. I have a CEWP which contains SPJS Charts. I’m trying have the charts either update dynamically when the list is updated (preferred) or have the webpart itself refresh somehow every few minutes. Any thoughts?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.