HOME > AppleScript > Safari 用スクロール座標付きしおり


--Mac OS X 10.4.8 (PPC)、Safari 2.0.4 で動作確認。
--ウインドウのスクロール位置 (X 座標、Y 座標) と URL を property として保持し、好きなときに呼び出す。

property theList : {}
property scriptName : "スクロール座標付きしおり"
property showListText : "しおりを呼び出す"
property getOffsetText : "しおりを作成する"
property deleteBookmarkText : "しおりを削除する"
property okText : "OK"
property backText : "戻る"
property cancelText : "キャンセル"

on run
startScript()
end run

on startScript()
tell application "Safari"
activate
if (exists window 1) then
set frontWindowID to (id of window 1)
else
set frontWindowID to null
end if
try
set getSelection to (do JavaScript "getSelection()+''" in document 1) as Unicode text
--実行時にテキストが選択されていると、先頭から 20 文字がしおりのタイトル候補になる。(フレームのページは無理)
if getSelection is "" then
set cutSelection to "no title"
else if (number of characters of getSelection) > 20 then
set cutSelection to ""
repeat with i from 1 to 20
set cutSelection to cutSelection & ((character i of getSelection) as Unicode text)
end repeat
else
set cutSelection to getSelection
end if
on error
set cutSelection to "no title"
--document 1 が存在しない場合など。
end try
try
set chosenOne to firstChoose() of me
if chosenOne is false then
return
else if (chosenOne as string) is getOffsetText then
getOffset(frontWindowID, cutSelection) of me
if result is false then
return
else if result is backText then
startScript() of me
end if
else if (chosenOne as string) is showListText then
showList(frontWindowID) of me
if result is false then
return
else if result is backText then
startScript() of me
end if
else if (chosenOne as string) is deleteBookmarkText then
deleteBookmark() of me
if result is false then
return
else if result is backText then
startScript() of me
end if
end if
on error errMsg
display dialog errMsg buttons {okText} default button 1
end try
end tell
end startScript

on firstChoose()
tell application "Safari"
if (exists document 1) and (theList is not {}) then
choose from list {showListText, getOffsetText, deleteBookmarkText} with prompt scriptName default items showListText
else if (exists document 1) and (theList is {}) then
choose from list {getOffsetText} with prompt scriptName default items getOffsetText
else if ((exists document 1) is false) and (theList is {}) then
try
display dialog "・しおりがありません。" & return & "・しおりを作成できるページが開かれていません。" buttons {cancelText} default button 1 giving up after 5
if gave up of result then error
on error
set askResult to false
end try
return askResult
else if ((exists document 1) is false) and (theList is not {}) then
choose from list {showListText, deleteBookmarkText} with prompt scriptName default items showListText
end if
end tell
end firstChoose

on getOffset(frontWindowID, cutSelection)
tell application "Safari"
if number of items of theList is not less than 30 then
--しおりは 30 件まで保存。'30' を書き換えれば変更可能。
set theList to (items 1 thru -2 of theList)
end if

try
set curXOffset to (do JavaScript "window.pageXOffset" in document 1) as Unicode text
set curYOffset to (do JavaScript "window.pageYOffset" in document 1) as Unicode text
set curTitle to (name of document 1) as Unicode text
set curURL to (URL of document 1) as Unicode text
if curURL starts with "file" then
set curDomain to "file" as Unicode text
else
set curDomain to (do shell script "echo " & quoted form of curURL & " | sed 's/.*:\\/\\///;s/\\/.*//'") as Unicode text
end if
try
set theResult to (display dialog "しおりにタイトルを" & return & "付けたり付けなかったりしてください (目印程度に)。" default answer cutSelection buttons {backText, okText} default button 2 cancel button 1 giving up after 60)
on error
return backText
end try
if (gave up of theResult) or (text returned of theResult is "") then
set bookmarkName to "no title" as Unicode text
else
set bookmarkName to (text returned of theResult) as Unicode text
end if
if (frontWindowID is not null) then activateFrontWindow(frontWindowID) of me
set curList to {curXOffset, curYOffset, curTitle, curURL, curDomain, bookmarkName}
on error
return failedToGetMessage(frontWindowID) of me
end try

if (curXOffset is "") or (curYOffset is "") or (curURL is "") then
return failedToGetMessage(frontWindowID) of me
else
set the beginning of theList to curList
end if
end tell
end getOffset

on showList(frontWindowID)
tell application "Safari"
set visibleList to makeVisibleList() of me
set showListResult to (choose from list visibleList with prompt "しおりを選択して下さい。" default items (item 1 of visibleList) cancel button name backText)
if showListResult is not false then
set listIndex to (character 1 of (item 1 of showListResult)) as integer
set xoffset to (item 1 of (item listIndex of theList))
set yoffset to (item 2 of (item listIndex of theList))
set theURL to (item 4 of (item listIndex of theList))
try
set urlBool to (theURL is (URL of document 1))
on error
set urlBool to false
--ページのソース (= document 扱い) が前面にある場合、"URL of document 1' はエラーになる。
end try
if (exists document 1) and (urlBool is true) then
do JavaScript "window.scrollTo(" & xoffset & "," & yoffset & ")" in document 1
permuteList(listIndex) of me
else
open location theURL
delay 1
with timeout of 120 seconds
if not my readyStateComplete(90) then
display dialog "ページの読み込み完了を確認できませんでした。" & return & "スクリプトを中断します。" buttons {okText} default button 1
if (frontWindowID is not null) then activateFrontWindow(frontWindowID) of me
return false
end if
end timeout
do JavaScript "window.scrollTo(" & xoffset & "," & yoffset & ")" in document 1
permuteList(listIndex) of me
end if
else
return backText
end if
end tell
end showList

on activateFrontWindow(frontWindowID)
--display dialog の後にボタンを押すとウインドウの順番が入れ替わってしまう問題への対策。
--document が存在するときだけ実行するようにしないと SafariStand などの隠れたウインドウが出てきてしまう。
tell application "Safari"
if (exists window 1) and (exists document 1) then
set index of (window id frontWindowID) to 1
end if
end tell
end activateFrontWindow

on readyStateComplete(timeoutValue)
--読み込み完了まで次の処理を待つ
--http://www.apple.com/applescript/safari/jscript.01.html
with timeout of 120 seconds
delay 2
repeat with i from 1 to the timeoutValue
tell application "Safari"
if (do JavaScript "document.readyState" in document 1) is "complete" then
return true
else if i = timeoutValue then
return false
else
delay 1
end if
end tell
end repeat
return false
end timeout
end readyStateComplete

on failedToGetMessage(frontWindowID)
tell application "Safari"
try
display dialog "しおりを作成できませんでした。" buttons {cancelText} default button 1 giving up after 5
if gave up of result then error
on error
if (frontWindowID is not null) then activateFrontWindow(frontWindowID) of me
return false
end try
end tell
end failedToGetMessage

on permuteList(num)
--最後に開いたしおりをリストのトップに並び替える。
--http://www.tonbi.jp/AppleScript/tips/List/AddDelete.html
set theItem to (item num of theList)
set (item num of theList) to 0 as integer
set theList to (every list of theList)
set the beginning of theList to theItem
end permuteList

on deleteBookmark()
--しおりを削除する
tell application "Safari"
set visibleList to makeVisibleList() of me
set showListResult to (choose from list visibleList with prompt "削除したいしおりを選択して下さい (複数選択可)。" default items (item 1 of visibleList) cancel button name backText with multiple selections allowed)
end tell
if showListResult is not false then
set indexList to {}
repeat with curItem in showListResult
set the end of indexList to ((character 1 of curItem) as integer)
end repeat
repeat with j in indexList
set item j of theList to 0 as integer
end repeat
set theList to (every list of theList)
else
return backText
end if
end deleteBookmark

on makeVisibleList()
--choose from list で表示するためのリスト
set visibleList to {}
repeat with i from 1 to (number of every item of theList)
set the end of visibleList to ((i as Unicode text) & ". " & (item 6 of (item i of theList)) & ": " & (item 3 of (item i of theList)) & " [" & (item 5 of (item i of theList)) & "]{" & (item 1 of (item i of theList)) & "," & (item 2 of (item i of theList)) & "}")
end repeat
return visibleList
end makeVisibleList

--pageXOffset, pageYOffset の値を保存するだけなので、日々更新されるサイトや掲示板などには向かない。フレームを使ったサイトも無理。
--画像を直接開いている場合、do JavaScript を実行すると画像が消えてしまう。

HOME > AppleScript > Safari 用スクロール座標付きしおり

TOP

created: 2007-03-06T23:37:36+09:00
last modified: 2007-03-06T23:37:36+09:00
author: AquaBowler