Jump to content

Hi there,

I could use the help of someone who is more experienced in web dev than I am.

 

The bigger picture: I want to enable users of a page to save parts of it as a pdf, simply using the print() method and some CSS styling in @media print. SInce there is a metric ton of CSS that I have no control over, I want to "start fresh", open a new window, insert the bits of html that I want, add a single stylesheet that formats that page for printing, print() and close it again. Not the prettiest way, but it works.

Now for my problem. The page contains a more complex canvas element (utilizing ChartJS). Since I only want to print it, I simply want to insert it as an <img> into the 'print page' by doing something like this:

 

[.....]
var myCanvas = document.getElementById('myChart');
var source = myCanvas.toDataUrl();
var image = "<img src=' " + source + " '></img>"
myWindow.document.write(image);

 

However: this returns a "Uncaught TypeError: myCanvas.toDataUrl is not a function" and yeah, true, somehow document.getElementById('myChart').toDataUrl returns undefined.

 

BUT: and this is, what I cannot get my head around: if I debug this in Chrome and access the myCanvas object in the console, it has and can execute the toDataUrl() just fine.

 

So when I do something like the folliwing:

 

 

[.....]
var myCanvas = document.getElementById('myChart');
// var source = myCanvas.toDataUrl();
var source;
// set a breakpoint here and simply assign 'source' in the chrome console via "source = myCanvas.toDataUrl()"
// and continue executrion
var image = "<img src=' " + source + " '></img>"
myWindow.document.write(image);

 

everything works just fine. 

 

This snipped was taken from the chrome console, just after the myCanvas variable is assigned:

 

> myCanvas
         <canvas height="500" id="myChart" style="display: initial; width: 500px; height: 500px; background-color: rgba(255, 255, 255, 0.8);" width="500">
            </canvas>
> document.getElementById('myChart');
        <canvas height="500" id="myChart" style="display: initial; width: 500px; height: 500px; background-color: rgba(255, 255, 255, 0.8);" width="500">
            </canvas>
> document.getElementById('myChart').toDataUrl;
         undefined
> myCanvas.toDataURL
         toDataURL() { [native code] }

 

Can anybody explain this?

 

Best regards,

Chris

"We cannot change the cards we're dealt - just how we play the hand" - R. Pausch

 

CPU: Ryzen 7 3700X , Cooler: BeQuiet Dark Rock 3 Motherboard: MSI B450 Mortar Titanium RAM: 16 GB Corsair LPX 3200 GPU: EVGA RTX2070 XC Storage: Adata 120GB SSD, SanDisk 1TB SDD, 2TB WD GreenHDD Case: Fractal Design Define Mini C PSU: EVGA Supernova 650GS Peripherals: Master Keys Pro S, Logitech G402 Audio: Schiit Fulla 2 + Sennheiser HD 650. Laptop: Asus Zenbook UX 302

Link to comment
https://linustechtips.com/topic/622279-html-js-method-only-availlable-in-console/
Share on other sites

Link to post
Share on other sites

How have you populated the canvas? If it contains any images that aren't from your domain, you can't call toDataURL because that would allow you to see what that image is, and the image was requested using the user's credentials (cookies etc), so you may be able to use that to figure out information about the user. The image needs to be served from your domain, or include the Cross-Origin Resource Sharing headers.

The console runs with slightly more privilege, so that may be able to bypass the CORS checks.

HTTP/2 203

Link to post
Share on other sites

Are you running the javascript before the document has rendered? Sounds like a timing issue to me.

Aragorn (WS): 250D | 6800k | 840 Pro 512GB | Intel 530 480GB  | Asus X99-M WS | 64GB DDR4 | Corsair HX720i | GTX 1070 | Corsair H115i | Philips BDM4350UC 43" 3840x2160 IPS

Gimli (server):  Node 304 | G4560 | ADATA XPG SX8000 128GB | 2x 5TB WD Red | ASROCK H270M-ITX/AC  | 8GB DDR4 | Seasonic 400FL

 Omega (server):                 Fractal Arc Mini R2 | i3 4130 | 500GB Maxtor | 2TB WD Red : Raid 1 | 3TB Seagate Barracuda | 16GB RAM | Seasonic G-450w
Alpha (WS): 900D | 4770k | GTX 780  | 840 Pro 512GB  | GA-Z87X-OC | Corsair RM 850 | 24GB 2400mhz | Samsung S27B970D 2560x1440

                              ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Link to post
Share on other sites

11 minutes ago, colonel_mortis said:

How have you populated the canvas? If it contains any images that aren't from your domain, you can't call toDataURL because that would allow you to see what that image is, and the image was requested using the user's credentials (cookies etc), so you may be able to use that to figure out information about the user. The image needs to be served from your domain, or include the Cross-Origin Resource Sharing headers.

The console runs with slightly more privilege, so that may be able to bypass the CORS checks.

No, the canvas is created using ChartJS, the libs are located locally on the server, so the "image" is generated on the same page.

I found the error. It's really simple.  And kind of embarassing that I spent like two hours searching for a solution - repeating the same mistake over and over again using auto-complete.

 

look closely:

 

myCanvas.toDataURL     vs.     document.getElementById('myChart').toDataUrl();

.

.

.

 

It's a typo. URL has to be all caps. Simple as that. :|

 

I'm gonna need a coffee break right now :D

 

 

"We cannot change the cards we're dealt - just how we play the hand" - R. Pausch

 

CPU: Ryzen 7 3700X , Cooler: BeQuiet Dark Rock 3 Motherboard: MSI B450 Mortar Titanium RAM: 16 GB Corsair LPX 3200 GPU: EVGA RTX2070 XC Storage: Adata 120GB SSD, SanDisk 1TB SDD, 2TB WD GreenHDD Case: Fractal Design Define Mini C PSU: EVGA Supernova 650GS Peripherals: Master Keys Pro S, Logitech G402 Audio: Schiit Fulla 2 + Sennheiser HD 650. Laptop: Asus Zenbook UX 302

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×