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!

9 Comments

  1. Hi Marc I am actually using 2010 which is a good thing in this case. IO am quite new to SharePoint and JQuery so its been a battle but thank you for all the effort of this post! Unfortunately I can only test it tomorrow morning when we get into work as I have no access to the site I am working on from home.

    Hopefully I can get this right using all the information you have provided above! Last question I have is will this work with the fact that I have a discussion list which has a custom button I created in JQuery which takes me to the new form and inserts the text automatically from the discussion list. Below is the full code used to get that content and put it in the RTE at the moment that’s only working in chrome and not IE.

    Just wanted to clarify this up as the time difference is big between us.

    unction GetParam(name)
    {
    name = name.replace(/[\[]/,”\\\[“).replace(/[\]]/,”\\\]”);
    var regexS = “[\\?&]”+name+”=([^&#]*)”;
    var regex = new RegExp( regexS );
    var results = regex.exec( unescape(window.location.href) );
    if( results == null )
    return “”;
    else
    return results[1];
    }

    $(document).ready(function() {

    //SP2010AddNewify(“Customer”,”/International/Lists/mE%20Clients/NewForm.aspx”, “mE Clients”);
    ExecuteOrDelayUntilScriptLoaded(GetBlogBody, “sp.js”);

    });

    //////////////////////////////////////////////////////////////////////////
    /////////////////////////////////GET ITEM////////////////////////////////

    function GetBlogBody() {

    var id = GetParam(“blogid”);
    var clientContext = SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle(‘Team Discussion’);
    var camlQuery = new SP.CamlQuery();
    camlQuery.set_viewXml(“” + id + “”);
    //camlQuery.set_viewXml(“Mandarin prices”);
    this.collListItem = oList.getItems(camlQuery);
    clientContext.load(collListItem);
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));

    }

    function onQuerySucceeded(sender, args) {
    //alert(‘Query Success’);
    var listItemInfo = ”;

    var listItemEnumerator = collListItem.getEnumerator();
    var contentbody = “”;

    while (listItemEnumerator.moveNext()) {
    var oListItem = listItemEnumerator.get_current();
    contentbody = oListItem.get_item(‘Body’);

    }// end while

    CopyBodyToDescription(contentbody);
    //alert(CopyBodyToDescription);

    } // End Function

    function CopyBodyToDescription(contentbody) {

    var systemDescriptionRTETextArea = $(“textarea[Title=’Description’]”);
    //alert($(systemDescriptionRTETextArea).html());
    $(systemDescriptionRTETextArea).text(contentbody);
    //alert($(systemDescriptionRTETextArea).text());

    }// End Function

    function onQueryFailed(sender, args) {
    alert(‘Request failed. ‘ + args.get_message() + ‘\n’ + args.get_stackTrace());
    }

    Reply
    • Travis:

      It’s hard for me to say for sure given your particular customizations. You should always take posts like these as a decent starting point and experiment for your own requirements.

      M.

      Reply
      • Ok, that’s a fair a point. Well I will use your post as a guideline tomorrow and hopefully be able to adapt it to my code. Thanks again Marc for the time and effort.

        Travis.

        Reply
  2. Hi Marc,

    So I eventually found a solution. It’s a bit of a fiddly one but it works none the less. Biggest issue was identifying the div tag that I needed my script to insert the content into. Here is the code I ended up using, hopefully this will help others in the future as well. The first two lines in the function were additional to the original issue they just add in the link to the discussion list I am pulling the content from.

    function CopyBodyToDescription(contentbody) {

    var blogurl = GetParam(“blogurl”);
    var bloglink = “Click here to view original blog “;
    var contentdiv = $(“.ms-formbody”).eq(1).find(‘span’).eq(1).find(‘iframe’).eq(1).contents().find(‘div’);
    contentdiv.html(bloglink + contentbody);

    }// End Function

    Reply
  3. Hello Marc,
    I’m trying to set (initial) rich-text field value. Although I believe I’m able to find correct hook (since my alert returns desired content), following method does not change field value.

    $(systemDescriptionRTETextArea).html("whatever");
    

    Any idea what i might be doing wrong? Whole thing (shortened):

    <script type="text/javascript" src="...jquery-1.10.1.min.js"></script>
    <script type="text/javascript" src="...jquery.SPServices-0.7.2.min.js"></script>
    
    function findFormField(columnName) {
    ...
    } // End of function findFormField
    
     $(document).ready(function() {
      var systemDescriptionRTETextArea = findFormField("Staffing Plan").find(".ms-rtestate-write div");
      //check initial value - empty
      alert(systemDescriptionRTETextArea.html());
      
      $(systemDescriptionRTETextArea).html("whatever");
    
    //check assignment  
    alert(systemDescriptionRTETextArea.html());
      });
    </script>
    

    Jan

    Reply
  4. Hi Marc,

    I have a SharePoint 2010 form which have multiple columns replaced with changed field names: newFieldName = init_fieldsCFN();

    var newDATE = “Date form completed?” (–> Acting as a question in the form)

    Some of these ‘Questions’ turn out to be lengthy and I would like to know if these ‘Questions’ can be wrapped in order that the end user does not have to scroll the form horizontally?

    Reply
  5. Hi Marc,

    Apologies. I should have provided more info.

    Instead of making use of an actual survey, I have created a normal list in SP2010 and used JQuery to display the “Questions” of the survey with its responses.

    In the JQuery code I use, I have substituted the column name “Date” to present itself on the NewForm.aspx as “Date form completed?” with the code: var newDATE = “Date form completed?”.

    I have about 40 of these questions, but some of them consist of long sentences. These sentences are only displayed on a single line in the form, so if these questions are, let’s say 50 characters, the form extends beyond the size of the display on the form and the user then needs to scroll to the right of the form to actually enter their data.

    So the question is if there are any code by which I can wrap these long sentences so that it is displayed on 3 lines instead of the single line and thus eliminate the need for the user to scroll to the right and enter their data?

    Reply

Have a thought or opinion?