-
Notifications
You must be signed in to change notification settings - Fork 1
/
api_lineselect.js
140 lines (121 loc) · 4.49 KB
/
api_lineselect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// $Id;$
/**
* Add line number and selection to PHP code blocks.
*/
Drupal.behaviors.api_lineselect = function(context) {
// Strip all new lines from inside of the title attribute of <a> tags
// Sometimes these contain extra new lines since the title attribute is the
// short function documentation.
$('.php code a').each(function() {
title = $(this).attr('title').replace(/\n/g, '');
$(this).attr('title', title);
});
// Find the code block on the page.
// @TODO: Make this work on pages with more than one code block.
var code = $('.php code', context).html() || false;
if (!code) {
return;
}
// More cleanup. If there is a closing <span> tag on a line of its own we
// shift it up to the previous line, unless it is the first line.
code = code.replace(/[^<?php][\n]<\/span>/g, '</span>');
// Split up the code based on newlines. Then put it into a table with line
// numbers in the left column and code in the right. We put it in a table so
// that when using shift select you're not also highlighting all the code
// using the browser native text selection.
var new_code = '';
var lines = code.split("\n");
var pad_length = lines.length.toString().length;
var line_numbers = '';
$.each(lines, function(index, value) {
// Wrap each line in a div, add a line number, and then wrap the contents
// of the line with a <pre> tag to preserve spacing.
line_numbers = line_numbers + '<span class="linenumber" rel="#L' + (index + 1) + '" ><pre>' + Drupal.api_lineselect_pad((index + 1), pad_length) + '</pre></span>';
// Make sure that blank lines are preserved.
if (value.length == 0) {
value = " ";
}
new_code = new_code + '<div class="line" id="L' + (index + 1) + '"><pre>' + value + '</pre></div>';
});
// Replace the existing highlighted code with our modified version.
output = '<table class="php"><tr><td>' + line_numbers + '</td><td width="100%">' + new_code + '</td></tr></table>';
$('.php code', context).parent().replaceWith(output);
// Bind click event handler to all line numbers.
$('.linenumber', context).api_lineselectShiftSelect();
// If there is a location hash with line numbers highlight those.
if (window.location.hash) {
hash = window.location.hash.replace('#','');
// The first letter is the identifier.
id = hash[0];
hash = hash.replace(id, '');
if (hash.indexOf('-') > 0) {
// This is a range.
n = hash.split('-');
n.sort;
for (i = parseInt(n[0]); i <= parseInt(n[1]); i++) {
$('#' + id + i).addClass('selected');
}
}
else {
// Single line.
$('#' + id + hash).addClass('selected');
}
// Jump to the first selected row.
window.scrollTo(0, $('.selected:first').offset().top - 50);
}
}
/**
* Helper function; Pad an integer to a specified length by adding leading
* zeros as necessary.
*/
Drupal.api_lineselect_pad = function(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
/**
* Function for binding and handing click events to line numbers. Allows for
* single line and multiple line selection if the user holds down the Shift
* key.
*/
jQuery.fn.api_lineselectShiftSelect = function() {
var lines = this;
var last_selected;
$(this).click(function(event) {
var last_index;
var select_index;
// Clear any existing highlighting from all lines;
$('.selected').removeClass('selected');
// Select the line that was just clicked on.
$($(this).attr('rel')).addClass('selected');
// If the shift key is being held down we allow selection of a range of
// lines.
if (event.shiftKey) {
select_index = lines.index(this);
last_index = lines.index(last_selected);
var end = Math.max(select_index, last_index);
var start = Math.min(select_index, last_index);
for (i = start; i <= end; i++) {
$($(lines[i]).attr('rel')).addClass('selected');
}
}
// Keep track of the last line that was clicked with or without shift held
// down so that we can do ranges on the next click if necessary.
last_selected = this;
// Figure out what to place as the hash.
var hash = '';
if (last_index && select_index) {
// Range.
hash = '#L' + last_index + '-' + select_index;
}
else {
// Single.
hash = $(this).attr('rel');
}
// Update the address bar.
window.location = window.location.href.replace(window.location.hash, '') + hash;
return false;
});
}