web-dev-qa-db-ja.com

クリックで貼り付ける方法は?それはグーグルドキュメントで動作します

ユーザーがクリックしたときに実際の貼り付けイベントを開始できるようにしたい。これがセキュリティの問題である可能性があることを理解できます。ユーザーのクリップボードにアクセスできるWebページがあると、それは悪いことになるからです。そのため、すべてのブラウザーがクリップボードデータへのアクセスを許可しないと考えました。

しかし、たとえばgoogle docs(Wordのようなアプリケーション)では、クリップボードのデータが別の場所でクリップボードにコピーされている場合でも、カスタムコンテキストメニュー(コンテキストメニューのふりをしているhtml要素を右クリック)から貼り付けることができますMicrosoft Paintのようなアプリケーション。これはGoogleで機能しますChromeブラウザ、これは私の興味のあるブラウザです。

私は彼らがフラッシュを使用してそれを行うと思ったが、クロムでフラッシュを完全に無効にしても、それはまだ機能します。これについてはすでに 質問 がありましたが、そこに述べられている答えは正しくありません。その質問の別の答えは、Googleがchrome拡張機能を使用していることを示唆していますが、Chromeのすべての拡張機能を無効にしても、まだ機能します

ウィンドウで再現する方法:

  • クロムのフラッシュを無効にし、すべての拡張機能を無効にします
  • 再起動
  • google docsに移動し、新しい空の書き込みドキュメントを開きます(スプレッドシートではなくドキュメント)
  • windowsでMicrosoftペイントアプリケーションを実行する
  • microsoft Paintで何かを描画し、Ctrl + Aを押してすべてを選択し、Ctrl + Cを押してコピーします
  • chromeに戻ってドキュメントの空のページに切り替え、空のページを右クリックします
  • 人工的なコンテキストメニューから[貼り付け]を選択します(コンテキストメニューはウィンドウのネイティブメニューではなく、google docsのhtml Webページからのものであることに注意してください)
  • クリップボードの画像がドキュメントドキュメントに貼り付けられていることがわかります(!)
  • 彼らはこれをどのように行うのですか?

現在のウィンドウで貼り付けイベントがトリガーされるため、ユーザーがWebページでCtrl + Vを押した場合にクリップボードデータにアクセスする方法を知っています。しかし、どのようにしてクリップボードデータにアクセスするかまたは実際のクリップボードデータの貼り付けを開始するか(たとえば、mspaintにコピーされたビットマップ) )JavaScriptで(またはjqueryを使用して)、ユーザーがボタンまたはdivをクリックするだけですか?

30
Tomas M

ユーザーがクリックしたときに実際の貼り付けイベントを開始できるようにしたい。これはセキュリティの問題である可能性があることを理解できます。

上記は一番下の行です。

このコードがある JS Fiddle

_var Copy =  document.getElementById('copy'),
    Cut =  document.getElementById('cut'),
    Paste =  document.getElementById('paste');

// Checking Clipboard API without an action from the user
console.log('Copy:' + document.queryCommandSupported('copy'));
console.log('Cut:' + document.queryCommandSupported('cut'));
console.log('Paste:' + document.queryCommandSupported('paste'));


//Now checking the clipboard API upon a user action
Copy.addEventListener('click', function(){
    console.log('Copy:' + document.queryCommandSupported('copy'));
});

Cut.addEventListener('click', function(){
    console.log('Cut:' + document.queryCommandSupported('cut'));
});

Paste.addEventListener('click', function(){
    console.log('Paste:' + document.queryCommandSupported('paste'));
});_
_<button id="copy">Copy</button>
<button id="cut">Cut</button>
<button id="paste">Pate</button>_

さまざまなブラウザーで確認すると、ブラウザーがqueryCommandSupported()を使用して Clipboard API を処理した場合の反応が異なります。結果は次のとおりです。

Chrome 47:

  • ユーザーのアクションなしで、コピー:false、カット:false、過去:false
  • ユーザーアクションを使用して、コピー:true、カット:true、貼り付け:false

Firefox 43:

  • ユーザーのアクションなしで、コピー:true、カット:true、過去:false
  • ユーザーアクションを使用して、コピー:true、カット:true、貼り付け:false

IE11:-Edgeでも同じだと思います

  • ユーザーのアクションなしで、コピー:true、カット:true、過去:true
  • ユーザーアクションを使用して、コピー:true、カット:true、貼り付け:true
  • すべてのオプションがtrueの場合、IEは、上記のすべてのアクションの許可をユーザーに求めます。

Safari:-iOS Safariと同じ

  • 有効な選択に対してのみコピーイベントを発生させ、フォーカスされた編集可能なフィールドでのみカットアンドペーストします。
  • document.execCommand()ではなく、ショートカットキーを介したOSクリップボードの読み取り/書き込みのみ。

クリップボードAPIの詳細なブラウザーサポートについて caniuse.com/#search=clip

また、ブラウザは、次のように_conteneditable="true"_要素の右クリックコンテキストメニューを使用した貼り付けをサポートしています JS Fiddle 2


しかし、たとえばgoogle docs(Wordのようなアプリケーション)では、クリップボードのデータが別の場所でクリップボードにコピーされている場合でも、カスタムコンテキストメニュー(コンテキストメニューのふりをしているhtml要素を右クリック)から貼り付けることができますMicrosoft Paintのようなアプリケーション。

彼らはフラッシュを使用してそれを行うと思ったが、クロムでフラッシュを完全に無効にしてもまだ機能します。

から Google Appsのアドオンを開発するためのGoogle Appsスクリプトドキュメント
"プラットフォーム:Appsスクリプトのコードエディターは、Googleスプレッドシート、ドキュメント、フォーム内から起動するウェブアプリです。言語はJavaScriptに基づいています_but executes on Google's servers rather than directly in the user's browser_(クライアント側のユーザーインターフェースを除く... "。

サーバー上で実行されているため、エクスペリエンスを向上させるために、特定の機能を有効にしたり、Javaを使用したりできると思います。


EDIT 1:
clipboard.js をチェックすると、ライブラリには「貼り付け」のオプションがなく、「(コピー)と「カット」のみが、「ブラウザのサポート "ページの最後にあるセクションでは、ライブラリが execCommand APIに依存しており、Safariでは機能しないことがわかります。


編集2:
質問とコメントの更新時に、Googleドキュメントの部分について、私は Prt Sc クリップボードにスクリーンショットを表示するには、ChromeでGoogleドキュメントを開き、右クリックしてcustomコンテキストメニューの[貼り付け]をクリックし、確実に機能するように、Googleを開きました。 Firefoxのドキュメントと「貼り付け」オプションをクリックするとすぐに this response が表示されました

enter image description here

また、参考までに、IE11でも同じことを試みましたが、21分以来、Googleドキュメントを起動しようとしています。

したがって、結論はおそらく、そしてほとんどの場合、「Google」Chrome has aException:-条件付きステートメントのようなもの-「Google」ドキュメントとブラウザの他のGoogleサービスの場合また、Firefoxの拡張機能である @ julien-gregoire は正しかったと思います。

このGoogleドキュメントのサポートページ から:

セキュリティ上の理由から、ほとんどのブラウザーでは、ドキュメント、スプレッドシート、スライドなどのウェブアプリがメニューからコンピューターのクリップボードを使用することを許可していません。

ただし、Chromeを使用している場合は、GoogleドライブChromeアプリをインストールすることで、クリップボードへのアクセスを許可できます。これにより、右クリックメニューを使用してコンテンツをコピーして貼り付けることができます(またはツールバーの[編集]メニューから[コピー]または[貼り付け]。アプリをインストールするには、Chrome Web Storeにアクセスしてください。

そして このスモールビジネスページ

キーボードショートカットがない場合は、コピーと貼り付けのオプションが2つあります。[編集]メニューから[コピー]または[貼り付け]を選択するか、ドキュメントを右クリックして[コピー]または[貼り付け]を選択します。コンテキストメニュー。 Googleドキュメントでは、これらのオプションはどちらもChrome Googleドライブウェブアプリがインストールされているユーザーのみが利用できます。アプリは無料ですが、他のブラウザでは利用できません。

したがって、彼らはすでにそのアプリをChromeの新しいバージョンの組み込み機能として実装しているようです。

11
Mi-Creativity

カスタムpasteはChromeで機能しますが、拡張機能を介してのみ機能します。 google docsコードを見ると、拡張機能がインストールされていないと貼り付けできないことがわかります。そして、Firefoxでコンテキストメニューの貼り付けを使用してみると、利用できないこと、および使用する必要があることがわかります。 CTRL+V。あなたはグーグルドキュメントのソースコードでこれを見つけることができます:

コピーして貼り付けるには、無料のGoogleドライブウェブアプリが必要です。これにより、クリップボードにアクセスして、切り取り、コピー、貼り付けを行うことができます。

したがって、pasteコマンドを機能させるには拡張機能が必要であることは明らかです。

これを行う1つの方法は、execCommand('paste')を使用することです。これは、ページから呼び出されても機能しませんが、実際には拡張コンテンツスクリプトで機能します。次のようにclipboardReadmanifest.json権限に追加するだけですこの:

_permissions: {
    ...
    "clipboardRead"
    ...
}
_

次に、コンテンツスクリプトでdocument.execCommand('paste')が機能します。

編集:

@ tomas-Mと@ Mi-Creativityで指摘されているように、Chrome上のGoogleドキュメントの実装は、Chrome自体にあり、公開された拡張機能にはないようです。たぶん、これがどこで定義されているかについての手掛かりを与えることができます: https://code.google.com/p/chromium/codesearch#chromium/src/chrome/common/extensions/api/_permission_features.json&q= clipboardRead&sq = package:chromium&dr = C&l = 164

それが実際に機能する方法であるかどうかを言うのは難しいですが、いずれの場合も、拡張機能を通じて他のサイトのexecCommand('paste')を「ロック解除」できます。あまり実用的ではありませんが、機能します。

コンソールでdocument.execCommand('paste')をテストすると、Googleドキュメントではtrueが得られますが、他のページではfalseが得られるため、この機能がGoogleドキュメントに実装されている方法だと思います。

6

ブラウザーによって動作は異なります。ここで動作する実装を見つけることができます: https://jsfiddle.net/1vmansr2/

関連するJS:

function myFunction() {

   navigator.clipboard.readText()
.then(text => {
document.getElementById("demo").innerHTML = text;

})
.catch(err => {
document.getElementById("demo").innerHTML = 'Failed to read clipboard contents: '+err;
});


}
0
Antoine