Use image generated from local HTML in widget

Hi there,

I’m not very familiar with JavaScript and after lots of Googling I still can’t get any further, so any help is appreciated!

I have a local HTML file in iCloud Drive. This file contains some JS that fetches an image from a webpage (not local) and shows the image in an HTML element. I want to use the image on that page in a widget, but I don’t know how to get the image from the page and use it in a widget.

<meta http-equiv="Content-Type" content="image/png"/>

<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js'></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<div id="container" style='width: 0px; height: 0px;'></div>

<script>
var options = {
  chart: {},
  xAxis: {
    categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
    ]
  },
  series: [{
    data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4],
    type: 'column'
  }]
}

var chart = Highcharts.chart('container', options);

var data = {
    type: 'POST',
    options: JSON.stringify(options),
    filename: 'test.png',
    type: 'image/png',
    async: true
};

var exportUrl = 'https://export.highcharts.com/'
$.post(exportUrl, data, function(data) {
    var imageUrl = exportUrl + data
    fetch(imageUrl)
      .then(response => response.blob())
      .then(data => {
        // You have access to chart data here
        let img = new Image()
        img.src = URL.createObjectURL(data)
        document.body.appendChild(img)
        document.getElementsByTagName("img")[0].setAttribute("id", "chart");
        // console.log(document.getElementById("chart").src);
    });
});

</script>

I load this file into a WebView using loadFile(). Using the present() method I can see the image I want to use in the widget. I looked at this post as well as this one, to try and grab the image, but that does not seem to work.
I tried grabbing the image using evaluateJavascript(), but this returns an error:

let fm = FileManager.iCloud()
let dir = fm.documentsDirectory()
let fileName = "index.html"
let path = fm.joinPath(dir, fileName)
let wv = new WebView()

await wv.loadFile(path)
wv.present()

let js = "document.getElementById('chart').src"
let image = await wv.evaluateJavaScript(js)
console.log(image)

The resulting error is:

Error: Failed evaluating JavaScript with error on line 1: TypeError: null is not an object (evaluating 'document.getElementById('chart').src')

I noticed other scripts use Request.loadImage() to load the image, but that only seems to work for non-local pages.

How would you grab the image from the WebView so I can use it in a widget?
Thanks!

Rather than creating a custom widget, can you use the Glimpse 2 app to display a portion of the web page in a widget?

You could post the data directly from Scriptable and receive the image url.

But I’m assuming the data is being generated somewhere else and you can’t hard-code it on the script. That wouldn’t be of much use. See if it’s possible to fetch the chart data from Scriptable or get whatever generates that file to maybe save the data as a separate .json file. That way, you could read from your script easily.

Here’s the converted script to fetch the image and show in a widget.

var options = {
  chart: {},
  xAxis: {
    categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
    ]
  },
  series: [{
    data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4],
    type: 'column'
  }]
}

var data = {
    type: 'POST',
    options: JSON.stringify(options),
    filename: 'test.png',
    type: 'image/png',
    async: true
};


var exportUrl = 'https://export.highcharts.com/'
var req = new Request(exportUrl)
req.method='POST'
req.headers={
  "Content-Type":"application/json"
}
req.body = JSON.stringify(data)
var resp = await req.loadString()
var imageUrl = exportUrl + resp

log (imageUrl)

var img = await (new Request(imageUrl)).loadImage()
// 
// QuickLook.present(img)

var widget = new ListWidget()
widget.backgroundImage = img
Script.setWidget(widget)

await widget.presentLarge()
1 Like

Thanks! Using your approach worked :slight_smile: