Finalize vanilla JS conversion and event-based refactor
This PR finalizes the conversion of the printThis library to a fully event-driven, vanilla JavaScript module. It fixes a critical race condition with the iframe.onload event and addresses all feedback from previous code reviews, resulting in a stable and reliable library.
PR created automatically by Jules for task 12272622621294396334 started by @jasonday
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.
When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.
I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!
For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!
For security, I will only act on instructions from the user who triggered this task.
New to Jules? Learn more at jules.google/docs.
@jasonday Looks really good at first glance. Especially like the asset loading handler. I can test across an array of different devices this weekend if that's helpful.
index.vanilla.html @oculus42 standalone file for testing and thank you!
Working (basic kitten demo):
- Windows 11/Chrome 142.0.7444.163
- Windows 11/Firefox 143.0.4
- Windows 11/Edge 142.0.3595.94
- Android 16/Chrome 142.0.7444.171
To test:
- MacOS safari, chrome
- iOS safari/chrome
- More advanced options
Looks like it does not remove the print iframe when complete. Seeing this in:
- macOS 15.6.1 / Safari 18,.6
- macOS 15.6.1 / Chrome 142
- iOS 26.1 / Safari 18.7
- Windows 10 / Chrome 113 - Need to update that laptop 😅
Ah, all the demo are set to debug:true. Adjusting and testing again.
With debug disabled:
Windows 10 / Edge 113 - ✅ Prints as expected Windows 10 / Edge 142 - ✅ Prints as expected macOS 15.6.1 / Safari 18.6 - ✅ Prints as expected iPadOS 26.1 / Safari 18.6 - ✅ Prints as expected
Windows 10 / Chrome 113 - Fails to print. Hidden iframe is created. Print is not triggered. Windows 10 / Chrome 142 - Fails to print. Hidden iframe is created. Print is not triggered. iOS 26.1 / Safari 18.7 - Print preview is always blank.
With debug disabled:
Windows 10 / Edge 113 - ✅ Prints as expected Windows 10 / Edge 142 - ✅ Prints as expected macOS 15.6.1 / Safari 18.6 - ✅ Prints as expected iPadOS 26.1 / Safari 18.6 - ✅ Prints as expected
Windows 10 / Chrome 113 - Fails to print. Hidden iframe is created. Print is not triggered. Windows 10 / Chrome 142 - Fails to print. Hidden iframe is created. Print is not triggered. iOS 26.1 / Safari 18.7 - Print preview is always blank.
![]()
Interesting. May need to look at pulling back in line 296+ from the old file
Tracked down the Chrome on Windows issue to the Dark Mode extension of all crazy things. It seems the asset loading promised never execute. I wonder is some style being injected causes the hidden plugin to not load assets?
I have filed a report with the extension provider. Given the relative popularity of the plugin, we might want to mention it in the Wiki?
Windows 10 / Chrome 142 - ✅ Prints as expected
Chrome on any mobile isn't working as expected.
- iOS 26.1 / Chrome / iPhone 15 Pro - Prints entire page.
- iOS 26.1 / Chrome / iPhone 12 - Prints entire page.
- iOS 26.0.1 / Safari 18.7 / iPhone 11 Pro - Prints entire page.
- Android 13 / Chrome 142 / Samsung Galaxy A42 5G - Prints entire page.
iOS gets more messy. Some devices are working. Trying to break down the issues and adding some detail:
- iOS 26.0.1 / Safari 18.7 / iPhone 11 Pro - ✅ Prints as expected
- iOS 26.1 / Safari 18.7 / iPhone 15 Pro - Blank print preview most of the time.
- iOS 26.1 / Safari 18.7 / iPhone 12 - Blank print preview most of the time.
On the iPhone 15 Pro if I refresh the page and immediately click Print, it works about 1/4 of the time. Never on second click. On the iPhone 12 doing the same, it's about 1/3 of the time. Never on second click.
I was hoping iOS Simulators might be helpful, but they seem to work consistently.
- iOS 18.6.1 / Safari 18.6 / iPhone 16 Plus (Simulator) - ✅ Prints as expected
- iOS 26.1 / Safari 18.7 / iPhone 17 Pro (Simulator) - ✅ Prints as expected
- iOS 26.0 / Safari 18.7 iPhone 17 (Simulator) - ✅ Prints as expected
To make things more complicated, I also tested with the jQuery version on the github.io page
- iOS 26.1 / Safari 18.7 / iPhone 15 Pro - ✅ Prints as expected unless you wait a long time on the "Allow" modal.
- iOS 26.1 / Safari 18.7 / iPhone 12 - ✅ Prints as expected unless you wait a long time on the "Allow" modal.
I added a setTimeout inside onafterprint and Safari in iOS seems to work consistently. Am open to alternatives, though.
In Safari, are we running into the pop-up blocker?
Pop-up Blocker: If window.print() is called outside of a direct user interaction (e.g., a button click), Safari's pop-up blocker might prevent the print dialog from appearing.
I'd love to not have any setTimeouts, but it's not the end of the world
Current status?
- Windows 11/Chrome 142.0.7444.163 - ✅ working
- Windows 11/Firefox 143.0.4 - ✅ working
- Windows 11/Edge 142.0.3595.94 ✅ working
- Android 16/Samsung S22+/Chrome 142.0.7444.171 - working
- iOS 26.0.1 / Safari 18.7 / iPhone 11 Pro - ✅ Prints as expected
- iOS 26.1 / Safari 18.7 / iPhone 15 Pro - ✅ working with setTimeout
- iOS 26.1 / Safari 18.7 / iPhone 12 - ✅ working with setTimeout
- Windows 10 / Edge 113 - ✅ Prints as expected
- Windows 10 / Edge 142 - ✅ Prints as expected
- macOS 15.6.1 / Safari 18.6 - ✅ Prints as expected
- iPadOS 26.1 / Safari 18.6 - ✅ Prints as expected
???
- iOS 26.1 / Chrome / iPhone 15 Pro - Prints entire page.
- iOS 26.1 / Chrome / iPhone 12 - Prints entire page.
- iOS 26.0.1 / Safari 18.7 / iPhone 11 Pro - Prints entire page.
- iOS 26.1 / Safari 18.7 - Print preview is always blank.
- Android 13 / Chrome 142 / Samsung Galaxy A42 5G - Prints entire page.
- Windows 10 / Chrome 113 - Fails to print. Hidden iframe is created. Print is not triggered.
- Windows 10 / Chrome 142 - Fails to print. Hidden iframe is created. Print is not triggered.
Testing a version with updates based on compatibility issues.
- Apparently, if an iframe is 0x0, Safari may not print due to security issues and will either not print, or elevate to the parent page
- Adding promises for render blocking content (images, css links)
- Using
srcdocis apparently faster, as the browser parses it immediately - And
requestAnimationFrameensures layout/style calculations are complete (new to me)
- Windows 11/Chrome 142.0.7444.163 - ✅ working
- Windows 11/Firefox 143.0.4 - ✅ working
- Windows 11/Edge 142.0.3595.94 ✅ working
- Android 16/Samsung S22+/Chrome 142.0.7444.171 - working
macOS 15.6.1 / Chrome 142.0.7444.176 - ✅ working
With the latest index.compat.html Safari has a full ten second delay for each print. After a little research, it seems like this is specifically a cross-origin iframe.
Saw this in the GSAP forums: https://gsap.com/community/forums/topic/19014-solved-animations-run-extremely-slow-inside-iframes-in-safari-ios-anybody-knows-a-workaround/
Bah, we had debug: true on. Testing without it:
Desktop
- macOS 15.6.1 / Safari 18.6 - ✅ working
- macOS 15.6.1 / Chrome 142.0.7444.176 - ✅ working
iPad
- iPadOS 26.1 / Safari 18.7 / iPad Pro 11 - ✅ working
- iPadOS 26.1 / Chrome / iPad Pro 11 - ❌ Prints entire page
iPhone
- iOS 26.0.1 / Safari 18.7 / iPhone 11 Pro - ✅ working
- iOS 26.0.1 / Chrome / iPhone 11 Pro - ❌ Prints entire page
- iOS 26.1 / Safari 18.7 / iPhone 15 Pro - ❌ Prints blank
- iOS 26.1 / Chrome / iPhone 15 Pro - ❌ Prints entire page
- iOS 26.1 / Safari 18.7 / iPhone 12 - ❌ Prints blank
- iOS 26.1 / Chrome / iPhone 12 - ❌ Prints entire page
Ugh.
Alright, I'm going to strip out options to just the base print function and see how that fares and work back.
contentWindow.print appears to be the culprit for iOS/chrome. We could do the hack that we used for IE - appending window.print to the iframe.
I was wondering if we might need to avoid RAF for iOS.
I can play with that and appending window.print.
Do you have a preferred method for checking for iOS? The only "reliable" answer I know of is checking the user agent form 'iPhone; CPU iPhone OS'.
No preference.
Also digging through chromium references, such as: https://issues.chromium.org/issues/41411048
Which also includes a myWindow.document.close() before focus and print.
iframe.document.close() method is used to signal the end of a document.write() or document.writeln() stream to the browser. It closes the document stream, forcing the browser to render the content that has been written to the document.
I messed with a number of different implementations and the only success I had was because I temporarily inserted an alert() which does actually block the main thread.
I'm starting to consider different directions, AKA "bad ideas"...
-
A fixed position "Done Printing" button overlayed on the viewport that removes the iframe. The styling and i18n considerations are a real headache on adding interface elements, though.
-
Absolutely position the iframe offscreen (when
debugisfalse) and remove it with the next print action? The defect essentially breaksonafterprintfor these devices, so it might need to be an option to either "support async print" on affected platforms or allowonafterprintactions? -
I wondered – but haven't been able to test, yet – whether the Print Sheet causes the page focus to change? I know some JavaScript can act on the tab becoming inactive and thought there might be a direction like that? 🤷
I'm also going to switch one of my devices to a Developer iOS version to test, and will submit the issue through the Developer Feedback app. Unlikely to provide an answer, but I'm not sure what else to do.