データモデル「docs」内のすべてのドキュメントに対して
自動的に適用されます各項目
には、ファイルのアイコン、ウェブ上でファイルを開くリンク、最終更新日時が含まれています。
次に、このテンプレートのレンダリングを管理するコントローラを Angular に指示する必要があります。そのために、
ngController ディレクティブを使用して、テンプレートを管理するよう DocsController に指示します
:
<body data-ng-controller="DocsController">
<section id="main">
  <ul>
    <li data-ng-repeat="doc in docs">
      <img data-ng-src=""> <a href=""></a> 
      <span class="date"></span>
    </li>
  </ul>
</section>
</body>
ここでは、イベント リスナーやイベント プロパティのデータをフックする例は示されていません。
あります。Angular は大変な作業です。
最後に、テンプレートに Angular のライトを追加します。一般的な方法は、
ngApp ディレクティブのすべて :
<html data-ng-app="gDriveApp">
必要に応じて、アプリの対象をページ内の小さな領域に絞り込むこともできます。私たちが持っているのは
このアプリのコントローラは 1 つですが、後でさらに追加する場合は ngApp を一番上に置きます。
要素を使用することで、ページ全体を Angular に対応できるようになります。
main.html の最終的な結果は次のようになります。
<html data-ng-app="gDriveApp">
<head>
  …
  <base target="_blank">
</head>
<body data-ng-controller="DocsController">
<section id="main">
  <nav>
    <h2>Google Drive Uploader</h2>
    <button class="btn" data-ng-click="fetchDocs()">Refresh</button>
    <button class="btn" id="close-button" title="Close"></button>
  </nav>
  <ul>
    <li data-ng-repeat="doc in docs">
      <img data-ng-src=""> <a href=""></a>  
      <span class="date"></span>
    </li>
  </ul>
</section>
コンテンツ セキュリティ ポリシーについて
他の多くの JS MVC フレームワークとは異なり、Angular v1.1.0 以降では、厳格な
CSP。すぐに使えます。
ただし、v1.0.1 と v1.1.0 の間で古いバージョンの Angular を使用している場合は、
「コンテンツ セキュリティ モード」で実行する Angular。そのためには、ngCsp ディレクティブをインクルードします。
ngApp とともに追加します。
<html data-ng-app data-ng-csp>
認可の処理
データモデルはアプリ自体では生成されません。代わりに、外部 API(
Google Drive API)。そのため、アプリのデータを入力するには多少の作業が必要です。
API リクエストを行う前に、ユーザーの Google アカウントの OAuth トークンを取得する必要があります。
そのため、chrome.identity.getAuthToken() の呼び出しをラップし、
accessToken。これは Drive API の今後の呼び出しで再利用できます。
GDocs.prototype.auth = function(opt_callback) {
  try {
    chrome.identity.getAuthToken({interactive: false}, function(token) {
      if (token) {
        this.accessToken = token;
        opt_callback && opt_callback();
      }
    }.bind(this));
  } catch(e) {
    console.log(e);
  }
};
トークンを取得したら、Drive API に対してリクエストを行い、モデルにデータを入力します。
スケルトン コントローラ
「モデル」(ドキュメントと呼ばれます)で、
をテンプレートに追加します。
var gDriveApp = angular.module('gDriveApp', []);
gDriveApp.factory('gdocs', function() {
  var gdocs = new GDocs();
  return gdocs;
});
function DocsController($scope, $http, gdocs) {
  $scope.docs = [];
  $scope.fetchDocs = function() {
     ...
  };
  // Invoke on ctor call. Fetch docs after we have the oauth token.
  gdocs.auth(function() {
    $scope.fetchDocs();
  });
}
gdocs.auth() は、DocsController コンストラクタの一部として呼び出されます。Angular の
内部処理によりコントローラが作成されると、ユーザーを待つ新しい OAuth トークンが保証されます。
データを取得しています
テンプレートのレイアウト。コントローラ スキャフォールディング済み。OAuth トークンを手に入れましょう。次のステップ
ここで、メイン コントローラ メソッド fetchDocs() を定義します。コントローラの主軸であり、
ユーザーのファイルをリクエストし、ドキュメント配列に API レスポンスのデータを格納します。
$scope.fetchDocs = function() {
  $scope.docs = []; // First, clear out any old results
  // Response handler that doesn't cache file icons.
  var successCallback = function(resp, status, headers, config) {
    var docs = [];
    var totalEntries = resp.feed.entry.length;
    resp.feed.entry.forEach(function(entry, i) {
      var doc = {
        title: entry.title.$t,
        updatedDate: Util.formatDate(entry.updated.$t),
        updatedDateFull: entry.updated.$t,
        icon: gdocs.getLink(entry.link,
                            'http://schemas.google.com/docs/2007#icon').href,
        alternateLink: gdocs.getLink(entry.link, 'alternate').href,
        size: entry.docs$size ? '( ' + entry.docs$size.$t + ' bytes)' : null
      };
      $scope.docs.push(doc);
      // Only sort when last entry is seen.
      if (totalEntries - 1 == i) {
        $scope.docs.sort(Util.sortByDate);
      }
    });
  };
  var config = {
    params: {'alt': 'json'},
    headers: {
      'Authorization': 'Bearer ' + gdocs.accessToken,
      'GData-Version': '3.0'
    }
  };
  $http.get(gdocs.DOCLIST_FEED, config).success(successCallback);
};
fetchDocs() は Angular の $http サービスを使用して、XHR を介してメインフィードを取得します。OAuth アクセス
トークンは、他のカスタム ヘッダーやパラメータとともに Authorization ヘッダーに含まれます。
successCallback は API レスポンスを処理し、エントリごとに新しいドキュメント オブジェクトを作成します。
できます。
この時点で fetchDocs() を実行すると、すべてが機能し、ファイルのリストが表示されます。

やりました!
おっと...きれいなファイル アイコンがありません。その理由は、コンソールをざっと確認すると
CSP 関連のエラー:

アイコン img.src を外部 URL に設定しようとしているためです。これは CSP に違反しています。例: https://ssl.gstatic.com/docs/doclist/images/icon_10_document_list.pngこの問題を解決するには
リモートアセットをローカルアプリに pull する必要があります。
リモート画像アセットのインポート
CSP が怒鳴るのをやめるために、XHR2 を使用して「インポート」します。ファイル アイコンを blob に設定してから、
img.src をアプリによって作成された blob: URL にマッピング。
XHR コードを追加して更新した successCallback は次のとおりです。
var successCallback = function(resp, status, headers, config) {
  var docs = [];
  var totalEntries = resp.feed.entry.length;
  resp.feed.entry.forEach(function(entry, i) {
    var doc = {
      ...
    };
    $http.get(doc.icon, {responseType: 'blob'}).success(function(blob) {
      console.log('Fetched icon via XHR');
      blob.name = doc.iconFilename; // Add icon filename to blob.
      writeFile(blob); // Write is async, but that's ok.
      doc.icon = window.URL.createObjectURL(blob);
      $scope.docs.push(doc);
      // Only sort when last entry is seen.
      if (totalEntries - 1 == i) {
        $scope.docs.sort(Util.sortByDate);
      }
    });
  });
};
CSP に再び満足して、次のような素晴らしいファイル アイコンが表示されるようになりました。

オフラインにする: 外部リソースのキャッシュ保存
最適化が必要なのは明らかに、ファイル アイコンごとに数百回の XHR リクエストを行わないことです。
fetchDocs() を呼び出すたびに作成されます。デベロッパー ツール コンソールで [更新] を押して、これを確認できます
ボタンを何回か押します。毎回、n 個の画像が取得されます。

successCallback を変更してキャッシュ レイヤを追加しましょう。追加された部分は太字でハイライト表示されています。
$scope.fetchDocs = function() {
  ...
  // Response handler that caches file icons in the filesystem API.
  var successCallbackWithFsCaching = function(resp, status, headers, config) {
    var docs = [];
    var totalEntries = resp.feed.entry.length;
    resp.feed.entry.forEach(function(entry, i) {
      var doc = {
        ...
      };
      // 'https://ssl.gstatic.com/doc_icon_128.png' -> 'doc_icon_128.png'
      doc.iconFilename = doc.icon.substring(doc.icon.lastIndexOf('/') + 1);
      // If file exists, it we'll get back a FileEntry for the filesystem URL.
      // Otherwise, the error callback will fire and we need to XHR it in and
      // write it to the FS.
      var fsURL = fs.root.toURL() + FOLDERNAME + '/' + doc.iconFilename;
      window.webkitResolveLocalFileSystemURL(fsURL, function(entry) {
        doc.icon = entry.toURL(); // should be === to fsURL, but whatevs.
        $scope.docs.push(doc); // add doc to model.
        // Only want to sort and call $apply() when we have all entries.
        if (totalEntries - 1 == i) {
          $scope.docs.sort(Util.sortByDate);
          $scope.$apply(function($scope) {}); // Inform angular that we made changes.
        }
      }, function(e) {
        // Error: file doesn't exist yet. XHR it in and write it to the FS.
        $http.get(doc.icon, {responseType: 'blob'}).success(function(blob) {
          console.log('Fetched icon via XHR');
          blob.name = doc.iconFilename; // Add icon filename to blob.
          writeFile(blob); // Write is async, but that's ok.
          doc.icon = window.URL.createObjectURL(blob);
          $scope.docs.push(doc);
          // Only sort when last entry is seen.
          if (totalEntries - 1 == i) {
            $scope.docs.sort(Util.sortByDate);
          }
        });
      });
    });
  };
  var config = {
    ...
  };
  $http.get(gdocs.DOCLIST_FEED, config).success(successCallbackWithFsCaching);
};
webkitResolveLocalFileSystemURL() コールバックでは、実行時に $scope.$apply() を呼び出している点に注目してください。
最後のエントリが表示されます。通常、$apply() を呼び出す必要はありません。Angular がデータの変更を検出します
構築できます。ただし、この例では非同期コールバックの追加レイヤがあり、
Angular では認識されません。モデルを更新したら、Angular に明示的に通知する必要があります。
初回実行時には、アイコンは HTML5 ファイル システムに存在せず、
window.webkitResolveLocalFileSystemURL() を指定するとエラー コールバックが呼び出されます。そのため
前の手法を再利用して画像を取得できます今度が違うのは
各 blob がファイル システムに書き込まれることを条件とします(writeFile() を参照)。コンソールでは
動作:

次回実行したとき(または [更新] ボタンを押すと)、
webkitResolveLocalFileSystemURL() が存在するのは、ファイルが以前にキャッシュに保存されているためです。アプリによる設定
doc.icon をファイルの filesystem: URL に追加して、アイコンのコストのかかる XHR が発生しないようにします。
ドラッグ&ドロップ アップロード
アップローダ アプリがファイルをアップロードできないのは、虚偽の広告です。
app.js では、HTML5 ドラッグ&ドロップに関する小さなライブラリ
DnDFileController。デスクトップからファイルをドラッグしてアップロードできる
Google ドライブに移動します。
これを gdocs サービスに追加するだけで、次のように機能します。
gDriveApp.factory('gdocs', function() {
  var gdocs = new GDocs();
  var dnd = new DnDFileController('body', function(files) {
    var $scope = angular.element(this).scope();
    Util.toArray(files).forEach(function(file, i) {
      gdocs.upload(file, function() {
        $scope.fetchDocs();
      });
    });
  });
  return gdocs;
});