/*
 * Copyright 2010 Mark Watkinson
 * 
 * This file is part of Luminous.
 * 
 * Luminous is free software: you can redistribute it and/or
 * modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Luminous is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Luminous.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 
 
 /**
   * This simply adds some extras to Luminous elements via a jQUery
   * plugin. The extras are currently a toggleable line-highlighting
   * on click
   */
 
(function($) {
    "use strict";
    
    if (typeof $ === 'undefined') { return; }
    
    /****************************************************************
     * UTILITY FUNCTIONS *
     ****************************************************************/
    
    // determines if the given element is a line element of luminous
    function isLine($line) {
        return $line.is('pre > span') && $line.parents('.luminous').length > 0;
    }
    
    function highlightLine($line) {
        // FIXME this 'highlighted_line' class needs to be renamed    
        $line.toggleClass('highlight');
    }
    
    function highlightLineByIndex($luminous, index) {
        var $line = $luminous.find('pre > span').eq(index);
        highlightLine($line);
    }
    
    function highlightLineByNumber($luminous, number) {
        // the line's index must take into account the initial line number
        var offset = parseInt($luminous.find('>pre').data('startline'), 10);
        if (isNaN(offset)) offset = 0;
        highlightLineByIndex($luminous, number - offset);
    }
    
    // binds the event handlers to a luminous element
    function bindLuminousExtras($element) {
        var highlightLinesData, highlightLines;
        if (!$element.is('.luminous')) { return false; }
        else if ($element.is('.bound')) { return true; }
        
        $element.addClass('bound');
        
        $element.click(function(ev) {
            var $t = $(ev.target);
            var $lines = $t.parents().add($t).
                    filter(function() { return isLine($(this)); }),
                 $line;
            if ($lines.length > 0) {
                $line = $lines.eq(0);
                highlightLine($line);
            }
        });
        
        // highlight all the initial lines
        highlightLinesData = $element.find('>pre').data('highlightlines') || "";
        highlightLines = highlightLinesData.split(",");
        $.each(highlightLines, function(i, element) {
             var lineNo = parseInt(element, 10);
             if (!isNaN(lineNo)) {
                 highlightLineByNumber($element, lineNo);
            }
        });
        
    }
    
    
    
    /****************************************************************
     * JQUERY PLUGIN *
     ***************************************************************/

    $.fn.luminous = function(optionsOrCommand /* variadic */) {
    
        var args = Array.prototype.slice.call(arguments);
        
        return $(this).each(function() {
            var $luminous = $(this);
            
            // no instructions - bind everything 
            if (!optionsOrCommand) {
                bindLuminousExtras($luminous);
                return;
            }
            
            // $('.luminous').luminous('highlightLine', [2, 3]);
            if (optionsOrCommand === 'highlightLine') {
                var lineNumbers = args[1];
                if (!$.isArray(lineNumbers)) 
                    lineNumbers = [lineNumbers];
                
                $.each(lineNumbers, function(index, el) {
                    highlightLineByNumber($luminous, el);
                });
                
                return;
            }
            
        });
    };

    $(document).ready(function() {
        $('.luminous').luminous();
    });
  
}(jQuery));
@@ -1437,21 +1437,17 @@
  renamed
-    
 %0A
+
         
@@ -1956,24 +1956,591 @@
 %0A    %7D%0A    %0A
+    function toggleHighlightAndPlain($luminous, forceState) %7B%0A        var data = $luminous.data('luminous'),%0A            state = data.code.active,%0A            $elem = $luminous.find('%3Epre'),%0A            toSetCode, toSetState;%0A        %0A        if (forceState === 'plain') state = 'highlighted';%0A        else if (forceState === 'highlighted') state = 'plain';%0A        %0A        toSetCode = (state === 'plain')? data.code.highlighted : data.code.plain;%0A        toSetState = (state === 'plain')? 'highlighted' : 'plain';%0A        %0A        $elem.html(toSetCode);%0A    %7D%0A    %0A
     // binds
@@ -2671,16 +2671,27 @@
 ghtLines
+, data = %7B%7D
 ;%0A      
@@ -3605,32 +3605,578 @@
    %7D%0A        %7D);
+%0A%0A        data.code = %7B%7D;%0A        data.code.highlighted = $element.find('%3Epre').html();%0A        %0A        data.code.plain = '';%0A        $element.find('%3Epre%3Espan').each(function(i, e) %7B%0A            var line = $(e).text();%0A            line = line%0A                    .replace(/&/g, '&amp')%0A                    .replace(/%3E/g, '&gt;')%0A                    .replace(/%3C/g, '&lt;');%0A        %0A            data.code.plain += '%3Cspan%3E' + line + '%3C/span%3E';%0A        %7D);%0A        data.code.active = 'highlighted';%0A        %0A        $element.data('luminous', data);
 %0A        %0A    %7D%0A
@@ -5187,32 +5187,32 @@
                %0A
-
                 
@@ -5225,32 +5225,254 @@
 ;%0A            %7D%0A
+            else if (optionsOrCommand === 'show') %7B%0A                // args%5B1%5D should be 'highlighted' or 'plain'%0A                if (args%5B1%5D)%0A                    toggleHighlightAndPlain($luminous, args%5B1%5D);%0A            %7D%0A
             %0A   

Implement JS API to toggle code highlighting