RGraph is a JavaScript charts library based on
HTML5 SVG and canvas. RGraph is mature (over 17 years
old) and has a wealth of features making it an ideal
choice to use for showing charts on your website.
Version 7.01 (released in October 2025) is the
latest version of RGraph and now includes a new tree
structure object. The accompanying Treemenu object can then turn
the object into a fully dynamic tree menu.
You can read the API documentation for the tree on
the main API documentation page
and see an example of the Treemenu
feature by following this link...
In the April 2025 (v6.21) release a new datagrid object
was added.
This makes it easy to add static or dynamic data
tables to your pages. It can be used whether you use the
canvas or SVG libraries or entirely standalone.
Get the latest version of RGraph (version 7.01, 8th October 2025) from
the download page. You can read the changelog here. There's also older versions available,
minified files and links to cdnjs.com hosted libraries.
Here's a link to a basic, standalone page of this technique. All the source code is in the page - nothing external is referenced so it makes it easier to follow. If you want to you can view the source code of the page, copy it and paste it into a file on your desktop and it should work perfectly well.
And here's a link to a more basic example of copying to the clipboard. This code will only work with the one code example on the page but there's a lot less javascript to understand. Other than there only being support for a single <pre> tag it's pretty similar.
Introduction
If you have examples of code on your website (this site has a lot of them) adding Copy to clipboard links is a trivial matter - simply add the code inside a pre tag, add the markup for the Copy button and then style the tags with css - like this:
BEFORE:
// An example of adding the Copy button to pre example code blocks
new RGraph.Bar({
id: 'cvs',
data: [4,8,6,3,5,4,9,8,9,8,6,5],
options: {
colors: ['blue','yellow']
}
}).draw();
Copy
The JavaScript code to copy the text to the clipboard
Here's the javascript code that implements the Copy to clipboard functionality. This is just the function that copies the text that's given to the clipboard.
//
// Copies text to the clipboard.
//
// @param text string The text to copy
// @param span object The span tag that's the copy link
//
function copyToClipboard(text, span)
{
// Get rid of the label if it's present
if (text.endsWith(text)) {
text = text.substr(0, text.length - label.length).trim();
}
// Use the Clipboard API with promises to
// copy text to the clipboard
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(function ()
{
// Change the Copy button to show a Copied label for a few seconds
showNotification(span);
}, function ()
{
alert('[ERROR] Copying to the clipboard failed!');
});
}
}
The HTML markup to add the Copy button to pre tags
Adding the Copy button to pre tags involves setting the tags cssposition to relative and adding an absolutepositionspan tag to the top right of the tag. Example code is as follows (this is the same as that shown above). The button doesn't do anything yet - it's just positioned in the top right corner of the pre tag.
If you try the example above in the introduction with your browser width reduced then you will see the issue with doing this:- being inside the scrolling pre tag, the Copyspan tag scrolls left and right as well as the content - because it's just part of the content that's inside the pre tag.
The positioning solution
There is a solution to this so that the Copy label stays at the top right no matter how much you scroll left or right. The pre tag has to be wrapped in a div tag and the span tag holding the Copy label should be brought outside the pre tag (but still remain within the div tag). So it looks like this:
<div class="codeblock">
<pre class="code">
YOUR CONTENT GOES HERE
<pre>
<span>Copy</span>
</div>
The CSS for the code block
Now, obviously, the structure that's shown above is not going to be of much use by itself - so here's the css code that's necessary to massage the structure into something useful:
/*
* This CSS code styles the copy link in the top right of <pre> code samples. The
* Copy link stays where it is (the top right corner) no matter whether you scroll left/right.
*//* This styles the <div> that wraps the <pre> tag */
div.codeblock {
position: relative;
background-color: #eee; /* You can change this to suit your website */
box-sizing: border-box;
margin-bottom: 20px;
}
/* This styles the <pre> tag */
div.codeblock pre {
overflow-x: auto; /* This facilitates horizontal scrolling*/
margin: 0;
padding: 10px; /* You can change this to give the code more or less space between it and the edge of the block */
width: 100%; /* Make the <pre> tag fill the <div> */
left: 0; /* Position the <pre> to fill the whole <div> */
top: 0; /* Position the <pre> to fill the whole <div> */
right: 0; /* Position the <pre> to fill the whole <div> */
bottom: 0; /* Position the <pre> to fill the whole <div> */
position: absolute; /* Position the <pre> to fill the whole <div> */
box-sizing: border-box;
}
/* This styles the Copy link that you click on to copy the code to your clipboard */
div.codeblock span {
position: absolute; /* Position the link in the top right of the <div> */
top: 15px; /* Position the link in the top right of the <div> */
right: 10px; /* Position the link in the top right of the <div> */
background-color: white; /* Change this to suit your design */
border: 1px dashed gray; /* Change this to suit your design */
padding: 2px 15px; /* Change this to suit your design */
cursor:pointer; /* By changing the cursor it shows the user that they can click this */
font-size: 10pt; /* Change this to suit your design */
font-weight: bold; /* Change this to suit your design */
display: inline-block;
line-height: 15px; /* Change this to suit your design */
}
The showNotification function
When the Copy link is clicked this function provides some feedback to the user by changing the Copy link to show Copied for a few seconds before reverting to Copy.
// Change the copy button to Copied for a couple
// of seconds
//
// @param object span The <span> tag object
//
function showNotification (span)
{
// Add the notification to the page by creating a new <span> tag and positioning it over the Copy link
var el = document.createElement('span');
el.innerText = 'Copied';
el.style.color = 'black';
el.style.transition = 'opacity .25s linear'; // Use a transition to facilitate a fade effect
el.style.opacity = 0; // Initially the opacity is zero
el.style.position = 'absolute'; // Position the Copied text over the Copy text
el.style.top = '2px'; // Position the Copied text over the Copy text
el.style.left = 0; // Position the Copied text over the Copy text
el.style.backgroundColor = 'white';
el.style.display = 'inline-block';
el.style.textAlign = 'center';
span.appendChild(el);
// Set the new <span> tag to cover the Copy text
el.style.width = el.parentElement.offsetWidth - 2 + 'px';
el.style.height = el.parentElement.offsetHeight - 4 + 'px';
el.style.width = el.parentElement.offsetWidth;
// Set the opacity to 1 - and because of the transition this will fade in over a quarter of a second
el.style.opacity = 1;
// Set the Opacity of the Copied text back to zero after two seconds
setTimeout(function ()
{
el.style.opacity = 0;
// Remove the Copied text from the DOM after 0.6 seconds
setTimeout(function ()
{
el.parentNode.removeChild(el);
}, 600)
}, 2000);
}
Add the Copy links to all of the pre tags
Obviously, we need to add a Copy button to each of the code samples on the page that the user can click to copy the code onto their clipboard. The button is a span tag positioned absolutely at the top right. It's a child of the div tag - not the pre tag - so it doesn't scroll if the pre tag scrolls. There's nothing special being done here - just a new span tag being created in javascript and then added to the dom. A click event listener is added to the span which calls the copyToClipboard function passing it the text to put on the clipboard and the span tag object.
//
// Now add a small Copy span to the top right of each code sample pre tag
//
document.addEventListener('DOMContentLoaded', function ()
{
// Get all of the pre tags on the page
var els = document.getElementsByTagName('pre');
// Feel free to change the label to say what you want
var label = 'Copy';
// Loop through all of the pre tags
for (var i=0; i<els.length; ++i) {
// Ensure that the pre tag has a class="code" attribute and if the data-copy="false" attribute is not present
// then continue. If the data-copy="false" attribute is present however then skip this particular pre tag.
if ( els[i].className.indexOf('code') !== -1
&& els[i].getAttribute('data-copy') !== 'false') {
// Create a div and wrap the pre with it
var div = document.createElement('div');
// Wrap the pre element with the div. The wrapElement function is defined further down.
wrapElement(els[i], div);
div.className = 'codeblock';
div.style.backgroundColor = '#eee';
div.style.backgroundImage = 'linear-gradient(-45deg, rgba(255, 255, 255, 0.5), transparent)';
// Set the div position to relative so the Copy
// label appears in the top right corner
els[i].style.position = 'relative';
// Create the span tag that's the Copy link. The style positions
// the button at the top right of the pre tag, gives it a background, a
// border and some padding.
var span = document.createElement('span');
span.innerText = label;
span.style.backgroundColor = 'white'
span.style.border = '1px dashed black';
span.style.color = 'black';
span.style.display = 'inline-block';
span.style.position = 'absolute';
span.style.top = '9px';
span.style.right = '10px';
span.style.cursor = 'pointer';
span.style.padding = '2px 15px 2px 15px';
span.style.fontWeight = 'bold';
span.style.fontSize = '10pt';
span.style.lineHeight = '15px';
div.appendChild(span);
// When the Copy button is clicked call the copyToClipboard function and pass it the contents of the pre
span.onclick = function (e)
{
copyToClipboard(this.parentNode.innerText.replace(label, '').trim(), this)
}
}
}
});
//
// Wrap an element with another
//
// @param el object The element to wrap
// @param wrapper object The element that becomes the wrapper
//
function wrapElement(el, wrapper)
{
el.replaceWith(wrapper);
wrapper.appendChild(el);
}