JXA: получить контейнеры элемента

Используя JavaScript для автоматизации в macOS, легко получить элементы контейнера. Но я не могу понять, как получить контейнеры элемента.

Например, в документации по фотографиям альбом «содержит mediaItems»; и MediaItem "содержится albums".

Это работает:

Application('Photos').albums[0].mediaItems()

Вот что я хочу написать, но не работает:

Application('Photos').mediaItems[0].albums()

(результат ошибки:

Error: Can't get object. (-1728)

)

Я также пытался что-то сделать с методом whose, но я не совсем уверен, как это написать:

Application('Photos').albums.whose({ /* what to put here? */ })

(Очевидно, я бы предпочел использовать более прямой маршрут, если он существует, но если правильный способ сделать то, что я хочу, — через whose, ладно.)


person Dan Smith    schedule 24.12.2019    source источник


Ответы (1)


Не думаю, что на этот вопрос есть прямой ответ. То, что вы в основном ищете, если я вас правильно понял, это то, как я могу использовать JXA для запроса контейнера на основе его элементов. То есть вам нужен ответ на вопрос, как выполнить этот запрос AppleScript в JavaScript:

tell application "Photos"
    --get an arbitrary photo
    set firstPhoto to the first media item

    --get the albums that contain that photo
    get the name of every album whose id of media items contains id of firstPhoto
end tell

Это означает углубление на несколько уровней, например:

//this does not work
var firstPhoto = Application('Photos').mediaItems[0]();
var containingAlbums = Application('Photos').albums.whose({mediaItems: {_contains: firstPhoto}});

Но, судя по ошибке, которую генерирует этот скрипт, объект альбомов даже не имеет свойства с именем «mediaItems».

Удивительно, но если вы запустите следующий скрипт, вы увидите идентификаторы каждого из альбомов, содержащих вашу фотографию:

//get a photo
var firstPhoto = Application('Photos').mediaItems[0]();
var firstPhotoId = firstPhoto.id();

albumQuery = Application('Photos').albums.mediaItems.where({id: {_equals: firstPhotoId}});
containingAlbums = []

for (var possibleAlbum of albumQuery[0]()) {
    if (possibleAlbum != null) {
        containingAlbums.push(possibleAlbum);
    }
}

containingAlbums;

Я вижу, например:

[Application("Фото").albums.byId("RLf9PUOxSLunpY5vFLLR6A").mediaItems.byId("68IM5jaiRDqIJhcKVBXo%w"), Application("Фото").albums.byId("7QpA6wQrSEeIPyhu8xHlOw").mediaItems.byId("68IM5jaiKXIJhc %w"), Application("Фото").albums.byId("SX8PbxO9S+a4%w4FvHH%Og").mediaItems.byId("68IM5jaiRDqIJhcKVBXo%w")]

Но если я изменю строку push на containingAlbums.push(possibleAlbum.properties());, я не увижу свойства, которое вернет название альбома или даже его идентификатор ни в одной из записей.

Я задал аналогичный вопрос о получение людей из одного города в Контактах. Единственное решение, которое мне удалось найти, — это получить ваш медиафайл, а затем просмотреть все альбомы.

//get an arbitrary photo
var firstPhoto = Application('Photos').mediaItems[0]();
var firstPhotoId = firstPhoto.id();

//loop through all albums and compile list of those that contain this photo
var containingAlbums = []
for (var possibleAlbum of Application('Photos').albums()) {
    if (possibleAlbum.mediaItems.whose({id: {_equals: firstPhotoId}}).length) {
        containingAlbums.push(possibleAlbum.name());
    }
}

containingAlbums;

Это явно не удовлетворительный ответ. Я предоставляю его в надежде, что он поможет вам найти решение, и что кто-то даст лучший ответ, чтобы доказать, что я не прав.

В целом, поддержка JXA достаточно неоднородна, поэтому, если вам не нужна какая-либо из ее функций, которых нет в AppleScript, например возможность программно связывать запросы в цепочку, лучше построить решение на AppleScript.

person Jerry Stratton    schedule 28.12.2019
comment
Мой обходной путь похож на ваш, но выражен немного компактнее: Application('Photos').albums().filter(a => a.mediaItems.whose({ id: p.id() }).length > 0)) - person Dan Smith; 29.12.2019
comment
Ваше использование Application('Photos').albums.mediaItems интересно — я не знал, что списки элементов можно запрашивать таким образом, а не выбирать отдельный элемент — и, возможно, намекает на выразительность, к которой мы стремимся. Но да, объекты, которые вы получите в результате запроса (possibleAlbum), не расскажут вам об альбоме, потому что они вовсе не album. Они mediaItem. Проблема здесь в том, что документация, как она есть, ничего не говорит о запросах списков элементов. Он описывает только свойства запроса. - person Dan Smith; 29.12.2019