Search code examples
javascriptprototypejsc3.js

Using Prototype.js with C3.js


I have an old web project that uses prototype.js and I'm trying to add charting to it using C3.

Unfortunately there's an error since prototype seems to add a bunch of methods to arrays and this specific method in c3.js checkValueInTargets uses Object.keys which grabs all the random methods in the array and then throws an error.

Is there a way to "hide" my charting code from prototype or a way to use the default JS arrays?

I can't remove or upgrade prototype unfortunately.

Thanks

sample project:

var chart = c3.generate({
    data: {
        columns: [
            ['data1', 30, 200, 100, 400, 150, 250],
            ['data2', 130, 100, 140, 200, 150, 50]
        ],
        type: 'bar'
    },
    bar: {
        width: {
            ratio: 0.5 // this makes bar width 50% of length between ticks
        }
        // or
        //width: 100 // this makes bar width 100px
    }
});

http://jsfiddle.net/Yq3DW/269/


Solution

  • One easy way to fix it would be to move the prototype script loading to after c3.js chart initialization call.

        ...
        <link href="lib/c3.js/c3.css" rel="stylesheet" />
    </head>
    <body>
        ...
        <div id="chart"></div>
        ...
        <script src="lib/d3/d3.js" charset="utf-8"></script>
        <script src="lib/c3.js/c3.js"></script>
        <script>
            var chart = c3.generate({
                data: {
                    columns: [
                        ['data1', 30, 200, 100, 400, 150, 250],
                        ['data2', 130, 100, 140, 200, 150, 50]
                    ],
                    type: 'bar'
                },
                bar: {
                    width: {
                        ratio: 0.5 // this makes bar width 50% of length between ticks
                    }
                    // or
                    //width: 100 // this makes bar width 100px
                }
            });
        </script>
    
        <script src="lib/prototype/prototype.js"></script>
        <!-- prototype code --->
    </body>
    

    If this is not possible, you could have a script block to store a reference to the native Object.keys and swap it out and back again when calling the C3 code, like so

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>C3</title>
        <meta charset="utf-8" />
        <script>
            var originalKeys = Object.keys;
        </script>
        <script src="lib/prototype/prototype.js"></script>
    </head>
    <body>
        <div id="chart"></div>
    
        <script src="lib/d3/d3.js" charset="utf-8"></script>
        <script src="lib/c3.js/c3.js"></script>
        <link href="lib/c3.js/c3.css" rel="stylesheet" />
        <script>
            var prototypeKeys = Object.keys;
            Object.keys = originalKeys;
            var chart = c3.generate({
                data: {
                    columns: [
                        ['data1', 30, 200, 100, 400, 150, 250],
                        ['data2', 130, 100, 140, 200, 150, 50]
                    ],
                    type: 'bar'
                },
                bar: {
                    width: {
                        ratio: 0.5 // this makes bar width 50% of length between ticks
                    }
                    // or
                    //width: 100 // this makes bar width 100px
                }
            });
            Object.keys = prototypeKeys;
        </script>
    </body>
    </html>
    

    Luckily tooltips don't cause any problems


    Fiddle - http://jsfiddle.net/td433xt1/