SPServices Compatibility Issues with the Minified Version of jQuery 1.9.0

Download jQuery 1.9.0Codeplex users tedka and danstaley have reported issues using SPServices with jQuery 1.9.0. You can read their issues here and here, respectively.

I’ve done some quick testing, and the problem seems to be with the minified version of jQuery 1.9.0, *not* 1.9.0 itself. When I use the non-minified version, my test pages perform just fine.

I’ve added a note to the home page of SPServices to this effect:

2013-01-29 – At this time, SPServices seems to work just fine with jQuery 1.9.0, but NOT with the minified version. If you need to use jQuery 1.9.0, please stick with the non-minified version or minify your own version.

When I create my own minified version of 1.9.0 using The JavaScript CompressorRater (I chose the first YUI Compressor 2.4.2 result, as I do when I minify SPServices), my minified version works fine, too.

At this point, I’m not sure what the exact problem is, but I’ll try to contact the jQuery team to see if there have been any other reports of issues. I’m not sure how well that will go, but at least there’s a workaround.

I found some other reports of issues which are caused by this line at the end of the minified version of jQuery 1.9.0:

//@ sourceMappingURL=jquery.min.map

While the source mapping capability sounds useful, having this line in the minified version causes another library following that line to throw errors, which is explained well on this thread at StackOverflow.

[important]This is a known issue with jQuery 1.9.0, which the team has already fixed for the next version. Here’s the bug in the jQuery bug tracker: http://bugs.jquery.com/ticket/13274[/important]

m4s0n501

SPServices Stories #3 – AddWebPart Method of the WebPartPages Web Service

Introduction

Eric Alexander (@ejaya2) should be no stranger to those of you who have visited NothingButSharePoint‘s Stump the Panel forums. If you’ve ever visited those forums, odds are very good that Eric has helped you out. He’s a stalwart member of the SharePoint support community.

Eric wrote a post on his blog about using SPServices to add Web Parts to existing pages that I thought was worth sharing as an SPServices Story.

AddWebPart Method of the WebPartPages Web Service

There are a lot of documentation black holes out there in the Sharepoint land and it seems that the WebPartPages web service is one of them.

In a project I’m currently working on, there is a need to automate a project creation process that is very manual to something more automated. Fortunately we have Nintex Workflow to handle situations like this.​ Part of this workflow is to provision a new subsite after the project is approved by the project manager. Nintex makes this easy with their LazyApproval feature and create site action.

What I needed to do was upon site creation from a template, add some web parts to the home page. This is where I was running into the huge documentation gap. I turned to one of my goto libraries, SPServices, to protoype the actual calls before porting it over to my workflow. Fortunately someone had tried to do this same thing in the past and provided a working example for adding a content editor web part. That is described here and worked no problem. My issue is I need to add list view web parts of document libraries and lists. I tried many things over the span of a couple days to tweak that to get my web parts onto the page. No dice.

Today I stumbled upon a post by Glyn Clough that filled that documentation black hole.

I need to use the List View Web Part markup like this for lists:

<?xml version="1.0" encoding="utf-8" ?>
<webParts>
 <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
  <metaData>
   <type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
   <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
  </metaData>
  <data>
   <properties>
    <property name="ListUrl" type="string">Lists/CustomList</property>
    <property name="ExportMode" type="exportmode">All</property>
   </properties>
  </data>
 </webPart>
</webParts>

and like this for document libraries:

<?xml version="1.0" encoding="utf-8" ?>
<webParts>
 <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
  <metaData>
   <type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
   <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
  </metaData>
  <data>
   <properties>
    <property name="ListUrl" type="string">Library</property>
    <property name="ExportMode" type="exportmode">All</property>
   </properties>
  </data>
 </webPart>
</webParts>

Once escaped and passed into my SPServices function I had web parts on my web part page.

SPServices Code

Eric’s post doesn’t have the SPServices call in his post, so I thought I’d provide an example here. This is built from the example from the documentation on the SPServices Codeplex site for AddWebPart. It adds an XLV Web Part showing the default view of my Tasks list to the home page of my root site and shows me an alert with the results.

var str = "&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;" +
"&lt;webParts&gt;" +
 "&lt;webPart xmlns=&quot;http://schemas.microsoft.com/WebPart/v3&quot;&gt;" +
  "&lt;metaData&gt;" +
   "&lt;type name=&quot;Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c&quot; /&gt;" +
   "&lt;importErrorMessage&gt;Cannot import this Web Part.&lt;/importErrorMessage&gt;" +
  "&lt;/metaData&gt;" +
  "&lt;data&gt;" +
   "&lt;properties&gt;" +
    "&lt;property name=&quot;ListUrl&quot; type=&quot;string&quot;&gt;Lists/Tasks&lt;/property&gt;" +
    "&lt;property name=&quot;ExportMode&quot; type=&quot;exportmode&quot;&gt;All&lt;/property&gt;" +
   "&lt;/properties&gt;" +
  "&lt;/data&gt;" +
 "&lt;/webPart&gt;" +
"&lt;/webParts&gt;";

$().SPServices({
  operation: "AddWebPart",
  webPartXml: str,
  pageUrl: "/SitePages/Home.aspx",
  storage: "Shared",
  async: true,
  completefunc: function (xData, Status) {
    alert("Status: " + Status + " xData: " + xData.responseText);
  }
});

SPServices Stories #1 – How to Start a Workflow on Multiple Items in a List

Introduction

Given the fact that so many people are using SPServices these days, I wanted to start posting some of the great things that people are doing with it out there.

If you have a story about how you are using SPServices that you would like to tell, ping me using the contact form. Your story doesn’t even have to include code, though people love to see examples. I’m always interested in what impact using SPServices may have had on your development philosophy, time to market with solutions, hiring practices, really anything that you feel SPServices has enabled you to do.

We can remove any identifying details if you feel that need to do so, but I’d like these stories to show off what *you* have done, so it’s great if you can take credit. I reserve the right to do a little editing for clarity, but otherwise you can write your own story. I’m also happy to help.

The first guest post is from fellow SharePoint MVP, Alberto Diaz Martin, who lives in Spain. Thanks to Alberto for kicking this series off!

[important]You can also read this post in Spanish on Alberto’s blog SharePoint 2010. Iniciar un flujo de trabajo en múltiples elementos de una lista[/important]

How to Start a Workflow on Multiple Items on a List

In SharePoint 2010 we have the option to select multiple items on a list. When you select several items, the ribbon allows you to Delete Items and Send Alerts, but where is the Workflow command?

To start a workflow on a list item, you have to go through the Start workflow page and if the workflow has an initialization form, you also have to enter the parameters. Because of this, SharePoint doesn’t allow users to start a workflow on multiple items simultaneously. But why not do so when we have a parameter-less workflow?

I think this is a missing feature on SharePoint 2010 because we can certainly do it using the SharePoint API or Web Services without any problems. What can we do to provide this capability to our users?

First, we need to create a Ribbon command using a Custom Action and in this action we will have two options to try to start the workflow. The first one uses an application page by passing the selected items as parameters and uses the server API to start the process. The second, and more flexible and elegant option is using JavaScript and the SharePoint Web Services to start each workflow per item.

SPServices Workflow Ribbon Custom Action

SharePoint Web Services are a horrible way to talk with SharePoint [ed: I disagree, but everyone is entitled to their opinion!] because the Web Services use XML to get and put parameters and options, and it’s not easy working with XML in JavaScript.

SPServices to the Rescue!!

As you know, SPServices is a jQuery library which encapsulates SharePoint Web Services with jQuery to make it easy to call them. SPServices has a Workflow namespace with some powerful operations and we can use StartWorkflow to start an item workflow, even if it has parameters.

It is so easy to use, you only need the Item URL, the workflow template Id and, if required, the workflow parameters.

$().SPServices({
  operation: "StartWorkflow",
  item: currentItemURL,
  templateId: workflowGUID,
  workflowParameters: workflowParams,
  async: true,
  completefunc: function () {
    SP.UI.Notify.addNotification("Workflow process started on selected item.", false);
  }
});

To get the workflow template Id, we have another function called GetTemplatesForItem that returns all the associated workflows for an item. All we have to do is get all the templates and find our workflow by name.

$().SPServices({
  operation: "GetTemplatesForItem",
  item: itemURL,
  async: true,
  completefunc: function (xData, Status) {
    var currentItemURL = this.item;
    $(xData.responseXML).find("WorkflowTemplates > WorkflowTemplate").each(function (i, e) {
      if ($(this).attr("Name") == "Invoice Approve") {
        var guid = $(this).find("WorkflowTemplateIdSet").attr("TemplateId");
        if (guid != null) {
          workflowGUID = "{" + guid + "}";
          //in this point, we have our workflow Id and we have to call the starting method
        }
      }
    }
  }
})

Now, we have to traverse the selected items in the custom action method, and for each item call the SPServices StartWorkflow method. Something like this:

function StarSignWorkflow(listId) {

  RemoveAllStatus(true);
  waitDialog = SP.UI.ModalDialog.showWaitScreenWithNoClose('Starting approval workflow process on selected item','Please,wait until we finished this long operation.',76,400);

  //Get the selected items
  clientContext = new SP.ClientContext.get_current();
  var web = clientContext.get_web();
  var list = web.get_lists().getById(listId);
  var items = SP.ListOperation.Selection.getSelectedItems(ctx);
  totaSelItems = items.length;

  //Because only have items Id,we need to use Client Object Model to get EncodeAbsUrl.
  var query = new SP.CamlQuery();
  var queryString = '<View><Query><Where><In><FieldRef Name="ID"/><Values>';
  for (index in items) {
    var valueString = '<Value Type="Integer">' + items[index].id + '</Value>';
    queryString = queryString + valueString;
  }

  query.set_viewXml(queryString + '</Values></In></Where></Query></View>');
  this.collListItems = list.getItems(query);
  clientContext.load(collListItems,'Include(EncodedAbsUrl)');

  //In the success callback,we’ll have all the selected items with the absolute url.
  clientContext.executeQueryAsync(Function.createDelegate(this,this.onInitProcessSuccess),Function.createDelegate(this,this.onInitProcessFail));
}

function onInitProcessSuccess() {

  var listItemEnumerator = this.collListItems.getEnumerator();

  //If our workflow has default init param,we can provide it in this way to run workflow with default values.
  var workflowParams = "<Data><Approvers></Approvers><NotificationMessage></NotificationMessage>" +
      "<DurationforSerialTasks></DurationforSerialTasks><DurationUnits></DurationUnits>" +
      "<CC></CC><CancelonRejection></CancelonRejection><CancelonChange></CancelonChange>" +
   "<EnableContentApproval></EnableContentApproval></Data>";

  try {
    var counter = 1;
    var total = totaSelItems;

    //Traverse all the selected items
    while (listItemEnumerator.moveNext()) {
      var oListItem = listItemEnumerator.get_current();
      var itemURL = oListItem.get_item('EncodedAbsUrl');
      var workflowGUID = null;

      //Before start the workflow,we used GetTemplatesForItem to get Workflow Template Id.
      $().SPServices({
        operation: "GetTemplatesForItem",
        item: itemURL,
        async: true,
        completefunc: function (xData,Status) {
          var currentItemURL = this.item;
          $(xData.responseXML).find("WorkflowTemplates > WorkflowTemplate").each(function (i,e) {
            if ($(this).attr("Name") == "Invoice Approve") {
              var guid = $(this).find("WorkflowTemplateIdSet").attr("TemplateId");
              if (guid != null) {
                workflowGUID = "{" + guid + "}";
                $().SPServices({
                  operation: "StartWorkflow",
                  item: currentItemURL,
                  templateId: workflowGUID,
                  workflowParameters: workflowParams,
                  async: true,
                  completefunc: function () {
                    if (total == counter) {
                      if (waitDialog != null) {
                        waitDialog.close();
                      }
                      SP.UI.Notify.addNotification("Started workflow approved process for selected invoice.",false);
                      window.location.reload();
                    }
                    counter++;
                  }
                });
              }
            }
          });
        }
      });
    }
  }catch (e) {
    if (waitDialog != null) {
      waitDialog.close();
    }
    AddStatus("There is an exception. Error: " + e.message,"red");
  }
}

As you can see, you have an easy way to provide an easy way to start a process on multiple items at the same time. Thanks to SPServices, working with SharePoint client side is more flexible and easy.

AlbertoDiazMartinAlberto Diaz Martin
MVP SharePoint
adiazcan@hotmail.com
@adiazcan
http://geeks.ms/blogs/adiazmartin

Is Client Side Scripting a Good Way to Access SharePoint Data?

People reach out to me all the time to ask my advice on how to accomplish certain things with SharePoint. Sometimes I can help, and sometimes their questions are way beyond me. One of the benefits of being reasonably well known in the SharePoint space is that people tend to come to me with questions that are up my alley.

When the questions aren’t something I can handle, I usually suggest that they use one of the public forums out there. My favorite is SharePoint StackExchange and in a distant second, the MSDN Forums for SharePoint.

Other times, either due to how they found me or based on the content of their questions, things stay in an email exchange.

The other day, my friend and colleague Christina Wheeler (@cwheeler76) passed along some questions from someone she knew [I’ve edited each part of the exchange a little for clarity and anonymity]:

I was wondering if you have a good resource within your network that might have published a blog about the different ways to access Sharepoint list data (client side scripting using something like SPServices or server side scripting using a deployable web part). Also, are there any other ways to accomplish this? I know the data view web part is another method, but it has its limitations.

A good example would be wanting to combine data from a SharePoint list and an external list and display both back to the browser window. I thought SPServices would be an excellent alternative to the data view web part, because it wouldn’t require taking the server down to deploy or redeploy. However, there are concerns coming from my team that client side is not as fast, secure etc. So I am just looking to see if there are any resources out there that have addressed this as it relates directly to Sharepoint.

Well, she certainly arrived in the right place with those questions. Since SPServices is mine, I can certainly answer any questions about it better than most people. The first thing I did was refer her to the post that Mark Rackley (@MrAckley) and I wrote together called When to Choose SPServices vs. the Client Side Object Model (CSOM). That post has gotten a lot of reads and Mark and I still think it covers the topic pretty well.

That prompted the next set of questions:

Thank you so very much for pointing me to all this valuable information! […] mentioned the SPServices […], and from then, I was hooked. Honestly, it was the number one thing I took away […] because of its potential to get around some Sharepoint limitations. To give you an example, we have a […] calendar that is managed under the IT site for the Sharepoint intranet. We like to display a summary of the daily or upcoming downtime to appear on the home page. The only way to display this data from another sub site (before) was with an RSS feed. The problem with the RSS feed is when we get into reoccurring events on the Sharepoint calendar. Now, I abandoned the RSS feed in favor of SPServices and it works beautifully.

My problem comes in with trying to get everyone on board that client scripting is okay to use for returning SharePoint list data. This argument is a perfect example. I am familiar with both client side scripting (javascript, xslt, jquery) and server side scripting with C#, but I don’t claim to be an expert. The argument that has been presented to me is that server side scripting is preferred because:

1.) It’s more secure

2.) It’s browser independent

3.) It’s better from a performance perspective

I tend to disagree that server side scripting is always the better answer for Sharepoint solutions. For one, we are not talking about writing an ERP payroll system where I plan to return thousands and thousands of records, so the amount of data I plan to return from a SharePoint list is minimal enough that I don’t think performance is a concern. For browser independence, that’s why I use jquery. And I don’t really know the answer about security. I think it comes down to what I want to do with the javascript. I am talking about using js to return a Sharepoint list. In this scenario, there is no increased threat of any kind by choosing to use client side javascript over a custom deployable web part written in C#. The case I am trying to argue is that using client side scripting to access a Sharepoint list is now possible, and in some cases, more desirable because it is easier to test, deploy, update and would not require any server downtime. I would just like to know your thoughts on this, or perhaps any resources…another blog or white paper you wrote that touches on best practices for when to use client side scripting vs server side development? Please bear with me because I have only been using Sharepoint for 6 months. Are there any other options to displaying Sharepoint list data other than using client side scripting like SPServices or CSOM, or to write an ASP.net page or deploy a custom web part that uses the Sharepoint Object model reference? I’m sure this is such an obvious answer that I have never really understood the answer to!

We plan to debate this issue tomorrow and I am just trying to make sure I understand the concerns/risks about coding for Sharepoint, specifically. There are lots of resources that touch on when to use client side scripting vs server side coding, but I think it’s not so black and white when it comes to working with Sharepoint.

And my reply was this:

You’re spot on in your thinking. This is a classic “it depends” scenario, of course. A good architect looks at all of the possible tools to solve the problem and decides where and when to use each one. Client side scripting is an excellent option for some things and just downright a bad idea for others.

The security argument is moot. The Web Services fully respect the permission model. If the user can’t access something through the UI, they can’t through the Web Services, either. QED. In a way, it’s even *more* secure than server side code since it’s impossible to elevate permissions, which many developers do as a common practice whether it’s needed or not.

Here are some more posts which may be helpful [each here on my blog]:

http://sympmarc.com/2011/05/27/elevating-permissions-with-sharepoints-web-services/

http://sympmarc.com/2011/06/06/using-script-to-hide-content-not-always-a-good-idea/

http://sympmarc.com/2011/05/18/sharepoint-myths-part-2/

Finally, the best argument that you can make is that Microsoft is going to a distributed, client side development model in SharePoint 2013, relying on (you guessed it) JavaScript and jQuery much of the time. If they are baking it into the product set by expanding their version of the API (versus mine with SPServices) how can someone argue that client side development is flat out a bad idea?

I don’t know if this little exchange will be useful for anyone else or not. However, it seems like every time I answer questions like there, it helps me to crystalize my thinking a little more. If it’s helpful to others, great. Otherwise, at least I had a little fun writing it up.

Calculate Days between Two SharePoint List Dates in XSL Using ddwrt:DateTimeTick

There was an interesting question over in the MSDN Forums the other day that I struggled to answer. It was a headscratcher, so I had to figure it out. In the thread, emfuentes27 wanted to know why s/he saw different results in SharePoint Designer than in the browser when using this formula:

<xsl:value-of select="number(ddwrt:DateTimeTick(ddwrt:GenDisplayName(string(@Due_Date))))- number(ddwrt:DateTimeTick(ddwrt:GenDisplayName(string($Today))))" />

Not only had I never seen the ddwrt:DateTimeTick function (no documentation on that is available anywhere at all that I can find), but the numbers just didn’t make sense.

[important]The ddwrt namespace functions are incredibly valuable, but they are simply not documented by Microsoft anywhere. There is a single article by Serge van den Oever (@svdoever) from the SharePoint 2003 days which explains it (very well), but that’s really it.[/important]

The ddwrt:DateTimeTick isn’t documented there and I’d never seen it in the wild. At least now I know about it.

To determine the days between two dates in the past, I’ve always used date arithmetic XSL templates, as I explain in my post Date Arithmetic in SharePoint DVWPs. The ddwrt:DateTimeTick function turns out to be a lot easier to use, but as I said, the numbers just didn’t make sense. They didn’t make sense, that is, until I went back to a little arithmetic.

It seems that the values in the browser were off from the ones in SPD (I tested this in WSS 3.0 because I had that VM open) by a factor of 864000000000. Trying to figure out the significance of that, I realized that it’s the number of seconds in a day times 1 million:

864000000000 = 60 * 60 * 24 * 1000000

60 * 60 * 24 = the number of seconds in a day.

Wolfram Alpha helps with this. Try going there and typing in 86400 seconds.

Who knows why this is the case, but this equation will give you the right answer in a browser (it will be wrong in SPD), which is what you are really after in the first place:

<xsl:value-of select="(number(ddwrt:DateTimeTick(ddwrt:GenDisplayName(string(@Lead_x0020_Date)))) - number(ddwrt:DateTimeTick(ddwrt:GenDisplayName(string(@Created))))) div 864000000000" />

The ddwrt:DateTimeTick function is a great tool for your XSL work in SharePoint. It returns the number of “ticks” since Dec 30, 1899 in SharePoint Designer. That’s an odd date to use as the base, but you can test it by adding this to your XSL:

1899-12-30::<xsl:value-of select="ddwrt:DateTimeTick(ddwrt:GenDisplayName(string('0001-01-01')))" /><br/>
1899-12-31::<xsl:value-of select="ddwrt:DateTimeTick(ddwrt:GenDisplayName(string('0001-01-02')))" /><br/>
1900-01-01::<xsl:value-of select="ddwrt:DateTimeTick(ddwrt:GenDisplayName(string('0001-01-03')))" /><br/>

Even odder, the base date in the browser seems to be Jan 1, 0001. You don’t see that date bandied about too often. Go ahead; give it a go:

0001-01-01::<xsl:value-of select="ddwrt:DateTimeTick(ddwrt:GenDisplayName(string('0001-01-01'))) div 864000000000" /><br/>
0001-01-02::<xsl:value-of select="ddwrt:DateTimeTick(ddwrt:GenDisplayName(string('0001-01-02'))) div 864000000000" /><br/>
0001-01-03::<xsl:value-of select="ddwrt:DateTimeTick(ddwrt:GenDisplayName(string('0001-01-03'))) div 864000000000" /><br/>

This is yet another example where the rendering engine in SharePoint Designer doesn’t yield the same results as what the SharePoint server provides. Don’t expect something like this to be fixed any time soon, though, given Microsoft’s abandonment of the Design and Split View in SharePoint Designer 2013.

We don’t really care what the base date is for zero ticks, of course; we just want to be able to use the values to determine the difference in days between two “ticks”. As long as you use the million-day-seconds trick, all is well.

This post also appeared at NothingButSharePoint.com on 2013-01-09. Visit the post there to read additional comments.