News and updates for 2022

Pick a year: Stay up-to-date withe RGraph news RSS feed

Uploading an image directly from the clipboard

Written by Richard, 19th September 2022

For me, this is a holy-grail type thing! Uploading images to websites is a bit of a faff if you ask me - first copy the image to the clipboard (no problems there - just press PrtScr to take a screenshot) but then you have to save the image to a file - and this involves opening up a paint program (eg MSPaint, Paint Shop Pro or Photoshop); pasting the image into it; save it to a file and finally you have a file which you can upload to the website using the standard file upload control.

Well this is an example of a page that reads the clipboard directly when uploading an image so that all you now have to do is press PrtScr to grab a screenshot and paste it into the webpage. Oh and press the submit button to submit the form...

The following code is a full, self-contained page so you can grab the code and paste it into a file on your server and it should work. All it does is allow you to paste an image onto the page and then upload it. Once uploaded it will show you the resulting data.

The idea for this code came from a jsFiddle snippet by someone called Nick. There's a live demo of this code here:

https://www.rgraph.net/blog/clipboard-file-upload.php

<?php
    if (!empty($_POST)) {

        // Handle the POSTed data here - the image is actually base64 encoded data in
        // the $_POST['myTextarea'] variable which you can run through the base64_decode()
        // function and then write to a file

        $pos     = strpos($_POST['myTextarea'], 'base64,');     // Get the position of the string "bas64,"
        $encoded = substr($_POST['myTextarea'], $pos + 7);      // Get the base64 data (which starts after the comma)
        $raw     = base64_decode($encoded);                        // Decode the base64 data into raw binary

        // Show the base64 encoded data - use the $raw variable when writing to a file
        var_dump($_POST);
        exit;
    }
?>
<!DOCTYPE html >
<html>
<body>

<h1>File upload using paste</h1>

<p>
    You can paste an image, which is on your clipboard, into this window and it will appear below.
    If you use Windows you can press <b>PrtScr</b> to get a screenshot on your clipboard. Then
    press <b>CTRL+V</b> to paste it into this document.
</p>

<!-- P   -->
<form action="" method="post">
    <div id="form-elements-container">
        <input type="text" value="An example text input..." name="myTextInput"><br />
        <input type="submit" value="Submit form"><br />
    </div>
</form>

<!-- This is where the image thumbnail(s) will appear -->
<div id="images-container"></div>

<script>
    counter = 0;

    // All of this code runs when the image is pasted into the page
    document.body.onpaste = function (e)
    {
        var items = (e.clipboardData  || e.originalEvent.clipboardData).items;

        // Find pasted image among pasted items. If the type is not an image
        // then it gets ignored
        var blob = null;
        for (var i=0; i<items.length; i++) {
            if (items[i].type.indexOf("image") === 0) {
                blob = items[i].getAsFile();
            }
        }

        // Load image if there is a pasted image
        if (blob !== null) {

            var reader = new FileReader();

            reader.onload = function(e)
            {
                // Create a new image object from the pasted data
                var img    = new Image();
                img.src    = e.target.result;
                img.width  = 128;
                img.height = 128;
                img.style.margin = '5px';

                // Append the file to the document
                document.getElementById('images-container').appendChild(img);

                // Add a new textarea to the form
                var textarea    = document.createElement('textarea');
                textarea.name   = 'myTextarea_' + counter++;
                textarea.value  = img.src;
                textarea.style.width  = '128px';
                textarea.style.height = '200px';
                document.getElementById('form-elements-container').appendChild(textarea);

            };

            reader.readAsDataURL(blob);
        }
    }
</script>
</body>
</html>

Version 6.09 of RGraph now available

Written by Richard, 11th September 2022
A new version of RGraph has been released

Version 6.09 of RGraph is now available to download from the download page. This is another minor release with no huge additions - the reason for the new release is that there's a change to the website that I'll be making and don't wish things to get mixed up.

You can download RGraph here

Updated multi-color Line chart demo

Written by Richard, 17th August 2022

[View the example on CodePen.io]

Here's an updated version of a demo that's already in the download archive. The colors have been changed, tickmarks added, it now uses the ES6 spread operator when copying the configuration to the second chart, a key has been added and the way that the gradients are setup (using the beforedraw RGraph event). All the code for it is shown below and it should work as-is with version 6.08.

// The data for both of the Line chart objects
data = [8,4,6,2,1,5,3,3,4,8,9,8,4,1,3,4,7,8,8,5,6,4,1,2,3,4,2,3,1,5,3,5,1,5,6,8,7,9];

// Draw a Line chart that shows the fill of the chart
line = new RGraph.Line({
    id: 'cvs',
    data: data,
    options: config = {
        xaxisLabels: [
            '','Q1\n2014','',       '','Q2\n2014','',
            '','Q3\n2014','',       '','Q4\n2014','',
            '','Q1\n2015','',       '','Q2\n2015','',
            '','Q3\n2015','',       '','Q4\n2015',''
        ],
        filled: true,
        backgroundGridColor: '#ddd',
        backgroundGridVlines: false,
        backgroundGridBorder: false,
        xaxis: false,
        yaxis: false,
        spline: true,
        yaxisScaleUnitsPost: '%',
        marginLeft: 50,
        marginBottom: 50,
        textColor: 'gray',
        colors: ['rgba(0,0,0,0)'],
        shadow: false,
        tickmarksSize: 3,
        tickmarksStyle: 'filledcircle',
        key: ['Very Low','Normal','High','Very high'],
        keyColors: ['blue','green','orange','red'],
        keyPosition: 'margin',
        keyPositionX: 65,
        keyColorShape: 'circle',
        keyLabelsSize: 16,
        linewidth: 3,
        textSize: 16,
        textFont: "'Calibri Light', sans-serif"
    }
}).on('beforedraw',function (obj)
{
    // Create the gradient that is used as the stroke color
    grad = obj.context.createLinearGradient(0,35,0,200);
    grad.addColorStop(0, '#FF642C');
    grad.addColorStop(0.25, '#FF642C');
    grad.addColorStop(0.25, 'orange');
    grad.addColorStop(0.5, 'orange');
    grad.addColorStop(0.5, '#5ADDAA');
    grad.addColorStop(0.75, '#5ADDAA');
    grad.addColorStop(0.75, '#2BB3FF');
    grad.addColorStop(1.0, '#2BB3FF');
    
    
    // Create the gradient that is used as the fill color
    gradFill = obj.context.createLinearGradient(0,35,0,200);
    gradFill.addColorStop(0, '#F8D3D7');
    gradFill.addColorStop(0.25, '#F8D3D7');
    gradFill.addColorStop(0.25, '#FFE1D8');
    gradFill.addColorStop(0.5, '#FFE1D8');
    gradFill.addColorStop(0.5, '#E0F9EE');
    gradFill.addColorStop(0.75, '#E0F9EE');
    gradFill.addColorStop(0.75, '#DAF0FF');
    gradFill.addColorStop(1.0, '#DAF0FF');

    // Apply the gradient to the charts fill
    obj.set({
        filledColors: [gradFill]
    });
}).draw();




// Now create and draw the second, non-filled line that sits on
// top of the fill.
line2 = new RGraph.Line({
    id: 'cvs',
    data: data,
    options: {
        ...config,
        filled: false,
        labels: null,
        xaxis: false,
        yaxis: false,
        yaxisLabels: false,
        backgroundGrid: false,
        colors: [grad]
    }
}).draw();

New Line chart Wave effect

Written by Richard, 17th August 2022

I think that I may have mentioned this on the RGraph socials - but not here. so here's a mention of the new Line chart wave effect. It's on CodePen because the code for it will be a part of version 6.09 and that hasn't been released yet. Soon though...!

It acts just like the Bar chart Wave effect and looks particularly good when it's part of a transition effect - and there'll be an example of that on the Line chart documentation page and also in the download archive (from version 6.09).

Caching added to the RGraph forum

Written by Richard, 12th August 2022

This may be interesting to you - I've just added caching to the RGraph forum. Two types have been added:

  1. HTTP caching headers
  2. Server-based pre-rendering

HTTP caching headers

Adding HTTP headers for caching was an easy win - simply add the relevant HTTP headers and browsers will attempt to cache the response (ie the page) that the server sends. The headers that have been added are as follows:

Cache-Control: public, private, max-age=604800
Expires: Fri, 19 Aug 2022 09:56:47 GMT

So the response is cached for a week and can be cached by your browser and also by other caches too (eg ones at your ISP or other intermediaries).

Server-based pre-rendering

This is a bit more interesting and a little bit more involved than simply adding some extra HTTP headers to the response. What is done is a script that runs every so often makes a HTTP request for the forum pages (the ones that are closed) - the resulting output is stored in a file on disk. The full HTML page that's written to disk is exactly what you see when you request the page with your browser.

Then, when you request a forum post (one that's closed), if it's in the cache it gets sent to your browser instead of the page being built from the contents of the database. So there's less load on the database (something I'm sure the ISP will thank me for). The cache is cleared and then the pages are re-cached every four hours by a cron job (a scheduled task).

If you're thinking of employing this type of caching then you need to ensure that the HTML that makes up the page doesn't change. If it does then you could end up with stale, cached copies of your pages being shown instead of up-to-date copies.

Rewriting URLS without Apache - a reversal

Written by Richard, 6th August 2022

You may remember me writing about a new way of doing rewrites - without the Apache mod_rewrite module . Well, after a year or so of using this method I've decided to revert back to the standard way of doing Apache rewrites and redirects - ie using the RewriteRule directive (as well as the RedirectPermanent directive too).

Why?

Living with the new method just proved to be "not quite as simple" as using traditional methods with too many things to keep in mind. For example, the script name wasn't the same as the request URI - not a problem really - but something to remember and if you didn't you could easily get caught out.

Also, when I originally blogged about this method, I noted that performance wasn't an issue unless you had thousands of redirects. Now, I don't have any hard numbers to support this, but I do have a "feeling" (based on observations) that using the Apache directives is faster in practice than the new method. I think that I can note a very slight improvement - possibly due to there being no massive PHP file to parse. But, as with a lot of things, this may be just in my head!

So how have you laid out the redirects?

All the redirects are now placed in a single .htaccess file (previously they were in seperate files in each directory),grouped by directory and commented clearly to make finding things easy. For example:

################################
# Redirect regular expressions #
################################
RedirectMatch /canvas/docs/adjusting-linehtml.* /canvas/adjusting-line.html
RedirectMatch ^/demos/bar-basic.html.+          /demos/bar-basic.html
RedirectMatch ^/fiddle.*                        /demos/index.html

# ...

################
# REDIRECTS: / #
################
RedirectPermanent /interactive  /demos/index.html
RedirectPermanent /interactive/ /demos/index.html
RedirectPermanent /browser      /install/browsers.html

# ...

####################
# REDIRECTS: /blog #
####################
RedirectPermanent /blog/index.html/index.html /blog/index.html
RedirectPermanent /blog/index.html/2011       /blog/index.html
RedirectPermanent /blog/index.html/2012       /blog/index-2012.html

# ...

######################
# REDIRECTS: /canvas #
######################
RedirectPermanent /canvas/funnel                /canvas/funnel.html
RedirectPermanent /canvas/misc.html/            /canvas/misc.html
RedirectPermanent /canvas/interactive-keys.html /canvas/keys.html#interactive-keys

Not too difficult to maintain and quick. What everyone wants right?

Two new interesting demos

Written by Richard, 23rd July 2022

Two new demos have been added, which will be available in the next release (6.09). One of the demos is called line-big-data.html and is an example of showing a large amount of data using the Line chart. In this case, there are 100,000 points shown. The rendering takes about half a second. To help improve the rendering time certain bits of the chart are turned off - namely the X axis, the Y axis and the background grid vertical lines.

The other demo is a Bar chart that uses the responsive callback option to switch to a Horizontal Bar chart when the screen size is smaller. The whole code for this chart is shown below. It uses a very simple Bar chart to set things up and install the responsive configurations. Then each responsive configuration has a callback function that resets the canvas and then draws the appropriate chart.

<script>
    //
    // Some information that's used by both charts
    //
    data          = [4,8,6,4,5,3,1,9,5,8];
    labels        = ['Bob','Jim','Lou','Pob','Kev','Doug','Bono','Vinny','Fee','Yugo'];
    marginInner   =  10;
    tooltipsStyle = {fontSize: '18pt'};
    
    //
    // This is the initial basic Bar chart that sets
    // up the responsive configurations. It's the
    // responsive callback functions that actually
    // draw the charts.
    //
    new RGraph.Bar({
        id: 'cvs',
        data: [],
        options: {
        }
    }).responsive([
        {maxWidth: null, width: 700, height: 350, callback: drawBar},
        {maxWidth: 750,  width: 450, height: 700, callback: drawHbar}
    ]);
    
    //
    // This function resets the canvas and then draws
    // a Horizontal Bar chart.
    //
    function drawHbar ()
    {
        RGraph.reset('cvs');
        
        new RGraph.HBar({
            id: 'cvs',
            data: data,
            options: {
                colors: ['Gradient(#fcc:#f00:#f00)'],
                yaxisLabels: labels,
                marginInner: marginInner,
                backgroundGridHlines: false,
                backgroundGridBorder: false,
                xaxis: false,
                textSize: 16,
                labelsAbove: true,
                labelsAboveUnitsPost: '%',
                tooltips: '%{property:yaxisLabels[%{group}]}s results: %{value}%',
                tooltipsCss: tooltipsStyle,
                yaxisLabelsOffsetx: -10,
                marginLeft: 75,
                marginLeftAuto: false
            }
        }).draw();
    }
    
    //
    // This function resets the canvas and then draws
    // a Bar chart.
    //
    function drawBar ()
    {
        RGraph.reset('cvs');
        
        new RGraph.Bar({
            id: 'cvs',
            data: data,
            options: {
                colors: ['Gradient(#fcc:#f00:#f00)'],
                xaxisLabels: labels,
                marginInner: marginInner,
                backgroundGridVlines: false,
                backgroundGridBorder: false,
                yaxis: false,
                textSize: 16,
                labelsAbove: true,
                labelsAboveUnitsPost: '%',
                tooltips: '%{property:xaxisLabels[%{group}]}s results: %{value}%',
                tooltipsCss: tooltipsStyle,
                xaxisLabelsOffsety: 5,
                marginBottom: 45
            }
        }).draw();
    }
</script>

Version 6.08 of RGraph now available

Written by Richard, 16th July 2022
A new version of RGraph has been released

Version 6.08 of RGraph is now available to download from the download page. This is another minor release with no huge additions though a key default - the textAccessible property - has changed to default to false (ie the textAccessible option is not used).

This means that the text on your chart(s) will no longer be selectable for clipboard operations. This change was implemented for purposes related to the RGraph website.

If you want to use accessible text you will need to explicitly set the textAccessible option to true in your charts configuration.

You can download RGraph here

All charts on the RGraph website have been switched to canvas-based text

Written by Richard, 15th June 2022

Perhaps you're aware of the RGraph websites' utterly dire performance on Google. Just google "javascript charts" (no quotes) and you will see. If you're in the UK the site may be on page 3 or 4 and if you're elsewhere in the world then you'll probably see it even lower.

This has been a constant cause of pain for me over the past ten (!) years. I'm frequently doing various things to try and increase the ranking - nothing ever works.

My latest attempt has been to switch all of the charts on the website from using accessible text to using canvas-based text. The default hasn't changed, however, so if you use RGraph your charts will be unaffected and your site is also unlikely to be affected this. This website however has many, many pages which show charts(100-200) so the setting might well be having an effect.

It will take time for everything to be re-indexed and maybe even more time for the relevant Google algorithm to run and reassess the website so this change will take time to have an effect - if it has one at all!

AJAX image uploads now available for forum posts

Written by Richard, 6th May 2022
AJAX file uploads for new forum posts

It seems to be quite the rage at the moment - AJAX file uploads for forms. So now you can attach up to three images (each of which can be up to 100k in size) to your forum posts (not replies though). If it gets abused I'll have to review it's use - but I think it should be fine. Famous last words... I've also implemented deep anchors - so instead of just linking to the page and then having to find the reply that may interest you - you can link directly to it. See it in action on the forum:

Visit the RGraph forum

Version 6.07 of RGraph now available

Written by Richard, 10th April 2022
A new version of RGraph has been released

Version 6.07 of RGraph is now available to download from the RGraph website. This is another minor release with no huge changes though there are a couple of new functions that will help you with creating dual color (Line) charts (an example of which is shown below) . There are other bug fixes and minor changes. You can download RGraph from the download page: https://www.rgraph.net/download.html#stable

SVG Bipolar updated to support uneven data

Written by Richard, 1st April 2022 A Bipolar chart with uneven data

This isn't an April Fools joke I promise (!) - the SVG Bipolar chart has been updated to support uneven data. What does this mean? Well just take a look at the image shown here - you can now mix regular and grouped/stacked sets of bars on the same chart and it won't explode! Which is nice.

New clipping functions

Written by Richard, 28th March 2022

Following on from the previous dual-color Line chart demo here's another example of that sort of chart. The difference with this one is that it uses two new functions that have been added to RGraph: RGraph.ClipTo.start() and RGraph.clipTo.end() These functions will be available from version 6.07 and make clipping the canvas easier. The documentation for them will be part of the API docs (it will only be there after version 6.07 has been released).

The beforedraw and draw RGraph events are still used to set up and remove clipping, but the RGraph functions make doing this far clearer and easier to understand.

View the example on codepen.io


// This is the first chart and draws the green,
// top half of the chart
line1 = new RGraph.Line({
    id: 'cvs',
    data: data = [
        4,8,6,3,2,4,-5,-4,5,6,-1,-9,1,2,-3,-5,-7,-4,-2,-2,6,2,3,4,
        4,8,6,2,3,5,1,4,9,5,6,4,3,8,7,5,6,4,5,1,2,3,4,6
    ],
    options: {
        textSize: 15,
        xaxisPosition: 'center',
        yaxis: false,
        backgroundGridHlinesCount: 10,
        backgroundGridVlines: false,
        backgroundGridBorder: false,
        shadow: false,
        linewidth: 0.5,
        colors: ['green'],
        filled: true,
        filledColors:['rgba(0,255,128,0.25)'],
        marginInner: 15,
        spline: true,
        xaxisLabels: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
        xaxisTickmarksCount: 12
    }
}).on('beforedraw', function (obj)
{
    // This is the new function that makes clipping the
    // canvas much easier. It can take a multitude of different
    // arguments. In this case, it simply clips to the top half
    // of the canvas (and then the other chart clips to the
    // bottom half). You can read about all of the different
    // ways that you can call this function in the API documentation
    // ( https://www.rgraph.net/canvas/api.html#functions.clipping )
    // and there's four examples that use it in the demos in
    // the download archive.
    RGraph.clipTo.start(obj, 'tophalf');

}).on('draw', function (obj)
{
    // This complements the above RGraph.clip.start() function and
    // ends clipping - returning the canvas to a neutral state.
    RGraph.clipTo.end(obj);
}).trace();



// And this is the second, red Line chart that's shown on the
// lower half of the chart.
line2 = new RGraph.Line({
    id: 'cvs',
    data: line1.data,
    
    // Set the options for the second chart. The ES6 "spread" operator (...)
    // is used here to reuse the options that were set in the first
    // object. Further options are then set in order to distinguish
    // it from the first chart.
    options: {
        ...line1.properties,
        colors: ['red'],
        filledColors: ['rgba(255,128,128,0.25)'],
        yaxisLabels: false,
        xaxisLabels: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
    }
}).on('beforedraw', function (obj)
{
    // Start clipping the canvas - this time to the lower half of
    // the canvas.
    RGraph.clipTo.start(obj, 'bottomhalf');

}).on('draw', function (obj)
{
    // End clipping
    RGraph.clipTo.end(obj);
}).trace();

New dual-color Line chart added to the download archive

Written by Richard, 20th March 2022

View the example on CodePen.io

I've just added a new demo to the RGraph download archive which shows a dual-color Line chart - one color for positive values and another color for negative values. The demo code is shown below and it should function correctly with version 6.06 of RGraph (the current version). It will be included in the next available download archive (version 6.07) whenever that is available.

The chart uses the beforedraw and draw events in order to install and remove clipping - which facilitates using two separate colors for positive and negative values.

Note also that the second chart uses the ES6 spread operator so if you're using a particularly old browser then this demo may not function correctly.

// The first line chart is clipped to the top half of the
// canvas so you only see the top half of the chart. The
// clipping is installed by the beforedraw event and then
// removed by the draw event. As a result you only see the
// top half of the chart (which is red)
new RGraph.Line({
    id: 'cvs',
    data: data = [
        4,8,6,3,2,4,-5,-4,5,6,-1,-9,1,2,-3,-5,-7,-4,-2,-2,6,2,3,4,
        4,8,6,2,3,5,1,4,9,5,6,4,3,8,7,5,6,4,5,1,2,3,4,6
    ],
    options: opt = {
        textSize: 15,
        xaxisPosition: 'center',
        yaxis: false,
        backgroundGridHlinesCount: 10,
        backgroundGridVlines: false,
        backgroundGridBorder: false,
        shadow: false,
        linewidth: 0.5,
        colors: ['red'],
        filled: true,
        filledColors:['rgba(255,128,128,0.25)'],
        marginInner: 15,
        spline: true,
        xaxisLabels: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
        xaxisTickmarksCount: 12
    }
}).on('beforedraw', function (obj)
{
    obj.path(
        'sa b r % % % % cl',
        0,0,obj.canvas.width,obj.canvas.height / 2
    );
}).on('draw', function (obj)
{
    obj.path('rs');
}).trace();


// This is the chart object that shows the bottom half of the
// chart. Again, clipping is used to accomplish this and is again
// installed by the beforedraw and removed by the draw events.
// This chart uses blue colors instead instead of red.
new RGraph.Line({
    id: 'cvs',
    data: data,
    options: {
        ...opt, // Use the ES6 spread operator to combine
                // the options from above
        colors: ['blue'],
        filledColors: ['rgba(128,128,255,0.25)'],
        yaxisLabels: false,
        xaxisLabels: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
    }
}).on('beforedraw', function (obj)
{
    obj.path(
        'sa b r % % % % cl',
        0,obj.canvas.height / 2,obj.canvas.width,obj.canvas.height / 2
    );
}).on('draw', function (obj)
{
    obj.path('rs');
}).trace();

Older demo added to the download archive

Written by Richard, 6th February 2022

I realised recently that a demo that I showed a screenshot of on this blog, albeit some time ago, wasn't in the download archive. So I've remedied this and the new demo is called demos/bar-grouped-purple.html (it'll be in the next release). Here's a screenshot of it in case you're curious. Click the image to view the source code on GitHub.

A grouped Bar chart

Version 6.06 of RGraph is now available

Written by Richard, 22nd January 2022
A new version of RGraph has been released

RGraph version 6.06 is now available! In the first release of 2022 the main change is that there's now a set of functions that are dedicated to making importing data from the query string (the URL) easier. These new functions are called:

  • RGraph.GET.number()
  • RGraph.GET.string()
  • RGraph.GET.json()
  • RGraph.GET.array()
And for SVG:
  • RGraph.SVG.GET.number()
  • RGraph.SVG.GET.string()
  • RGraph.SVG.GET.json()
  • RGraph.SVG.GET.array()
The RGraph.GET.json() function is most useful in my opinion as it allows you to import an entire JavaScript object which can contain multiple things - for example both data and labels. You should be aware, though, that if not properly encoded JSON can interfere with SEO efforts. You can read more about the query string functions on this page. There are a few other changes that you can read about on the changelog page.

You can download the software from the download page:

https://www.rgraph.net/download.html#stable

Pick a year: Stay up-to-date withe RGraph news RSS feed