Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Publishing a chart from Google Sheets produces fixed-width result

A client has many Google spreadsheets containing data from which they have generated charts on new sheets within the workbook. I have provided code which enables them to publish the chart (which previously generated a <script> element containing JSON), copypaste the published JSON into their CMS, and have the end result be a generated responsive <iframe>. The chart's width option is changed on the fly to match the container, and the usual trick of reloading the chart when the browser is resized handles keeping it that way.

However, Google Sheets has been updated and the client's new charts only have an option to publish as "Link" or "Embed", where the latter is just an <iframe> wrapped around the former. As the <iframe> is published with a fixed width, I have updated my code to handle this alternative, changing the width attribute of the iframe on the fly.

The problem is that the internal contents of this iframe are now completely generated by Google with a fixed width, rather than a width which matches the containing iframe (whose width I am setting).

I can't reach into the iframe to modify the document from script, as it's from a different domain. The original chart embedded in the spreadsheet is responsive (resizing the browser window containing the spreadsheet resizes the chart very nicely) but I cannot see any way to maintain that effect during publishing.

I could move everything out into script that directly uses the visualization API, but then it's not using the client's pre-generated charts (and it seems like every chart they produce is a different style/layout, which would be a maintenance nightmare).

So: how can I publish a pre-existing chart from a Google Sheets document, with the published result being responsive in the same way as the original chart?

like image 416
Matt Sach Avatar asked Jan 16 '15 11:01

Matt Sach


2 Answers

If you can live with scaling and smaller text / thin lines.

Solution is using this JS + JQuery Scaling method in HTML head section, this written by yazzz here, kudos to her/him in that link, not in here.

<head>
<script 
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js">
</script>
<script>
// this script is written by yazzz https://stackoverflow.com/a/35819751/9894532
$(function() {
    $("#wrapper").each(function() {
        var $wrap = $(this);
        function iframeScaler(){
            var wrapWidth = $wrap.width(); // width of the wrapper
            var wrapHeight = $wrap.height();
            var childWidth = $wrap.children("iframe").width(); // width of child iframe
            var childHeight = $wrap.children("iframe").height(); // child height
            var wScale = wrapWidth / childWidth;
            var hScale = wrapHeight / childHeight;
            var scale = Math.min(wScale,hScale);  // get the lowest ratio
            $wrap.children("iframe").css({"transform": "scale("+scale+")", "transform-origin": "left top" });  // set scale
        };
        $(window).on("resize", iframeScaler);
        $(document).ready( iframeScaler);
    });
});
</script>
</head>

<body>
<p>Responsive and Dynamic Iframe Scaling of Published Chart from Google Spreadsheet</p>
<p>Courtesy of <a href="https://stackoverflow.com/a/35819751/9894532">yazzz from Javascript StackOverflow</a></p>

<div id="wrapper">
    <iframe width="500" height="294" seamless frameborder="0" scrolling="no" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vRB4wPFarqsHWgk0ubQ6bH3YC5iwvDayAkrDg0iNPipAAszBA26QnFaPC1Xk5g8XF1ixP7jnsxiaMzL/pubchart?oid=1495533449&amp;format=interactive"></iframe>
</div>

</body>

You can view his/her implementation of my sample here in JS Fiddle

like image 82
Marhensa Avatar answered Nov 18 '22 06:11

Marhensa


From what I saw the issue is that the google sheets canvas is usually around 50% of mobile size, so here is my solution. It's a bit weird but works for me:

@media (max-width:500px) {
    body p:has(iframe[src^="https://docs.google.com/spreadsheets"]) {
        transform: scale(0.5);
        transform-origin: top left;
    }
    body p iframe[src^="https://docs.google.com/spreadsheets"] {
        min-width: 200%;
        position: relative;
        left: 100%;
        margin-bottom: -180%;       
    }
}
like image 1
Ofer Laor Avatar answered Nov 18 '22 06:11

Ofer Laor