Using DOM Altering JavaScript Functions in the Page Editor

Thursday, March 26, 2015 @ 03:00

By Corey Adler

One of the features that I’ve enjoyed in my time working with Sitecore has been the dichotomy between doing things with the Content Editor and the Page Editor. The ability to accomplish the same end result through two completely different means is something that I’ve always enjoyed about programming in general—and it’s just as much fun in a CMS! However, this functionality comes at a price: In order for me to properly close out any features, tasks, or bugs on my plate I can’t just test out my fixes using just the Content Editor or just the Page Editor—I need to be able to verify that it works when doing it both ways. Nothing hit that point home more than something that came up in a recent project.

I was tasked with having a video from the Media Library show up in a player on a page that would be created by a Sitecore end user. Instead of using the regular HTML 5 video player, it was decided that we would be showing videos with the jwPlayer library—a very popular JavaScript-based video player. I completed the rendering, including the appropriate setup code for the jwPlayer, as shown below (with requisite null check!):

jwPlayer Setup

The rendering worked terrifically and I felt good about myself, so I pushed my code to the server. Hooray!

Soon afterwards, though, I received every developer’s bane: The dreaded QA message that something was broken. It turned out that QA had gotten everything working just fine through the Content Editor, but that something quite strange was happening when they tried to setup a video through the Page Editor: Nothing was showing up. No video player, no image and no rendering even!

I immediately went and took a look. Yep, nothing was showing up in Page Editor. Then it was time to rev up the Console in Chrome and to see…no JavaScript errors at all. Huh. That’s weird. Time to check sources then: Was the script even included? Was it to be found on the page at all? Yes and…yes. So if the script was there, and the requisite <div> tag to set up jwPlayer was there, why wasn’t it showing up in Page Editor?

After banging my head on the problem for a while, I decided to go to Stack Overflow—you can find the question at http://stackoverflow.com/q/28545873/391762. A few hours after I posted the question, Marek Musielak (SO profile at http://stackoverflow.com/users/157833/marek-musielak), who happens to be a Sitecore MVP out of Poland, gave me my answer. In his words:

“The issue is that when you add a component through Page Editor, the script is fired before the div <div id="@vidid"> element is added to DOM. Don't ask me why...The solution is really simple: wrap your javascript code with if condition, checking if the div is already there.”

When I did that…

Added Condition

…sure enough it worked just fine. But even though it started working, and I had successfully resolved my issue, I felt a little uneasy. Marek had said “Don’t ask me why”, but I really wanted to know why. Why would it work just fine on the page, but only work in Page Editor if I added the IF condition?

Having gone to the well already the first time, I went back to Stack Overflow, this time asking why this was happening in the first place (question at http://stackoverflow.com/q/28565071/391762). This time, Mark Cassidy (http://stackoverflow.com/users/81631/mark-cassidy) gave an answer that linked to a blog post by a Colin Ihrig (found at http://www.sitepoint.com/a-detailed-breakdown-of-the-script-tag/) in which he mentions that a browser, when it encounters a <script> tag, stops loading the document and executes the script. In such a case, if the script in question references a DOM element that has not been rendered or parsed out yet, it will execute, but will not take effect due to the DOM element not being present. To top it all off: Since no errors actually occurred, nothing will get populated in Console!

So what happens when adding the IF condition? It turns out that it does something very similar to what happens when you put a function inside of jQuery’s document.Ready() function: It forces the script to wait until the DOM element is parsed out and ready before it will actually execute it. That, it turns out, was what was happening when attempting to add the rendering through Page Editor originally: It was running the script block as it was loading the full rendering onto the page, not realizing that the DOM element that it was supposed to go on was not on the page yet. Once it found that it wasn’t there it exited gracefully, and simply did not render the player on the page at all. Adding the condition forced Page Editor, like a regular browser, to wait for the DOM element to be parsed and ready first before running the script.

One of the things that I love about using Sitecore is the fact that I learn something new all the time—and it doesn’t necessarily deal with Sitecore! So be sure to always understand that, no matter what you do in Sitecore, that you’re still using a web browser, and that fundamental web browser principles still apply while running Sitecore; make sure that DOM altering functions are properly wrapped! I’ve learned my lesson, and I hope you have too. Until next time, I wish you good coding.