javascript automation click download button in iTunes

非 Y 不嫁゛ 提交于 2021-02-07 10:31:28

问题


I need to programatically download an app from iTunes using JXA. I've done the following:

var its = SystemEvents.processes.byName('iTunes');
delay(3);
its.windows[0].buttons.byName('Get').click();

There is no element selected. I've tried clicking on buttons[0...7] and none of those are the 'Get' button. I assume the button I need is inside a document, biut the JXA documentation clearly states that button elements are children of Window, not of Document. Any ideas on how to click on the corrent button?


回答1:


A "leaf" UI element such as a button will be at the bottom of a potentially complex hierarchy of UI elements, which is especially true in the case of iTunes.

To give you a sense, here's an example object specifier for the Get button on a free app's App Store page (assuming you've already ensured that this page is active):

Application("System Events")
  .applicationProcesses.byName("iTunes")
    .windows.byName("iTunes")
      .splitterGroups.at(0)
        .scrollAreas.at(0)
          .uiElements.at(0)
            .groups.at(3)
              .buttons.at(0)

The problem is that this object specifier differs across pages, so ideally you'd just apply a filter to all UI elements (via the window's entireContents property) to retrieve the button of interest:

// Get an array of all UI elements in iTunes window.
uiElems = Application("System Events").applicationProcesses['iTunes']
           .windows[0].entireContents()

// Find all buttons whose description contains 'Get'.
btns = uiElems.filter(function(el) { 
  try {
    return el.role() == 'AXButton' 
           &&
           el.description().match(/\bGet\b/)
  } catch (e) {}
})

// Click on the 1st button found.
btns[0].click()

Here's the catch: on my reasonably recent machine, this takes about 20 seconds(!).

I would image that a .whose-style filter would be faster, but I couldn't get it to work in this instance, because exceptions must be caught - as above - but .whose does not seem to support embedded exception handlers.

If you're willing to make assumptions about a lower level in the hierarchy in whose subtree the button can be found, you can speed things up considerably:

// Get the group UI elements in one of which the 'Get' button is located.
grps = Application("System Events").applicationProcesses['iTunes'].
        windows[0].splitterGroups[0].scrollAreas[0].uiElements[0].groups

// Loop over groups
count = grps.length
for (i = 0; i < count; ++i) {
  // In the group at hand, find all buttons whose description contains 'Get'.
  btns = grps[i].entireContents().filter(function(el) { 
    try {
      return el.role() == 'AXButton' 
             &&
             el.description().match(/\bGet\b/)
    } catch (e) {}
  })
  // Exit loop, if a 'Get' button was found.
  if (btns.length > 0) break  
}

if (btns.length == 0) {
  console.log('ERROR: No "Get" button found.')
} else {  
  // Click on the 1st button found.
  btns[0].click()
}

This runs in less than 1 sec. on my machine.


UI automation (GUI scripting) is tricky business, unfortunately.

For interactive exploration, there's the Accessibility Inspector developer tool that comes with Xcode, but using it is non-trivial, especially when it comes to translating findings into code.



来源:https://stackoverflow.com/questions/33232154/javascript-automation-click-download-button-in-itunes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!