/*
  Ajax Code Display 
  written by Christian Heilmann (http://wait-till-i.com)
  license:http://creativecommons.org/licenses/by/3.0/
  requires on jQuery 1.2.2 or newer
*/
// when the web page is ready
$(document).ready(
  function(){
    // get all links with the class codeexample and apply a function
    $('a.codeexample').each(
      function(){
        // if the class 'dodisplay' is present
        if(this.className.indexOf('dodisplay') !==- 1){
          // add functionality to toggle the display of the output 
          $(this).toggle(
            // on the first click and subsequent odd clicks
            function(){
              // create an IFRAME after the element that shows the document 
              // the original link points to 
              $(this).after('<iframe class="codeexample" src='+this.href+'></iframe>');
              // store the original text in the link and change it to 'close'
              this.oldhtml = this.innerHTML;
              this.innerHTML = 'close';
            },
            // on the second and subsequent even clicks 
            function(){
              // remove the IFRAME and change the link text back to the old text
              this.parentNode.removeChild(this.nextSibling);
              this.innerHTML = this.oldhtml;
            }
          );
        }
        // store the link reference in 'link'
        var link = this;
        // are there any highlights to be done?
        var highlights = this.className.match(/highlight\[([^\]]+)/);
        // shall I only display a range of lines?
        var boundaries = this.className.match(/lines\[([^\]]+)/);
        // convert the ranges defined in classes to arrays
        // [1,5-7,12-15] => [1,5,6,7,12,13,14,15]
        var getrange = function(range){
          var elms = range.split(',');
          var range = [];
          for(var i=0,j=elms.length;i<j;i++){
             if(elms[i].indexOf('-')===-1){
              range.push(+elms[i]);
            } else {
              var s = +elms[i].split('-')[0];
              var e = +elms[i].split('-')[1];
              for(s;s<=e;s++){
                range.push(+s);
              };
            };
          };
          return range;
        };
        // convert code returned from the Ajax call
        var convert = function(code){
          // define output array
          var codeout = [];
          // replace HTML special chars
          code = code.replace(/&/mg,'&#38;');
          code = code.replace(/</mg,'&#60;');
          code = code.replace(/>/mg,'&#62;');
          code = code.replace(/\"/mg,'&#34;');
          // change tabs to spaces
          code = code.replace(/\t/g,'  ');
          // split code on newlines to get the lines
          var lines = code.split(/\r?\n/);
          // if there are highlights to be done 
          if(highlights){
            // get the full highlight range and loop over it
            var tohighlight = getrange(highlights[1]);
            for(var i=0,j=tohighlight.length;i<j;i++){
              // ger the appropriate line and add strong elements
              // around it
              var line = lines[tohighlight[i]-1];
              if(line){
                lines[tohighlight[i]-1] = '<strong>' + line + '</strong>';
              };
            };
          };
          // if there are only a few lines to be displayed
          if(boundaries){
            // get all the needed lines and loop over them
            var chunk = getrange(boundaries[1]);
            for(var i=0,j=chunk.length;i<j;i++){
              var line = lines[chunk[i]-1];
                // add spacers in between different line blocks
              if(i>0 && chunk[i] !== (chunk[i-1])+1){
                codeout.push('[...]');
              };
              // add a span with the line number, followed by a tab 
              if(line){
                var html = '<span>'+(chunk[i])+'</span>\t'+line;
                codeout.push(html);
              };
            };
          // if there are no boundaries just add line numbers to each line
          } else {
            for(var i=0,j=lines.length;i<j;i++){
              var html = '<span>'+(i+1)+'</span>\t'+lines[i];
              codeout.push(html);
            };
          };
          // create a pre with a code and the joined output after the link
          $(link).after(
            '<pre class="codeexample"><code>' +
              codeout.join('\n') +
            '</code></pre>'
          );
        };
        // do the ajax, timeout after 100 milliseconds if the 
        // document is not available
        $.ajax({
            url:this.href,
            timeout:500,
            success:convert
        });
      }
    );
  }
);
