Framework-Free Automatic Brush Loading for SyntaxHighlighter

Update: Have you heard of SyntaxHighlighter? It’s pretty cool. I like that it adds little controls for popping the code out into a new window in plain text and that it has line numbers. However, I think that these days I prefer CodeColorer. Anyway, I still have this deployed in some places, and I figure SyntaxHighlighter lovers might find it handy. In case I want to come back to in in the future, I’ve created a project on GitHub, Lazy Brush Loader for SyntaxHighlighter to manage it, so check that out if you’re interested.

Please let me know if this helped you or if you find any problems with it. Thanks!

N.B. You can only pass the brush. No other arguments.

Just include the stylesheets and the core JavaScript files.

<link rel="stylesheet" type="text/css" href="/js/SyntaxHighlighter/styles/shCore.css" />
<link rel="stylesheet" type="text/css" href="/js/SyntaxHighlighter/styles/shThemeDefault.css" />
<script type="text/javascript" src="/js/SyntaxHighlighter/src/shCore.js"></script>

Then include this script:

/* Add document.getElementsByClassName to IE */
if (!document.getElementsByClassName) {
  document.getElementsByClassName = function(className) {
    var all_elms = document.getElementsByTagName('*');
    var elms = [];
    for (var i=0;i<all_elms.length;i++) {
      var elm = all_elms[i];
      if (elm.className) {
        if (RegExp(className).test(elm.className)) {
          elms.push(elm);
        }
      }
    }
    return elms;
  };
}

/* Add Array.indexOf to IE */
if (!Array.indexOf) {
  Array.prototype.indexOf = function(obj) {
    for (var i=0;i<this.length;i++) {
      if (this[i] == obj) {
        return i;
      }
    }
    return -1;
  }
}

/* Global timers, because IE wouldn't have it any other way. */
LB_TIMERS = [];

/* Load brushes on demand */
var load_SyntaxHighlighter_brushes = function() {

  /*
   * Path to SyntaxHighlighter directory
   */

  var scripts_path = '/js/SyntaxHighlighter/scripts/';

  /* All of the brushes I have. 2D array of variable width. Each item  in array
   * is array of brush aliases and brush filename. Filename must be last item
   * in each array. Listed on
   * alexgorbatchev.com/wiki/SyntaxHighlighter:Brushes  */

  var jses = [ ["as3", "actionscript3", "shBrushAS3.js"],
  ["bash", "shell", "shBrushBash.js"],
  ["c"-"sharp", "csharp", "shBrushCSharp.js"],
  ["cpp", "c", "shBrushCpp.js"],
  ["css", "shBrushCss.js"],
  ["delphi", "pas", "pascal", "shBrushDelphi.js"],
  ["diff", "patch", "shBrushDiff.js"],
  ["groovy", "shBrushGroovy.js"],
  ["js", "jscript", "javascript", "shBrushJScript.js"],
  ["java", "shBrushJava.js"],
  ["jfx", "javafx", "shBrushJavaFX.js"],
  ["perl", "pl", "shBrushPerl.js"],
  ["php", "shBrushPhp.js"],
  ["plain", "text", "shBrushPlain.js"],
  ["ps", "powershell", "shBrushPowerShell.js"],
  ["py", "python", "shBrushPython.js"],
  ["rails", "ror", "ruby", "shBrushRuby.js"],
  ["scala", "shBrushScala.js"],
  ["sql", "shBrushSql.js"],
  ["vb", "vbnet", "shBrushVb.js"],
  ["xml", "xhtml", "xslt", "html", "xhtml", "shBrushXml.js"] ];


  /* Find all items with class="brush: ..." */
  var brushables = document.getElementsByClassName('brush:');

  /* All of the brushes (syntaxes) that we find */
  var brushes = [];

  for (var i=0;i < brushables.length;i++) {
    var brush = brushables[i].className.split(': ')[1];
    if (brushes.indexOf(brush) == -1) { brushes.push(brush); }
  }

  /* All of the brush script tags that we're loading */
  var scripts = [];
  for (var i=0;i<brushes.length;i++) {
    var brush = brushes[i];
    for (var j=0;j<jses.length;j++) {
      var js = jses[j];
      if (js.indexOf(brush) > -1) {

        /* Create script DOM node */
        var script = document.createElement('script');
        script.setAttribute('type','text/javascript');
        script.setAttribute('src',scripts_path+js.slice(-1));
        script.setAttribute('defer','defer');
        script.setAttribute('id',brush);

        /* Add a "loaded" attribute to script so that we can toggle it to true
         * when the element has loaded. */

        script.loaded = false;

        /* For IE (oh, the hours of our lives we've lost to IE...) */
        if (/msie/i.test(navigator.userAgent)) {
          var timer = function(script,brush) {
            this.script = script;
            this.brush = brush;
            this.check_loaded = function() {
              if (script.readyState == 'loaded') {
                script.loaded = true;
                window.clearInterval('LB_TIMERS['+brush+'_timer'+']');
              }
            };
          };
          LB_TIMERS[brush] = new timer(script,brush);
          LB_TIMERS[brush+'_timer'] = window.setInterval('LB_TIMERS["'+brush+'"].check_loaded()',100);
        }
        else {
          /* EOMB */
          script.onload = function() {
            this.loaded = true;
          }
        }
        document.getElementsByTagName('head')[0].appendChild(script);
        scripts.push(script);
      }
    }
  }

  /* Don't run highlight until we've loaded the brushes! */
  var timer = window.setInterval(function() {
    var all_loaded = true;
    for (var i=0;i < scripts.length;i++) {
      if (!scripts[i].loaded) {
        all_loaded = false;
      }
    }
    if (all_loaded) {
      window.clearInterval(timer);
      SyntaxHighlighter.highlight();
    }
  },100);
}
SyntaxHighlighter.utils.addEvent(window,'load',load_SyntaxHighlighter_brushes);
This entry was posted in javascript, scripts and tagged , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>