Part 2: Sort a javascript array of dates from SharePoint

This is more of a follow-up to my post yesterday on how to convert dates from SharePoint to javascript. Today I’ll show you how to pull a list of dates from SharePoint (as well as other fields), push them into an array, and then sort that array by date.

Problem: Pull a list of reservations from a SharePoint and order them chronologically. There are three fields, firstName, lastName, and startTime. We want to pull all three fields, and then output those fields into an unordered list. As an added trick, we have several reservation lists we need to pull from (Elementary School, Middle School, and High School). So all reservations need to be pulled, and then sorted chronologically.

Solution 1: Just modify your CAML query to OrderBy the startTime field. Well, this works fine. But when pulling from multiple lists (using SPServices), the results will essentially be “grouped” by list.

Solution 2: Push all results to a javascript array, then sort the array. The problem here is that SharePoint’s date/time field isn’t very javascript-y. So sorting won’t work.

Solution 3: Use the convertSPDate() function mentioned in yesterday’s post on converting dates from SharePoint to javascript, then follow solution 2!

Here’s the code (commented with explanations):

Convert a SharePoint date/time field to a javascript Date() object

In a recent project I was looking for a way to sort an array of dates brought back from SharePoint. This worked fine in Chrome, but then I realized it didn’t work in any other browsers! So, by writing a few console.log() lines to test with Safari & FireFox, I discovered that the date that SharePoint passes is seen to javascript as an “invalid date” to almost all browsers. So, here’s a small helper function that just converts what you get from SharePoint into a true javascript Date() object. Hope you find it helpful! I’ve also included it in my code section as a Gist, so grab just the function there if you’d like.


function convertSPDate(d) {
/*
*	A function to convert a standard SharePoint
*	date/time field (YYYY-MM-DD HH:MM:SS) to a
*	javascript Date() object
*
*	Author: Ben Tedder (www.bentedder.com)
*/
    // split apart the date and time
	var xDate = d.split(" ")[0];
	var xTime = d.split(" ")[1];

    // split apart the hour, minute, & second
	var xTimeParts = xTime.split(":");
	var xHour = xTimeParts[0];
	var xMin = xTimeParts[1];
	var xSec = xTimeParts[2];

    // split apart the year, month, & day
	var xDateParts = xDate.split("-");
	var xYear = xDateParts[0];
	var xMonth = xDateParts[1];
	var xDay = xDateParts[2];

	var dDate = new Date(xYear, xMonth, xDay, xHour, xMin, xSec);
	return dDate;
}

	// create a couple of variables
	var startTime;
	var convertedStartTime;

	// a standard SPServices call
	$().SPServices({
		operation: "GetListItems",
		webURL: myListURL,
		async:false,
		listName: myListName,
		CAMLRowLimit: 1,
		completefunc: function (xData, Status) {
			$(xData.responseXML).SPFilterNode("z:row").each(function(i){
				// set the value of startTime to standard SP date/time field
				startTime = $(this).attr("ows_startTime");
			})
		}
	});

	// set the convertedStartTime to a true javascript date
	convertedStartTime = convertSPDate(startTime);

SharePoint Success!

This is meant to be a little encouragement in the midst of your day of end users telling you SharePoint is “hard to use,” “counter-intuitive,” or any other expletive adjective of their choice. With a little stylistic care and a little luck, you can have successes that take you a long way down the road of End User adoption!

A couple of weeks ago I wrote an article briefly describing a scheduling system built in SharePoint using nothing but 3 lists, a standard publishing page, and some jQuery.

The goal: to direct parents of 700 students to the online scheduling system for Parent-Teacher Conferences. All bookings had to be performed in the 10 days leading up to the 2-day conferences. A parent could book one slot with each of their child’s teachers, and each slot was 20 minutes long from 12 noon until 6pm. Keep in mind, no signup of this kind has ever been done electronically at this school. Previously everything was on slips of paper delivered in backpacks…followed up by half a day of phone calls to the secretaries.

The potential concerns:

  • no ability to “train” parents how to use the system, it must be intuitive
  • a good portion of the parent population speak English as a second language, with mostly Chinese or Korean as a first/only language, and about 2 dozen other languages next to those.
  • all bookings must be made ENTIRELY online (no call-ins, paper signups or emails…for consistency)
  • everyone must book their “own” slots (teachers nor secretaries can book time slots for parents)
  • parents must be able to change their time slots at will
  • priority must be given in the following order:
    • Teachers (to block certain slots for coffee breaks, etc)
    • Teachers who have children at the school (to book slots for their children)
    • Parents with more than one child in the school
    • Parents with only one child in the school (everyone else)

So, on to the success!

As of this writing we’ve just finished Day 8 of the rollout, and we have 612 students who have been booked using the system! By my count that’s just under 88% of children in the school. Now you’re probably about to ask “so how many phone calls and emails did you get?” I don’t have an exact number, but I’d say we’ve received about 20-25 calls/emails from people with “issues.” So with a 96% success rate (4% margin of error) on this first-time rollout, I’m happy!

A breakdown of the issues we did encounter:

  • a glitch where about 4 double-bookings occurred
  • a bug that wasn’t allowing users on IE7 to proceed with bookings (a simple browser switch did the trick until the fix was applied)
  • a glitch where about 5 or 6 parents were able to book slots that the teachers had blocked out
  • several login issues (separate from the actual scheduling system)
  • 2 cases of “my children” not appearing because of data integrity issues (extra spaces in names being pulled from the SQL server)

All that to say, don’t give up on your SharePoint end users! If a system is necessary enough and simple enough, you can bring them on board faster than you may initially have thought.

Drag-and-drop menu rearranging not working in Drupal

Just a quick post for those who are having this same issue. The key, I’ve discovered, is to make sure the javascript files are being aggregated. Go to Configuration > Performance; scroll to the bottom of the page and click “Aggregate JavaScript files.” That’s it!

Fix: jQuery Mobile w/SharePoint not working with IE8

I recently wrote a post on using jQuery Mobile together with SPServices to create an “app” for SharePoint. However, I’ve discovered a bug with my methods that appear in (at least) IE8.

Several surrounding issues:

  • Page is blank in Internet Explorer 8 (IE8)
  • “Can’t move the focus to the control because it is invisible” javascript error
  • The ui-mobile-rendering class is set to “hidden”
  • …lots of other lame issues

Solution:

  1. jQuery Mobile 1.0.1 does not support jQuery 1.7.1 :), so just download jQuery 1.6.4 and you should be fine. Although, jQuery Mobile 1.1 (right now in its first release candidate) supports jQuery 1.7.1, so just hang on!
  2. and in relation to #1, the .on() event handler was introduced with jQuery 1.7, so you’ll have to degrade to something like .live()

So after fixing those two issues with the last blog post, everything is working great on IE8. Hope it helps!

HTML5 video tag formats

If you’ve played with the new video element in HTML5, you’re probably noticing the power it has to release you of the flash-based bonds you’ve been held captive by. But if you’re running an older browser (anything prior to IE 9 according to this site), you’ll see a supreme lack of video playing in your browser. You’ll need to provide a flash fallback using something like MediaElement.js or Video for Everybody.

Assuming you have fixed your video tag for older browsers, here’s a breakdown of the 3 different video formats you can use with the HTML5 video element.

WebM/VP8

Quoting the WebM Project site, “The WebM project is dedicated to developing a high-quality, open video format for the web that is freely available to everyone.” Nothing more really needs to be said about which direction we should heading for video on the web. And again from their site, “WebM is supported by Mozilla, Opera, Adobe, Google and more than seventy other publishers and software and hardware vendors.” I wonder which video format will rise to the top?!

Ogg/Theora

This format is also an open source codec designed to compete with MPEG-4 and other proprietary codecs (Windows Media, Realmedia, etc.). I don’t have tons of experience with it, but it only seems to have a couple of percentage points up on the WebM format in terms of current usage support. Right now it supports all the same browsers. So I put it in just for the heck of it, but you might be able to get by without it.

MPEG-4/H.264

The licensing on MPEG-4 is not royalty-free, so many browsers won’t support this format. Keep in mind that if you’re using all 3 formats (suggested), you need to list this one first because of a bug with the iPad. Also, Firefox and Opera have both stated they won’t support this format. Chrome currently does, but it seems it won’t in upcoming versions. This format is a ticking clock because of its closed door policy. Yes, it’s nice. But its days are numbered.

If you need software to be able to convert quickly and easily to all of these formats, check out Miro Video Converter. It’s an awesome (lightweight) tool.

ps. Have you tried the YouTube HTML5 version? They’ll let you sign up for a trial to see how it’s working for you.

SPServices and jQuery: pull items from multiple lists in SharePoint 2010

Let’s say you want to display all of the titles of every page library in your site collection. Using jQuery and SPServices, it’s a breeze it’s definitely possible.

What we have here are three calls of the SPServices function. First, we call the GetAllSubWebCollection operation. This will bring us all sites (webs) within a certain site collection. Once we have that, we’ll then iterate through each web to find all lists (2nd SPServices call) using the GetListCollection function. Once we have all lists, we’ll iterate through each list to look for any lists with the title “Pages”. This will give us every page library of every site in our site collection. Then we we will call our 3rd and final SPServices function, GetListItems to bring us all of the titles of all the items (in every list, in every site of this site collection). Finally, for our last act, we’ll then link each title of each item of each list of each subsite of the site collection to it’s specific URL.

But then we have to do something with that chunk of data. The last line in our code is a simple jQuery function that appends an LI with each title inside an empty UL tag with the ID of #sitelist (somewhere in your page).

Phew!

…ok, here’s the code (I just tested it, it works!):

$().SPServices({
	operation: "GetAllSubWebCollection",
	webURL: "/",
	async:false,
	completefunc: function(xData, Status) {
		$(xData.responseXML).find("Web").each(function(){
$().SPServices({
 operation: "GetListCollection",
 webURL: $(this).attr("WebFullUrl"),
 async:false,
 completefunc: function(xData, Status) {
  $(xData.responseXML).find("List").each(function(){
  //function to get all items inside every list called "Pages"
  if($(this).attr("Title") == "Pages") {
   $().SPServices({
    operation: "GetListItems",
    webURL: $(this).attr("WebFullUrl"),
    async: false,
    listName: $(this).attr("Title"),
    CAMLViewFields: "<ViewFields><FieldRef Name='EncodedAbsUrl' /><FieldRef Name='Title' /></ViewFields>",
     completefunc: function (xData, Status) {
      $(xData.responseXML).SPFilterNode("z:row").each(function() {
       var url = $(this).attr("ows_EncodedAbsUrl") + "";
       var liHtml = "<li><a href='" + url + "'>" + $(this).attr("ows_Title") + "</a></li>";
       $("#sitelist").append(liHtml);
      });
     }
    });
   }
  })
 }
});
		})
	}
})

As usual, thanks to Marc Anderson and his SPServices library