Setting a Rich Text Column in a SharePoint Form with jQuery – SharePoint 2010

I have gotten several questions on an older post of mine titled Setting a Rich Text Column in a SharePoint Form with jQuery from a guy named Travis. He’s been struggling to try to use the script in the post to get at the text in a Rich Text Editor (RTE) in SharePoint 2007.

I just took a look at an RTE in SharePoint 2010 in both IE and Firefox. The markup for it is considerably different than it was in SharePoint 2007, and looking at my older post, I can tell from the screenshots that I was in 2007. The good thing is that it looks identical in both browsers in 2010, which wasn’t usually the case in 2007.

Here’s what the column looks like in SharePoint 2010 with the same text typed into it as in the previous example:

9-11-2013 12-56-16 PM

And here’s what the markup looks like in IE10:

9-11-2013 1-04-32 PMThe script in the older post shouldn’t work in any browser, since the markup is different. Rather than a textarea, the typed text goes into a div. It was pretty easy to select the textarea in 2007 because it had its title attribute set to the DisplayName of the column. In 2010, there’s no such obvious “hook” to select on.

Instead, we have to fall back to looking for the column name in the comment which is above each column’s control on the page. To recap, each cell in the left column where the names of the columns show has the CSS class ms-formlabel applied to it. In the right column, where the editing controls are, each cell has the class ms-formbody applied to it.

To find the RTE in the page, we have to loop through all of the ms-formbody cells to find the right one. I do this in SPServices for some things as well, because SharePoint is very inconsistent when it comes to providing a good way to select form elements.

Here’s my findFormField function from SPServices:

// Finds the td which contains a form field in default forms using the comment which contains:
//  <!--  FieldName="Title"
//    FieldInternalName="Title"
//    FieldType="SPFieldText"
//  -->
// as the "anchor" to find it. Necessary because SharePoint doesn't give all field types ids or specific classes.
function findFormField(columnName) {
  var thisFormBody;
  // There's no easy way to find one of these columns; we'll look for the comment with the columnName
  var searchText = RegExp("FieldName=\"" + columnName.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "\"", "gi");
  // Loop through all of the ms-formbody table cells
  $("td.ms-formbody, td.ms-formbodysurvey").each(function() {
    // Check for the right comment
    if(searchText.test($(this).html())) {
      thisFormBody = $(this);
      // Found it, so we're done
      return false;
    }
  });
  return thisFormBody;
} // End of function findFormField

So the script to get the HTML value of the RTE – assuming we have the function above available to us – is:

var thisFieldHtml = findFormField("System Description").find(".ms-rtestate-write div").html();
alert(thisFieldHtml);

Unfortunately (fortunately?) SharePoint keeps track of where our cursor is at any given time during the editing process by maintaining two spans inside the div.

<span id="ms-rterangecursor-start"></span><span id="ms-rterangecursor-end"></span>

Here’s what it looks like in an alert when I’ve just typed “big “:

9-11-2013 1-33-09 PMIf we highlight a section of text, then that highlighted text is contained within the two spans. Here I’ve highlighted the word “over”:

<span id="ms-rterangecursor-start"></span>over<span id="ms-rterangecursor-end"></span>

So if we want to get the HTML value of the RTE without the editing spans, we need one more line of code to remove them:

var thisFieldHtml = findFormField("System Description").find(".ms-rtestate-write div");
thisFieldHtml.find("#ms-rterangecursor-start, #ms-rterangecursor-end").remove();
alert(thisFieldHtml.html());

If we just want the text value of the RTE, then we don’t need to bother stripping out the spans:

var thisFieldText = findFormField("System Description").find(".ms-rtestate-write div").text();
alert(thisFieldText);

Note: I’ve also tried this in SharePoint 2013. There, the artificial surrounding div which SharePoint wrapped the Rich Text in with the earlier version is not present, so we don’t need to look inside it:

var thisFieldText = findFormField("Reason for Nomination").find(".ms-rtestate-write").text();
alert(thisFieldText);

Travis, I hope this helps!

SharePoint 2010 Ribbon Button Error – "Access is denied. sp.ui.rte.js…"

Heather WatermanHeather Waterman (@hwaterman) and I turn to each other fairly regularly when either of us is stuck on something that we know the other will understand better. It’s the tremendous value of the SharePoint community along with the crazy tools like Skype that we have these days. (When I started coding, it was hard enough to get the attention of the person sitting next to you, much less someone across the hall or on the other side of the world. Or South Carolina.) All that and the fact that Heather is an all around good egg, and it’s a win for me at least!

Today I was having a problem where the buttons on the SharePoint 2010 ribbon weren’t working correctly. When I popped open the Developer Tools in IE9 (by hitting F12), I could see this error every time I clicked on one of the ribbon’s Rich Text formatting buttons.

image

That’s “SCRIPT5: Access is denied.  sp.ui.rte.js?rev=uY%2BcHuH6ine5hasQwHX1cw%3D%3D, line 2 character 267202”. Sure, it made sense to me, too.

I found several blog posts, each of which had interesting suggestions (e.g., add the site to the Trusted Zones or check for empty CSS or JavaScript files), but none of them worked for me.

Off to Skype to ask Heather, the expert. She had seen this issue before, but the tips above had solved it in the cases she could remember. We started marching through my custom master page and CSS to see what we could find.

Long story short, I was loading jQuery, jQueryUI, and SPServices from CDNs, using the txt file I describe in my post called, aptly enough, Referencing jQuery, jQueryUI, and SPServices from CDNs. I would have thought that since the error was about one of SharePoint’s js files, the issue would have been with one of the js files I was loading from the CDNs. However, it turned out to be the jQueryUI CSS file, not any of the script files.

I’m not sure that it is part of the cause, but because I’m working on a new SharePoint Internet site in stealth mode, I have the IP address in my hosts file. My guess is that this causes an issue with loading CSS files from another domain.

Well ,thanks to Heather I have the rest of the afternoon to do other useful things rather than spending more time on this silly issue. Thanks, Heather!

Setting a Rich Text Column in a SharePoint Form with jQuery

Over in the SPServices Discussions, @PirateEric was having a problem setting the value of a Rich Text column (RTE) in a SharePoint form. He was referring to my blog post Finding the Contents of a SharePoint Rich Text Column with jQuery – And Changing It, which I’ll stand by, but the jQuery there wasn’t cutting it. (If you’d like to read the whole thread, it’s here.)

What Eric wanted to do was set the RTE when the form loaded based on the results of a call to GetListItems (the workhorse of the SharePoint Web Services operations). That call would grab an existing list item so that Eric could reuse some of the values.

In my earlier post, I was focused on changing the existing value in an RTE column. Eric wanted to populate an empty RTE column. (This method works to re-populate an RTE that already has a value as well.)

The code is actually far simpler in this case. To review, an RTE (which stands for Rich Text Editor) is a column like this:

image

The markup for the RTE in the DOM is (as you might expect) fairly complex, but here are the important bits. I’m showing a view of the markup for the entire table row which represents the RTE column in my SharePoint form.

image

Any existing value will be stored in the textarea I’ve highlighted, but also within the iframe I discussed in my prior post. To simply set the value of the RTE column, you can just insert your own markup – or simply text – into that textarea. SharePoint’s script will fire on that change event, populating the iframe contents appropriately.

The jQuery to do this is really simple:

var systemDescriptionRTETextArea = $("textarea[Title='System Description']");
alert($(systemDescriptionRTETextArea).html());
$(systemDescriptionRTETextArea).html("Cream cheese");
alert($(systemDescriptionRTETextArea).html());

Here’s what I’m doing here:

  • Line 1: I’m finding the RTE’s textarea in the form using the selector. Many of the key elements in SharePoint forms have their title attribute set to the DisplayName of the column. (Unfortunately, this is not true of some columns types, like checkboxes and radio buttons, for example.)
  • Line 2: I’m alerting the original contents of that textarea, just to see what’s already there (just for debugging)
  • Line 3: I’m setting the value of the column to “Cream cheese”
  • Line 4: I’m alerting the contents again to be sure that it “took”

There you go, simple jQuery to set the contents of an RTE column. Of course “Cream cheese” probably isn’t what you’re aiming for: you can insert any valid HTML.

Finding the Contents of a SharePoint Rich Text Column with jQuery

I’ve had two questions this week about how to find the contents of a Rich Text column reliably with jQuery. Rich Text columns are rendered in a more complex way than just a nice textarea. Like some of the other column types they are a sort of hybrid, with some HTML elements and some script to hold it all together.

Taking a look at a Rich Text column with the Developer Tools in IE8, all of the gunky HTML below makes up the column. The value in the column is stored in a div inside one of the iframes. So it’s available, but you need to do some digging!

image

There are two spans wrapping everything, and within them there are the following elements:

  • textarea – This textarea contains the previously set value, not the currently edited value.
  • table – This table contains the buttons above the box which allow you to set the formatting.
  • iframe – I’m not exactly sure what this iframe is for; in my test WSS environment, it simply contains the image /_layouts/images/blank.gif that SharePoint uses as a placeholder.
  • div – this div contains the iframe where the real value is.
  • script – Finally, this script block sort of holds everything together.

So, as you can see in the screenshot above, we want to grab the contents of the body inside the iframe inside the div. Make sense?

To do this, we can use the following jQuery:

$("textarea[Title='System Description']").closest("span").find("iframe[Title='Rich Text Editor']").blur(function(){
  alert($(this).contents().find("body").html());
});

The name of my column in this example is System Description. First I find the texarea with System Description as the title. Then I find the closest ancestor which is a span. (I usually prefer to use .closest() rather than .parent() when I can in case anything else ends up inserted between the two elements.) Next I am finding the iframe which has its title attribute set to ‘Rich Text Editor’. That gets me into the right neighborhood. To test this, I decided to alert the contents of the iframe’s body when a blur event is triggered. That will happen when you’re finished editing the System Description (in this case) and my cursor exits the column.

If you’d just like to grab the value, you could use this jQuery. Yes, it’s a bit messy, but it gets the job done!

var systemInformation = $("textarea[Title='System Description']").closest("span").find("iframe[Title='Rich Text Editor']").contents().find("body").html();

p.s. This all works exactly the same in SharePoint 2010 as it does in SharePoint 2007.