1

I am writing a script to print a section of a bookdown online book as PDF, then move to the next section, and so on.

The print part works (the key codes are from this page):

tell application "Safari"
activate

tell application "System Events"
    key code 35 using command down -- activate print menu item
end tell

delay 0.5

set i to 0
repeat while i < 15
    set i to i + 1
    delay 0.1
    tell application "System Events"
        key code 48 -- press tab 15 times
    end tell
end repeat

tell application "System Events"
    key code 49 -- press space
end tell

set i to 0
repeat while i < 2
    set i to i + 1
    delay 0.1
    tell application "System Events"
        key code 125 -- press down key twice
    end tell
end repeat

tell application "System Events"
    key code 36 -- enter
end tell

set i to 0
repeat while i < 16
    set i to i + 1
    delay 0.1
    tell application "System Events"
        key code 125 -- press tab to get to "save"
    end tell
end repeat

tell application "System Events"
    key code 36 -- enter to cleck on save
end tell

end tell

Problem

Now that I have printed the current section and I am back on Safari, I can click manually on the right arrow and move to the next section, but I can't manage to have the script to do that.

I have tried to add the following to the script above:

tell application "System Events"
        key code 124 -- right arrow to enter the next page
    end tell

Or even to "reopen" Safari, but nothing happens.

tell application "Safari"
activate

tell application "System Events"
    key code 124 -- right arrow to move to the next section
end tell

end tell

How can I have AppleScript "turn the page" and move to the next section?

Also, I welcome suggestions to improve the script! I wonder if it would be easy to avoid repeating "tab" 15 times. I have looked at the Accessibility Inspector and found that "PDF" in the print menu corresponds to NSPopUpButtonCell. I have tried to use select NSPopUpButtonCell of its sheet but it did not work.

Emy
  • 141

1 Answers1

1

I can click manually on the right arrow and move to the next section, but I can't manage to have the script to do that.

How can I have AppleScript "turn the page" and move to the next section?

If you are trying to programmatically click the right-arrow, as shown in the image below, then the following example AppleScript code can do that:

tell application "Safari" to ¬
    tell document 1 to ¬
        do JavaScript ¬
            "document.getElementsByClassName('fa fa-angle-right')[0].click();"

Notes:

This requires Allow JavaScript from Apple Events to be check on the hidden Develop menu.

To unhide the hidden Develop menu:

  • Safari > Preferences… > Advanced > [√] Show Develop menu in menu bar

enter image description here


Update to address:

Also, I welcome suggestions to improve the script! I wonder if it would be easy to avoid repeating "tab" 15 times.

Here is how I'd use the JavaScript from above and coded to avoid using the key code and or keystroke System Events commands, especially tabbing around the UI.

Example AppleScript code:

tell application "System Events"
tell application process "Safari"

    set frontmost to true

    set i to 0
    repeat until (its frontmost = true)
        delay 0.1
        set i to i + 1
        if i ≥ 20 then return
    end repeat

    click menu item "Print…" of ¬
        menu 1 of ¬
        menu bar item "File" of ¬
        menu bar 1

    tell its front window

        set i to 0
        repeat until (exists menu button "PDF" of sheet 1)
            delay 0.1
            set i to i + 1
            if i ≥ 20 then return
        end repeat

        click menu button "PDF" of sheet 1

        set i to 0
        repeat until (exists menu item "Save as PDF" of ¬
            menu 1 of menu button "PDF" of sheet 1)
            delay 0.1
            set i to i + 1
            if i ≥ 20 then return
        end repeat

        click menu item "Save as PDF" of ¬
            menu 1 of ¬
            menu button "PDF" of ¬
            sheet 1

        set i to 0
        repeat until (exists button "Save" of sheet 1 of sheet 1)
            delay 0.1
            set i to i + 1
            if i ≥ 20 then return
        end repeat

        click button "Save" of sheet 1 of sheet 1

        set i to 0
        repeat while (exists sheet 1)
            delay 0.1
            set i to i + 1
            if i ≥ 100 then return
        end repeat

    end tell    
end tell

end tell

tell application "Safari" to ¬ tell document 1 to ¬ do JavaScript ¬ "document.getElementsByClassName('fa fa-angle-right')[0].click();"


Notes:

Since this type of AppleScript script is using UI Scripting, I have included an error handling in the form of a repeat loop to wait up to two seconds for the target UI element to become available to be acted upon for most of the targets, however the last repeat loop waits longer because it has to wait until the Save as PDF to complete. A simple delay command with an appropriate value could be used instead, but with the include delay of a tenth of a second in the repeat loops it shouldn't have to wait any longer than need be. In other words, I'd only use simple delay command if I want to slow the script down from going through the various events of the UI. It's doubtful that it would need to be adjusted, but obviously do so as/if necessary.

If the timeout is reached, the script aborts at that point without any error message. The single-line if i ≥ 20 then return statements can be turned into a full if block and include an error message via the display dialog, display alert, or display notification command as wanted.

user3439894
  • 58,676
  • It works, thanks a lot! But why you don't need end tell at the end? – Emy Apr 20 '21 at 16:54
  • 1
    RE: "But why you don't need end tell at the end?" -- Because it was not written in the form of a tell block statement but as a single-line. tell statement. Note that the ¬ character is a line continuation character and is used for readability (especially when posting code here). – user3439894 Apr 20 '21 at 17:03
  • 1
    @Emy, Please see the Update to address: section of my updated answer, as it address the first sentence of the last paragraph of your OP. – user3439894 Apr 20 '21 at 21:00
  • Thank you, I appreciate your help! – Emy Apr 20 '21 at 21:29
  • 1
    @Emy, I changed the last repeat loop as it originally targeted the wrong UI element. It's now coded to give time for the Save to PDF to complete, as I noticed some of the chapters are quite long and could have been truncated. Sorry! – user3439894 Apr 21 '21 at 14:16
  • Thank you again. I ran into another issue actually but I don't want to take too much of your time and maybe it could be the object of another post. When downloading a book like this one: https://bookdown.org/roy_schumacher/r4ds/ , all the chapters have the same name and the loop gets stuck because of the rewrite. If the chapter have the same name one could just add anumber to the name of the saved file. But again let me know if this should be a different question. – Emy Apr 22 '21 at 11:11
  • @Emy, Just an FYI... This would be so much easier to just use wget to download the entire book as HTML and its assets and then be able to read the whole thing as a local copy in your web browser. For example, with the book of this question the only thing I had to change after downloading it with wget was the name of one file, i.e., fontawesome-webfont.ttf?v=4.1.0 in '../bookdown.org/yih_huynh/Guide-to-R-Book/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf?v=4.1.0' to fontawesome-webfont.ttf in order to show the icons across the top and the L/R arrows properly. – user3439894 Apr 22 '21 at 18:26
  • Notes: wget is not a native macOS command line utility, however, if you use Homebrew it can be installed with it. For testing I just did it in a Linux virtual machine. The command I used was: wget --recursive --no-clobber --page-requisites --convert-links --wait=10 --limit-rate=20K --domains bookdown.org --no-parent https://bookdown.org/yih_huynh/Guide-to-R-Book/ The --wait and --limit-rate options were set so it wouldn't suck the whole thing down to quickly and get cutoff and blacklisted. The book has 198 items, totaling 19.9 MB and took ~30 min. to download. – user3439894 Apr 22 '21 at 18:26
  • It also did it in the background and allowed me to do other things. I'd highly recommend going this route unless you really want it saved in PDF documents. The book linked in your comment is larger than the one of this question so it will take longer to download. – user3439894 Apr 22 '21 at 18:26
  • Thank you for your explanation, it's useful to know. In this cases though, I actually really wanted a PDF because then I can read on a tablet, annotate, and then import to a spaced repetition software. – Emy Apr 22 '21 at 19:19
  • 1
    @Emy, Okay, I'll look at how the filename can be programmatically handled to avoid being a duplicate in a automated manner and get back to you. BTW do you use Homebrew? – user3439894 Apr 22 '21 at 19:23
  • 1
  • Yes, I have used Homebrew in the past. – Emy Apr 22 '21 at 23:32
  • Thank you @user3439894! It works like a charm. I appreciate your help. – Emy Apr 22 '21 at 23:33