iPhone 「ショートカット」アプリで JavaScript を実行する

#はじめに
iPhone で Greasemonkey みたいに自分の作成した JavaScript のプログラムを起動できないかと方法を探していたら「ショートカット」アプリで似たような事はできそうだとわかりました。

**でも、できない事（たぶん・・・）**
・「ショートカット」アプリから直接 "Web ページで JavaScript を実行" のショートカットは実行できない。
　※この JavaScript を実行するタイプのショートカットは、サファリから選択して実行するんものなんですよ、きっと。
・ Greasemonkey のように、対象の URL と一致したら自動実行するような機能はない。

#インストール
App Store からインストールします。
![S__2719746.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/69e94f86-fc1c-1a83-9c21-4e5ef9d81392.jpeg)

#簡単なスクリプトを作成し実行してみる。

作成するスクリプトの内容としては、www.amazon.co.jp の検索フィールドに "alexa spot" と入力する事にします。

![S__2719748.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/fbab1302-f478-9cac-ae61-b7cb2f7aa21d.jpeg) = 検索より"Web" => ![S__2719749.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/f015a7ae-c300-9f95-80d0-25c96b2db3d6.jpeg)

Webページで JavaScript を選択
以下のように、簡単なサンプルがついてきています。

![S__2719750.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/bdf064fa-e963-31e7-d2b5-2db01dc884a0.jpeg)

これを以下の内容に変更します。
amazon.co.jp での nav-search-keywords の入力フィールドに "alexa spot" と値を入れる内容です。

```JavaScript
var result = [];
document.getElementById("nav-search-keywords").value = "alexa spot";
completion(result);
```
以上で、まずは簡単なショートカットができました。
しかし、これをタップして実行しても「ショートカット」アプリからは実行できません。
以下のようなエラーになります。
![S__2719751.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/15a87a17-74ad-401a-e613-8cd22ac53eba.jpeg)

## 実行前の事前準備

このショートカットはサファリで読み込むものだと思います、以下のように safari からショートカットが実行できるように設定を行います。

1. サファリより、画面下の四角に上矢印のマーク「共有メニュー」を選択します。
2. "その他"を選択します。
3. "ショートカット" を ON にします。
4. すると共有メニューに、”ショートカット”のアイコンが加わります。

![S__2719753.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/23dd8c04-9a94-0eca-a696-247dfd4bd0c6.jpeg) ＝＞　![S__2719754.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/5ab472e2-cf9e-f7b9-f742-215e1fbeae13.jpeg)

1. 「ショートカット」アプリからも作成した JavaScript (現時点では名称未設定ショートカット）を選び
2.  "共有シートに表示" を有効にしておきます。


![S__2719755.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/5bf74710-5db1-78ee-60c7-27e08ac97306.jpeg) 右上の横向きスイッチから => ![S__2719756.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/52276f49-b72e-d17f-b3e0-fafd9f96832e.jpeg)

#実行してみる。

1. サファリで http://www.amazon.co.jp を開き
2. 四角に上矢印のマーク「共有メニュー」を選択
3. ショートカットを選んで、作成した”名称未設定ショートカット”を選択
4. 一番最初は、アクセス許可するかの画面がでます。許可を選択
5. 作成しておいた JavaScript が実行され、検索文字として "alexa spot" がセットされていれば、動作 OK です。

![S__2719757.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/9b3b2693-877e-9d67-7acc-cbe9c8b55d49.jpeg) = 許可 =>![S__2719758.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/2d26bc5e-5c17-0e7a-b7e5-7fba13ae6f2d.jpeg)

#ゆうちょ銀行へのログイン

ここまで期待通りに動作できたので、サンプルとしてゆうちょ銀行へログインするためのスクリプトを作成してみます。
ゆうちょ銀行へのログインは、お客様番号が３つに分かれていたり合言葉があったりと手間がかかります。
また、子供の口座残高も確認したいなど複数口座がある場合など、手間に加えて記憶力も必要になってきます。

人それぞれ設定している合言葉などが違いますので、そのままでは動作しませんがサンプルとしてご覧ください
**ゆうちょ銀行へのログインのサンプル**

```JavaScript

var result = [];
// ゆうちょ銀行
if (document.URL == "https://direct.jp-bank.japanpost.jp/tp1web/U010101SCK.do")  {
  var tid1 = "1234";
  var tid2 = "2345";
  var tid3 = "34567";

  var aid1 = "1111";
  var aid2 = "2222";
  var aid3 = "33333";

  var btn1 = document.createElement( 'input' );
  btn1.addEventListener("click", login1 );
  with( btn1 ) {
    setAttribute( 'value', 'オレオレ' );
    setAttribute( 'type', 'button' );
    setAttribute( 'style', 'background-color: red; font-size:30px');
  }

  var btn2 = document.createElement( 'input' );
  btn2.addEventListener("click", login2 );
  with( btn2 ) {
    setAttribute( 'value', '子供の口座' );
    setAttribute( 'type', 'button' );
    setAttribute( 'style', 'background-color: red; font-size:30px');
  }

  // append at top of targetID
  document.getElementsByClassName("hdgL1Ba")[0].appendChild( btn1 );
  document.getElementsByClassName("hdgL1Ba")[0].appendChild( btn2 );

  function login1() {
    document.getElementsByName("okyakusamaBangou1")[0].value = tid1;
    document.getElementsByName("okyakusamaBangou2")[0].value = tid2;
    document.getElementsByName("okyakusamaBangou3")[0].value = tid3;
    document.getElementsByName("U010103")[0].click();
  }
  function login2() {
    document.getElementsByName("okyakusamaBangou1")[0].value = aid1;
    document.getElementsByName("okyakusamaBangou2")[0].value = aid2;
    document.getElementsByName("okyakusamaBangou3")[0].value = aid3;
    document.getElementsByName("U010103")[0].click();

  }
}

if ( document.URL.match( /.jp-bank.japanpost.jp\/tp1web\/pc\//) ) {

  var tpass = "オレオレパス";
  var apass = "コドモのパス";

  var btn1 = document.createElement( 'input' );
  btn1.addEventListener("click", login1 );
  with( btn1 ) {
    setAttribute( 'value', 'オレオレ' );
    setAttribute( 'type', 'button' );
    setAttribute( 'style', 'background-color: red; font-size:30px');
  }

  var btn2 = document.createElement( 'input' );
  btn2.addEventListener("click", login2 );
  with( btn2 ) {
    setAttribute( 'value', '子供の口座' );
    setAttribute( 'type', 'button' );
    setAttribute( 'style', 'background-color: red; font-size:30px');
  }

  var askStrings = document.getElementsByClassName("listTy02");
  for (var i = 0; i < askStrings.length; i++) {
    var aikotoba = askStrings[i].innerText;
  }

  if( askStrings.length > 0 ) {
    if ( aikotoba.indexOf("最も好きな都市はどこですか") > 0) {
      tpass = "すきな都市";
      apass = "スリランカ";
      // ボタンを追加
      document.getElementsByClassName("boxTy04")[0].appendChild( btn1 );
      document.getElementsByClassName("boxTy04")[0].appendChild( btn2 );
    }
    else if ( aikotoba.indexOf("結婚記念日はいつですか") > 0) {
      tpass = "おぼえてない";
      apass = "みらい";
      document.getElementsByClassName("boxTy04")[0].appendChild( btn1 );
      document.getElementsByClassName("boxTy04")[0].appendChild( btn2 );
     }
     else if ( aikotoba.indexOf("最も印象に残っている旅行先はどこですか") > 0) {
       tpass = "サムイ";
       apass = "バリ";
       document.getElementsByClassName("boxTy04")[0].appendChild( btn1 );
       document.getElementsByClassName("boxTy04")[0].appendChild( btn2 );
     }
     else if ( aikotoba.indexOf("母親の旧姓は何ですか") > 0) {
       tpass = "ママゴン";
       apass = "ママゴン";
       document.getElementsByClassName("boxTy04")[0].appendChild( btn1 );
       document.getElementsByClassName("boxTy04")[0].appendChild( btn2 );
     }
     else if ( aikotoba.indexOf("最も好きなデザート（スイーツ）は何ですか") > 0) {
       tpass = "プリン";
       apass = "コーヒーゼリー";
       document.getElementsByClassName("boxTy04")[0].appendChild( btn1 );
       document.getElementsByClassName("boxTy04")[0].appendChild( btn2 );
     }
     else if ( aikotoba.indexOf("最も好きな果物は何ですか") > 0) {
       tpass = "ドラゴン";
       apass = "ジャック";
       document.getElementsByClassName("boxTy04")[0].appendChild( btn1 );
       document.getElementsByClassName("boxTy04")[0].appendChild( btn2 );
     }
  }
  else {
    tpass = "オレのログイン";
    apass = "ボクのログイン";
    document.getElementsByClassName("req")[0].appendChild( btn1 );
    document.getElementsByClassName("req")[0].appendChild( btn2 );
  }

  function login1() {
    if (document.getElementsByName("aikotoba").length > 0 ) {
      document.getElementsByName("aikotoba")[0].value = tpass;
      var list = document.getElementsByTagName('a');
      for ( var x = 0; x < list.length ; x++ ) {
        if ( list[x].innerHTML == "次へ" ) {
          list[x].click();
        }
      }
    }
    else {
      document.getElementsByName("loginPassword")[0].value = tpass;
      document.getElementsByName("U010302")[0].click(); // ログインボタンを押す
    }
  }
  function login2() {
    if (document.getElementsByName("aikotoba").length > 0 ) {
      document.getElementsByName("aikotoba")[0].value = apass;
      var list = document.getElementsByTagName('a');
      for ( var x = 0; x < list.length ; x++ ) {
        if ( list[x].innerHTML == "次へ" ) {　　// 次へボタンがあれば押す
          list[x].click();
        }
      }
    }
    else {
      document.getElementsByName("loginPassword")[0].value = apass;
      document.getElementsByName("U010302")[0].click(); // ログインボタンを押す
    }
  }
}

completion(result);

```

**実行してみる**

ゆうちょ銀行のログイン画面を表示させておき -> 「共有メニュー」-> 「ショートカット」-> ゆうちょのショートカットを選択

![S__102203395.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/97e45e22-0740-63c4-1b16-aaa9c224d6d4.jpeg)➡︎![S__102203396.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/3fe5d0c6-83fc-2280-f669-5e51f352059c.jpeg) ➡︎![S__102203397.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/284d8437-e274-8de9-0062-dedef13ded2d.jpeg)

上記の最後の画像のように、JavaScript が実行された結果 "オレオレ" と "子供の口座" ボタンが追加されています。
これをクリックすると、お客様番号が入力され次の画面へ進みます。
次のページに進むたびにショートカットを呼び出す必要がありますが、以下のように合言葉や最後のパスワード画面へもボタンが追加され、それをクリックするだけでログインが完了します。
※通常は一度ログインすると合言葉は聞かれなくなります。

![S__102203400.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/54e5e74f-227c-b132-1fa1-4337cb35e3cd.jpeg)➡︎![S__102203402.jpg](https://qiita-image-store.s3.amazonaws.com/0/246034/ce44e513-066b-d889-6cb4-53e36e650b95.jpeg)

通勤電車の中でも操作できるレベルになっていると思います。
なお、わたしは iPhone でデバッグはしたくないので Mac + Greasemonkey で動作したものをコピペで利用しています。
またログイン関連の動作においては、通常複数回まちがえるとロックされますので、作成とテスト時にはその点に注意が必要です。

以上、なにかのお役に立てましたら幸いです。