p5.js icon indicating copy to clipboard operation
p5.js copied to clipboard

print("content") outside of setup/draw invokes print dialog. possible to catch with FES?

Open alexdmiller opened this issue 4 years ago ā€¢ 23 comments

Most appropriate sub-area of p5.js?

  • [ ] Color
  • [x] Core/Environment/Rendering
  • [ ] Data
  • [ ] Events
  • [ ] Image
  • [ ] IO
  • [ ] Math
  • [ ] Typography
  • [ ] Utilities
  • [ ] WebGL
  • [ ] Other (specify if possible)

Details about the bug:

  • p5.js version: 0.10.2
  • Web browser and version: Firefox 72.0.2
  • Operating System: MacOS 10.14 (Mojave)
  • Steps to reproduce this:

The following code causes the print dialog to appear in Firefox (using editor.p5js.org).

print("Hello world!")

alexdmiller avatar Feb 07 '20 17:02 alexdmiller

Welcome! šŸ‘‹ Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.

welcome[bot] avatar Feb 07 '20 17:02 welcome[bot]

Hm odd! I am not able to recreate on Mac 10.15.2 using the online editor and Firefox 72.0.2. This sketch just prints the text in the console for me:

function setup() {
  print("Hello world!")
}

stalgiag avatar Feb 08 '20 01:02 stalgiag

Ah, I'm realizing my mistake. I tried to use the print function all by itself, outside of the setup function. Coming from Java Processing, I expected this to work, and the reference examples for print don't include a setup or draw function.

I realize my case is probably a bit unusual, but it might be worth updating the documentation?

alexdmiller avatar Feb 08 '20 03:02 alexdmiller

I don't think this is something we can specifically document just for print() as most functions in p5.js cannot be used outside of setup() or draw() before setup() or draw() is called. However, this behaviour should be caught by the friendly error system, not sure if it would be impossible to catch print() though.

limzykenneth avatar Feb 09 '20 14:02 limzykenneth

@limzykenneth Can I work on this issue?

debajitdeb11 avatar Feb 24 '20 06:02 debajitdeb11

@debajitdeb11 Sure, do have a look at it. I'm not sure how would the FES detect print("something") is being used before initialization though as unlike the other functions, print() exist on the global scope. Let us know what you find, thanks!

limzykenneth avatar Feb 24 '20 10:02 limzykenneth

Where is the source code for the online editor is located in the source file? editor

debajitdeb11 avatar Feb 25 '20 14:02 debajitdeb11

The source code for the web editor is located in another repo but why do you need the source code for it for this issue?

limzykenneth avatar Feb 25 '20 14:02 limzykenneth

i think this is a great place for FES. if someone is interested in working on it iā€™m also happy to answer questions, code review, whatever!

outofambit avatar Feb 28 '20 20:02 outofambit

@debajitdeb11 if you are still working on this maybe window.onbeforeprint can help you? I am just guessing here but maybe using something like a check for _setupDone or similar inside it to call report() to trigger a friendly warning message?

akshay-99 avatar Feb 29 '20 15:02 akshay-99

@akshay-99 the thing with calling print(...args) outside setup or draw is that it gets called before the library is loaded and browser calls window.print() . So I think it's hard for FES to detect it. A better way to go around situation will be to have a static function p5.print() alongside this one.

p5.print('Hello World'); // logs Hello World into console.
print('Hello'); // opens print dialog box
function setup() {
  // put setup code here
}

function draw() {
  // put drawing code here
}

@outofambit what do you suggest about this? If there is way for it to be get detected by FES, I would like to work on it.

DivyamAhuja avatar Mar 10 '20 09:03 DivyamAhuja

@DivyamAhuja I am sorry I didn't reply earlier. I must have missed this comment somehow. When we use global mode, all of p5's API functions get attached to the window object when p5 is initialised.

Also you are right that the call is made before the library initialises. And hence my mention of_setupDone was wrong. But we can still use window.onbeforeprint :smile: The FES has helpForMisusedAtTopLevelCode which currently handles many cases similar to this issue. helpForMisusedAtTopLevelCode is built such that it can work even before p5 is initialised. The reason it does not handle print() is due to the fact that print is already there in the window object and hence calling it does not produce an error. But what if just before this line, we add this

window.onbeforeprint = () => {
    helpForMisusedAtTopLevelCode(new ErrorEvent('print', {message:'print used'}));
}

The effect of this now is that if a print() is called outside setup, onbeforeprint triggers and calls helpForMisusedAtTopLevelCode, passing to it a new ErrorEvent. The contents of this can be anything since it won't be put on the console. We just need to make sure that the message field has "print" somewhere in it so that the regex here can match it

akshay-99 avatar Mar 26 '20 22:03 akshay-99

It is interesting to note that there is another way to handle this, one that is not just limited to print but can work for anything else in the window object that may conflict with p5

We can simply redefine the function in the window object to make it pass through the FES before it executes its original task. Lets assume we have a function something that is both defined in p5 and the window object. We can catch the use of something outside of setup and draw in the following way

let somethingBackup = window.something;
window.something = (params) => {
    helpForMisusedAtTopLevelCode(new ErrorEvent('something', {message:'something used'}));
   somethingBackup(params);
}

akshay-99 avatar Mar 26 '20 22:03 akshay-99

@debajitdeb11 @DivyamAhuja is anyone working on this?

akshay-99 avatar Mar 30 '20 11:03 akshay-99

@akshay-99 No, am not working on it. You can continue working on it if you want.

DivyamAhuja avatar Mar 30 '20 11:03 DivyamAhuja

BTW calling print(); with no parameters invokes the browsers print dialog. Which is really bad when using an online IDE like https://jsitor.com/ with auto run on and you type print() before entering what to print in the draw loop.

Having a command to override the system print would be great, NoPrintDialog();

Could the sandbox flags be used to disable the window.print()? https://html.spec.whatwg.org/multipage/origin.html#sandbox-propagates-to-auxiliary-browsing-contexts-flag

Or could we just hijack window.print() https://stackoverflow.com/questions/32181838/override-window-print-for-all-windows-using-window-prototype

hellonearthis avatar Mar 30 '20 13:03 hellonearthis

I think overriding default print function with this should work.

const _windowPrint = window.print;

window.print = function(...args){
  if(args.length === 0){
    _windowPrint();
  }
  else{
    console.log(...args);
  }
}

current implementation adds print function to p5 class while overriding window.print will be helpful I think. https://editor.p5js.org/DivyamAhuja/sketches/6zIHhzpg0

DivyamAhuja avatar Mar 30 '20 14:03 DivyamAhuja

@DivyamAhuja ah that's interesting. I was talking about overriding it for catching its use for outside setup and draw to warn the user. But your idea of removing p5.prototype.print and overriding window directly is simpler.

One question I have in mind is instance mode, as this would leak p5's functionality to the global object even in instance mode. So hypothetically if the user is also using some other script that also overrides print, and using p5 in instance mode to avoid any clashes, this print functionality would still clash. Which means it would depend on the order of the import which script's print is used. But this is a very unlikely situation indeed.

@hellonearthis yeah I guess a command or a parameter which when called or set true, would map print to console.log even when called with 0 parameters would help in that case.

akshay-99 avatar Mar 30 '20 15:03 akshay-99

@akshay-99 Yeah, I didn't think of a case with multiple libraries. In this case overriding may really be flawed

DivyamAhuja avatar Mar 30 '20 16:03 DivyamAhuja

I have had this print() problem when used inside a draw() loop.

p5 could treat print() as console.log('') to would prevent the browser print() to not popup but there might also be a case to use print() so made add a printerMode(CONSOLE|PRINTER) to let the user enable the printer as the default could be console.

Overriding outside of the p5 scope is problematic unless it could be address like p5.print('hi'); but not sure on that point.

hellonearthis avatar Apr 19 '20 12:04 hellonearthis

This simple sketch is very easy for a novice user write. In auto-refresh mode get into loop with print dialog repeating opening. Must kill browser window/tab to stop.

I recommend print with no args call console.log.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);
  print();
}

jht1493 avatar Apr 01 '21 02:04 jht1493

Thank you all for working on this. I'd like to bump up this issue for the upcoming 1.7.0 release with another print() related issue #2765. Since the issue was filed a while ago, what will be the good next steps to move this issue forward? @limzykenneth @davepagurek. Also adding GSoC FES contributor @Ayush23Dash and mentors @almchung @nbriz to this discussion.

Qianqianye avatar Jul 01 '23 01:07 Qianqianye

With the suggested beforeprint event it is possible to catch print being called outside of setup and draw to print a FES warning, this possibly can be implemented in helpForMisusedAtTopLevelCode as a special case. It won't stop the print dialog from showing, nor should it really for instances of it being used outside of setup and draw. @Ayush23Dash if you need help with this do let us know.

For the more general case for print() with no arguments opening print dialogs when used in draw() we can focus discussions on #2765. I have a couple vague ideas how this may be solved but have not yet tried it out but if there's idea for solutions that can preserve both print("something") and print() behaviours, do leave a comment in #2765.

limzykenneth avatar Jul 01 '23 19:07 limzykenneth