A tag to insert a code selector widget
Author: | Admin |
Title: | A tag to insert a code selector widget |
Language: | en-US |
Created: | 14:36 on Monday, 11. October 2021 |
Modified: | 15:04 on Monday, 11. October 2021 |
Keywords: | jekyll, ruby, tag, liquid, code |
Excerpt: | This is a simple Liquid tag that inserts a code selector widget. When clicking on it, the code in the following |
Tags: | Jekyll |
Page layout: | nonav |
This is very simple. The tag inserts a small <div> element that contains some clickable text.
When clicked, the contents of the following highlight
block will be selected so it can be easily
copied. Note that the codeselect
tag must stand immediately before the highlight
tag (literally,
the line before, otherwise it may not work). It also works with the markdown method of code
highlighting (three backticks) and is smart enough to NOT select the line numbers in case they are
present.
Yes, I’m aware that there are different and maybe easier solutions for this problems, some are CSS and JavaScript - only, but this solution is slightly smarter, because it’s optional.
The plugin code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module Jekyll
class SelTag < Liquid::Tag
def initialize(tag_name, text, tokens)
super
@text = text
end
# render the output. Make sure, we have a valid cssclass
def render(context)
output = "<div class=\"codeselect\">Code: (click to select all)</div>"
return output
end
end
end
Liquid::Template.register_tag('codeselect', Jekyll::SelTag)
Supporting JavasSript code
This is the necessary JavaScript. It consists of 2 parts. First, a generic jQuery plugin to select the text of a given node. Just put this somewhere into your site’s footer scripts. It must load after jQuery has been fully loaded.
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
// jQuery plugin to select text of a node
// should work on all modern browsers
jQuery.fn.selectText = function(){
this.find('input').each(function() {
if($(this).prev().length == 0 || !$(this).prev().hasClass('p_copy')) {
$('<p class="p_copy" style="position: absolute; z-index: -1;"></p>').insertBefore($(this));
}
$(this).prev().html($(this).val());
});
var doc = document;
var element = this[0];
console.log(this, element);
if (doc.body.createTextRange) {
var range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
var selection = window.getSelection();
var range = document.createRange();
if (typeof(element) == 'object') {
range.selectNodeContents(element);
} else {
console.log(' not an object ' + typeof(element));
}
selection.removeAllRanges();
selection.addRange(range);
}
};
The following small JavaScript fragment should go to your $(document).ready()
function. It handles
the clicks and does the actual work.
1
2
3
4
5
6
7
8
9
10
$('div.codeselect').on('click', function(event) {
// this is for a highlight witOUT linenos or the markdown method
if ( $(this).next().contents().find('code').length ) {
$(this).next().contents().find('code').selectText();
}
// and this is for linenos
if ( $(this).next().contents().find('td.code').length ) {
$(this).next().contents().find('td.code').selectText();
}
});