One of the interesting problems we faced with the SocialThing for Websites integration on The Boot was keeping it as simple as humanly possible for a partner to implement (or even disable if needed). This meant that from a partner perspective all they needed to do was paste in one line of code to be up and running.
The trouble is, we needed both of these. So what to do?
We've all seen scripts get set in the head of the document with a corresponding <div> in the body that the script hooks onto and uses as a container to hold onto all of its resources. We can skip the hardcoded <div> by placing the <script> element in the body of the document and giving it an id attribute. We'll know that the <script> node exists because its being actively parsed, and we can do a lookup on it via its id and create our container <div> element using the insertBefore DOM method.
<!-- in our html -->
<script id="foo" src="http://www.foo.com/bar/script.js"></script>
// in our javascript
var script = document.getElementById("foo");
var div = document.createElement("div");
div.setAttribute("id","bar-div");
script.parentNode.insertBefore(div,script);
Now we've got our container element in the DOM, without any extraneous and unnecessary markup.
As for the second problem, and bearing in mind that you have a core script used by multiple partners with a need to distinguish each implementation with several parameters - how do you define variables specific to the script without another <script> element in the page? We cause the validation geeks to get their panties in a knot and use custom attributes on our <script> element, that's how.
<!-- in our html -->
<script lang="en-us" devid="abcdefg123" css="foo.css" id="foo" type="text/javascript" src="http://www.foo.com/bar/script.js"></script>
// in our javascript
var script = document.getElementById("foo");
if(script.getAttribute("lang")) baz.params.lang = script.getAttribute("lang");
if(script.getAttribute("devid")) baz.params.devid = script.getAttribute("devid");
// etc
That was the first approach to the problem, but then we decided to abstract this data further away from the client to avoid any potential damage through a well meaning but careless editor.
The final solution to this issue was to have an interstitial boot strapper script, unique to each partner, that a partner would point to that would set up all of these params on a <script> node that we create. This removes any possibility of parameter corruption by the partner, and unknots the panties of the validation purists. Bonus!
<!-- so now rather than pull in the application source proper, we pull in something that loads it for us -->
<script type="text/javascript" src="http://www.foo.com/bar/script-loader.js"></script>
// and our code in script-loader.js
function addScript(url, attributes) {
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.setAttribute("src", url);
for (var a in attributes) {
script.setAttribute(a, attributes[a]);
}
document.body.appendChild(script);
}
addScript("script.js", {id: "foo", devid:"abcdefg123", css: "foo.css", lang: "en-us"});
And thats all there is to it. Everything is set up and ready to roll, the partner didn't have to get their hands dirty with javascript or custom DTD's, and we maintain the ease of integration that we wanted all along.