Lazyloading Brushes for dp.SyntaxHighligher using jQuery
When it comes to websites, the most important thing for me is to get the content. So loading content first is always a good idea. Using dp.SyntaxHighlighter means we might eventually load brushes we don’t need before we start to render the code sections. As well as wasting bandwidth.

photo: credit .Jennifer Leigh.
So the best way would be to only load those brushes you need to style the code sections. A few lines of jQuery supported JavaScript, and we have a solution.
First of all we need a function that makes sure it get’s executes. or dies if it fails too often.
:::javascript
var n = 10;
$.failproof_highlight = function() {
try {
dp.SyntaxHighlighter.ClipboardSwf = 'sh/Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
return true;
} catch(err) {
if(n < 1) return false;
n--;
t=setTimeout("$.failproof_highlight()",100);
}
};
So in case dp.SyntaxHighlighter is not ready yet, we wait for 100ms and try again. Until we succeed or failed for 10 times = 1s.
Next we want to see if we are need to load anything at all. And if so we can at least start loading the stylesheet.
:::javascript
if(pre_code.length) {
$(document.createElement('link'))
.attr({type: 'text/css',
href: '/sh/Styles/SyntaxHighlighter.css',
rel: 'stylesheet',
media: 'screen' })
.appendTo('head');
var brushMap = {
python: 'shBrushPython.js',
py: 'shBrushPython.js',
xml: 'shBrushXml.js',
xhtml: 'shBrushXml.js',
xslt: 'shBrushXml.js',
html: 'shBrushXml.js',
xhtml: 'shBrushXml.js',
js: 'shBrushJScript.js',
jscript: 'shBrushJScript.js',
javascript: 'shBrushJScript.js'
};
Now we only need to figure out what brushes to load. This is pretty straight forward:
:::javascript
var scripts = ['/sh/Scripts/shCore.js'];
libs = {}
pre_code.each(function(i,e) {
libs['/sh/Scripts/' + brushMap[$(e).attr("class")]] = 1;
});
for(lib in libs) { scripts.push(lib); }
And finally we need to load them. We basically spawn requests with the jQuery.getScript function for each file and decrement a counter when the file is loaded. Once all files have been loaded, we call the failproof_highlight function.
:::javascript
$.script_count = scripts.length;
$.script_load_notify = function() {
if(--$.script_count <= 0) $.failproof_highlight();
};
for(var i=0; i < scripts.length; i++) {
$.getScript(scripts[i], $.script_load_notify);
}
Stitching it together gives us:
:::javascript
$(document).ready(function(){
var n = 10;
$.failproof_highlight = function() {
try {
dp.SyntaxHighlighter.ClipboardSwf = 'sh/Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
return true;
} catch(err) {
if(n < 1) return false;
n--;
t=setTimeout("$.failproof_highlight()",100);
}
};
{% set base = '/contrib/syntaxhighlighter/' %}
var pre_code = $("[name=code]")
if(pre_code.length) {
$(document.createElement('link'))
.attr({type: 'text/css',
href: '/sh/Styles/SyntaxHighlighter.css',
rel: 'stylesheet',
media: 'screen' })
.appendTo('head');
var brushMap = {
python: 'shBrushPython.js',
py: 'shBrushPython.js',
xml: 'shBrushXml.js',
xhtml: 'shBrushXml.js',
xslt: 'shBrushXml.js',
html: 'shBrushXml.js',
xhtml: 'shBrushXml.js',
js: 'shBrushJScript.js',
jscript: 'shBrushJScript.js',
javascript: 'shBrushJScript.js'
};
var scripts = ['/sh/Scripts/shCore.js'];
libs = {}
pre_code.each(function(i,e) {
libs['/sh/Scripts/' + brushMap[$(e).attr("class")]] = 1;
});
$.script_count = scripts.length;
$.script_load_notify = function() {
if(--$.script_count <= 0) $.failproof_highlight();
};
for(var i=0; i < scripts.length; i++) {
$.getScript(scripts[i], $.script_load_notify);
}
There is quite a bot of room to improve and maybe even turn this into a jQuery Plugin at some point. I hope this helps someone. Comments appreciated as always.
Moritz Angermann 19 January 2009 Hanoi, Vietnam