The SharePoint Content Editor and the Infinite JavaScript Problem


One of the nice things about the SharePoint Content Editor Web Part is that it lets you easily include your own html and javascript without having to modify the page structure itself and that works really well for most things.  However, many third-party and hosted utilities require you to embed a script in your content that looks something like this :

   <script type="text/javascript" charset="utf-8" src="http://external.url.com/SomeID/TheirApp.js"></script>
   <noscript><a href="http://external.url.com/SomeID/">Click here to do something wonderful</a></noscript>

Simple enough and anyone can paste that in.  The catch comes when the javascript file that you are including writes its own HTML into your page.  What happens is that this may work properly the very first time you edit the page, assuming you do nothing else after pasting in the javascript.  However, as soon as you edit the page again, the javascript inserts another copy of its HTML because that external JS file doesn’t know the difference between editing a page and viewing a page so it keeps writing its HTML, over and over, which the Content Editor then thinks is you adding more HTML.  Wash, rinse, repeat until your database explodes.

The solution was to not use the Content Editor at all for this but to instead use something that does not even have a place for HTML at all: the Xml Viewer Web Part.  Simply add the XmlViewer to your page/content and then define your Xml like this, using the original HTML provided by the third part as the core of your Xml :

<wrapper>
   <script type="text/javascript" charset="utf-8" src="http://external.url.com/SomeID/TheirApp.js"></script>
   <noscript><a href="http://external.url.com/SomeID/">Click here to do something wonderful</a></noscript>
</wrapper>

Then define Xsl that merely writes the content of the Xml unchanged to the browser, like this :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="html" indent="yes" media-type="text/html" omit-xml-declaration="yes"/>

<xsl:template match="/">
	<!-- Ignore the root node as it is just a wrapper -->
	<xsl:apply-templates select="/*/*" />
</xsl:template>
 
<xsl:template match="node()" >
	<xsl:copy>
		<xsl:copy-of select="@*" />
		<xsl:apply-templates select="node()"/>
	</xsl:copy>
</xsl:template>
 
</xsl:stylesheet>

The only catch is that your source html must comply with the basic rules of Xml (i.e. matched opening/closing tags, special character restrictions) but that probably isn’t really too big of an issue.

When this renders, it will only write out the html you need for your include – once.

Update: 2-May-2013 – Thanks to a user, I discovered that this also works if you leave out the outer <wrapper> element from the Xml and then leave the Xsl completely blank. Logically, this should fail all over the place because not only is it malformed Xml, but there is no Xsl at all. My testing showed that this approach could be used to embed any Html, even the dreaded OBJECT and EMBED tags. Regardless, it works fine in SharePoint 2010 but am not at all sure that it will keep working fine in future versions as this really looks almost broken.

Advertisements

Posted on July 18, 2012, in SharePoint and tagged , , , , . Bookmark the permalink. 1 Comment.

  1. http://www.navy.mil

    Thanks David … I hadn’t considered using the XML web part for this until I read your post. Works well and overcomes some issues with the CEWP.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s