mirror of
https://github.com/pierre42100/comunic
synced 2024-11-16 18:41:13 +00:00
281 lines
10 KiB
JavaScript
Executable File
281 lines
10 KiB
JavaScript
Executable File
/**
|
|
* 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";
|
|
|
|
var LINE_SELECTOR = 'td .code > span ';
|
|
|
|
if (typeof $ === 'undefined') { return; }
|
|
|
|
/****************************************************************
|
|
* UTILITY FUNCTIONS *
|
|
****************************************************************/
|
|
|
|
// determines if the given element is a line element of luminous
|
|
function isLine($line) {
|
|
return $line.is(LINE_SELECTOR) && $line.parents('.luminous').length > 0;
|
|
}
|
|
|
|
function isLineNumber($element) {
|
|
return $element.is('.luminous .line-numbers span');
|
|
}
|
|
|
|
function highlightLine($line) {
|
|
$line.toggleClass('highlight');
|
|
}
|
|
|
|
function highlightLineByIndex($luminous, index) {
|
|
var $line = $luminous.find(LINE_SELECTOR).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('.code').data('startline'), 10);
|
|
if (isNaN(offset)) offset = 0;
|
|
highlightLineByIndex($luminous, number - offset);
|
|
}
|
|
|
|
function toggleHighlightAndPlain($luminous, forceState) {
|
|
var data = $luminous.data('luminous'),
|
|
state = data.code.active,
|
|
$elem = $luminous.find('.code'),
|
|
toSetCode, toSetState;
|
|
|
|
if (forceState === 'plain') state = 'highlighted';
|
|
else if (forceState === 'highlighted') state = 'plain';
|
|
|
|
toSetCode = (state === 'plain')? data.code.highlighted : data.code.plain;
|
|
toSetState = (state === 'plain')? 'highlighted' : 'plain';
|
|
|
|
$elem.html(toSetCode);
|
|
}
|
|
|
|
|
|
function toggleLineNumbers($luminous, forceState) {
|
|
var data = $luminous.data('luminous'),
|
|
show = (typeof forceState !== 'undefined')? forceState :
|
|
!data.lineNumbers.visible;
|
|
|
|
data.lineNumbers.visible = show;
|
|
|
|
|
|
var $numberContainer = $luminous.find('.line-numbers'),
|
|
$control = $luminous.find('.line-number-control');
|
|
|
|
if (!show) {
|
|
$numberContainer.addClass('collapsed');
|
|
$control.addClass('show-line-numbers');
|
|
$luminous.addClass('collapsed-line-numbers');
|
|
} else {
|
|
$numberContainer.removeClass('collapsed');
|
|
$control.removeClass('show-line-numbers');
|
|
}
|
|
$luminous.data('luminous', data);
|
|
|
|
}
|
|
|
|
// binds the event handlers to a luminous element
|
|
function bindLuminousExtras($element) {
|
|
var highlightLinesData, highlightLines, data = {},
|
|
hasLineNumbers = $element.find('td .line-numbers').length > 0,
|
|
schedule = [];
|
|
|
|
if (!$element.is('.luminous')) { return false; }
|
|
else if ($element.is('.bound')) { return true; }
|
|
|
|
$element.addClass('bound');
|
|
|
|
// highlight lines on click
|
|
$element.find('td .code').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 lines on clicking the line number
|
|
$element.find('td .line-numbers').click(function(ev) {
|
|
var $t = $(ev.target),
|
|
index;
|
|
if ($t.is('span')) {
|
|
index = $t.prevAll().length;
|
|
highlightLineByIndex($element, index);
|
|
}
|
|
});
|
|
|
|
data.lineNumbers = {visible: false};
|
|
|
|
if (hasLineNumbers) {
|
|
/**
|
|
* Line numbering is semi complicated because we can make it better
|
|
* with javascript!
|
|
* TODO: probably refactor this into a sub-function
|
|
*/
|
|
|
|
// the control is a show/hide line numbers, we can fade it
|
|
// in/out when the user hovers over the line numbers.
|
|
// We can also fix the line numbers so they move left
|
|
// as the widget is hoz-scrolled.
|
|
var $control, controlHeight, controlWidth, gutterWidth,
|
|
controlIsVisible = false,
|
|
$lineNumbers = $element.find('pre.line-numbers'),
|
|
defaultLineNumberWidth = $lineNumbers.outerWidth(),
|
|
mouseY = 0,
|
|
controlCalculateLeftCss = function() {
|
|
var visible = $element.data('luminous').lineNumbers.visible,
|
|
base = visible? gutterWidth - controlWidth : 0,
|
|
total = 0;
|
|
total = $element.scrollLeft() + base;
|
|
return total + 'px';
|
|
|
|
};
|
|
|
|
data.lineNumbers.visible = true;
|
|
data.lineNumbers.setControlPosition = function() {
|
|
$control.css('top', Math.max(0, mouseY - (controlHeight/2)) + 'px');
|
|
}
|
|
|
|
$control = $('<a class="line-number-control"></a>');
|
|
$control.click(function() {
|
|
$element.luminous('showLineNumbers');
|
|
$control.css('left', controlCalculateLeftCss());
|
|
if (!$element.data('luminous').lineNumbers.visible) {
|
|
$element.find('pre.code').css('padding-left', '');
|
|
} else {
|
|
$element.find('pre.code').css('padding-left', defaultLineNumberWidth + 'px');
|
|
}
|
|
|
|
});
|
|
|
|
$control.appendTo($element);
|
|
$control.show();
|
|
controlWidth = $control.outerWidth();
|
|
controlHeight = $control.outerHeight();
|
|
gutterWidth = $element.find('.line-numbers').outerWidth();
|
|
$control.css('left', gutterWidth - controlWidth + 'px');
|
|
$control.hide();
|
|
$element.mousemove(function(ev) {
|
|
var scrollLeft = $element.scrollLeft();
|
|
mouseY = ev.pageY - $(this).offset().top;
|
|
if (ev.pageX < gutterWidth) {
|
|
if (!controlIsVisible) {
|
|
data.lineNumbers.setControlPosition();
|
|
$control.stop(true, true).fadeIn('fast');
|
|
controlIsVisible = true;
|
|
}
|
|
} else {
|
|
if (controlIsVisible) {
|
|
$control.stop(true, true).fadeOut('fast');
|
|
controlIsVisible = false;
|
|
}
|
|
}
|
|
});
|
|
|
|
data.lineNumbers.setControlPosition();
|
|
$element.find('pre.code').css('padding-left', $lineNumbers.outerWidth() + 'px');
|
|
$lineNumbers.css({
|
|
position: 'absolute',
|
|
top: 0,
|
|
left: 0
|
|
});
|
|
$element.scroll(function() {
|
|
data.lineNumbers.setControlPosition();
|
|
$control.css('left', controlCalculateLeftCss());
|
|
$lineNumbers.css('left', $element.scrollLeft() + 'px');
|
|
});
|
|
schedule.push(function() { $element.luminous('showLineNumbers', true); });
|
|
$element.find('.line-numbers').parent().css({width: 0, maxWidth: 0});
|
|
|
|
}
|
|
|
|
// highlight all the initial lines
|
|
highlightLinesData = $element.find('.code').data('highlightlines') || "";
|
|
highlightLines = highlightLinesData.split(",");
|
|
$.each(highlightLines, function(i, element) {
|
|
var lineNo = parseInt(element, 10);
|
|
if (!isNaN(lineNo)) {
|
|
highlightLineByNumber($element, lineNo);
|
|
}
|
|
});
|
|
|
|
data.code = {};
|
|
data.code.highlighted = $element.find('.code').html();
|
|
|
|
data.code.plain = '';
|
|
$element.find(LINE_SELECTOR).each(function(i, e) {
|
|
var line = $(e).text();
|
|
line = line
|
|
.replace(/&/g, '&')
|
|
.replace(/>/g, '>')
|
|
.replace(/</g, '<');
|
|
|
|
data.code.plain += '<span>' + line + '</span>';
|
|
});
|
|
data.code.active = 'highlighted';
|
|
|
|
$element.data('luminous', data);
|
|
|
|
$.each(schedule, function(i, f) {
|
|
f();
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************
|
|
* 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;
|
|
}
|
|
else if (optionsOrCommand === 'show') {
|
|
// args[1] should be 'highlighted' or 'plain'
|
|
toggleHighlightAndPlain($luminous, args[1]);
|
|
}
|
|
else if (optionsOrCommand === 'showLineNumbers') {
|
|
toggleLineNumbers($luminous, args[1]);
|
|
}
|
|
|
|
});
|
|
};
|
|
|
|
$(document).ready(function() {
|
|
$('.luminous').luminous();
|
|
});
|
|
|
|
}(jQuery)); |