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!
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.
Its Helped me :) thank you
I see so much conflicting information about Enhanced Rich Text fields because it seems that M$ changes this for each major release of SharePoint. Things also change depending on if using the Publishing features or not. More confusion stems from the fact that a multi-line text field can be plain text, rich text, or enhanced rich text. SharePoint might also render it differently at runtime depending on the user agent but I have not verified that.
I am running SharePoint 2013 on-premises with Publishing features. My empty Enhanced Rich Text fields have a u200B (ZWSP) inside a paragraph inside a div. Ninety-nine percent of the time I see that the u200B is replaced when new content is typed or pasted into the field but on a few occasions it seems that it just gets pushed aside. Since it’s invisible, there is no way to for the user to know.
This also makes PreSaveAction() client validation on Custom List forms more difficult. While the boys at MSDN provided a neat little function (sorry – forgot where that was) to locate fields by title this new Enhanced Rich Text field has no title. It’s not a textarea, either. In the end I resorted to something like this (must know the DIV IDs) …
if (jQuery(“div[id$=’_ff211_ctl00_ctl00_TextField_inplacerte’]”).find(“p”).text().replace(/\u200B/g,”) == “”) { //Empty – DO SOMETHING }.
Of course, this is not foolproof since the user might somehow just push that invisible paragraph and ZWSP down the line rather than replacing it. The user might just add an empty paragraph at the top of the text box and then continue with another that has content.This is rare but does happen. I suppose the best way would be to strip out the ZWSP before checking then see what’s left. What’s left might just be an open and closing paragraph tag and nothing else, though. I also thought I might remove both the paragraph and the ZWSP but the user might have put content into that existing paragraph and just pushed the ZWSP down the road.
Maybe a cleaner option would be to strip out the paragraph and ZWSP as soon as the user focuses on that field but we would have the same issue determining if there was valid content in there. I have also seen some solutions where JavaScript/jQuery is added to the master page to always strip these out of every page. That brute force method does seem a bit worrisome to me. Maybe there is reason they are there.
Maybe a simple solution is to just avoid using the Enhanced Rich Text field and opt for the simpler Rich Text field or plain text; however, the Enhanced Rich Text field offers a better user experience since most users are familiar with using the Ribbon on the top of a page when editing rather than the little TinyMce like options for the lesser field.
Anyone have an idea that would work for all possible situations to really determine if the contents of an Enhanced Rich Text field is truly empty?
I’ll reply to my own post as I made this a lot harder than it needed to be. The simple option here is to just use jQuery text(). We still need to filter out the ZWSP in case it remained. Also, forget about looking inside the paragraph since one can easily go back after entering the text, select it, and then click the Clear Format button to remove the paragraph entirely.
This works for an example div in a custom new form …
$(“div[id$=’_ff281_ctl00_ctl00_TextField_inplacerte’]”).text().replace(/\u200B/g,”);
The reason I use the Ends-with selector is so that this can also be reused in the edit form without modification.
Sometimes I can’t see the forest for the trees.