---
title: JavaScriptでpreタグで囲まれたソースコードをtextareaにコピーする
author: aterai
pubdate: 2012-07-24T18:09:17+09:00
description: JavaScriptを使用して、preタグで囲まれたソースコードを簡単にコピーするためのBookmarkletを作成する
---
#contents

* 概要 [#summary]
`pre`タグで囲まれたソースコードを簡単にコピーする

- オリジナルは、[http://sybian99.googlepages.com/preToTextarea.user.js pre to textarea for Greasemonkey]
-- `pre`タグをtextareaにして簡単にコピーできるようにする
- [https://ateraimemo.com/data/javascript/pre2textarea.user.js pre2textarea.user.js]
- `pre`要素をダブルクリックすると、内容が`textarea`に変換される
- ダウンロード用のリンクを作成(`Java`のソースコードの場合は自動的にファイル名を取得)し、保存ダイアログを開く
-- [[JavaScriptでソースコードからJavaのファイル名を取得する>JavaScript/JavaFileName]]

* ソースコード [#sourcecode]
#gist(5441120)

* Bookmarklet版 [#bookmarklet]
- 名前
-- `pre2textarea`
- アドレス(`YUI Compressor` で圧縮)
 (function(){window.URL=window.URL||window.webkitURL;function h(l,k,m){var j=new Blob([l],{type:k+";charset=UTF-8"}),i=document.createElement("a");i.innerHTML="Download: "+m;i.setAttribute("download",m);i.href=window.URL.createObjectURL(j);return i}function d(j){var i=j.match(/public(?:\s|final)+(?:class|interface|enum)\s+([^<{\s]+)/m);return(i?i[1]:"Unknown")+".java"}function e(i){var j=document.createElement("div");j.innerHTML=i.innerHTML.replace(/<br[ \/]*>/gi,"\n").replace(/<.*?>/gm,"");return j.childNodes[0].nodeValue.replace(/\xA0/g," ")}function c(j){var i=j.downloadLink;j.parentNode.replaceChild(j.originalPre,j);if(i!=null&&i.parentNode){window.URL.revokeObjectURL(i.href);i.parentNode.removeChild(i)}}var f=function(l){var k=function(m){switch(m.type){case"keydown":if(m.keyCode=="27"){c(this)}break;case"dblclick":c(this)}},j=this.getBoundingClientRect(),i=document.createElement("textarea");i.addEventListener("keydown",k,false);i.addEventListener("dblclick",k,false);i.style.width=j.width+"px";i.style.height=(j.height>240?240:j.height)+"px";i.originalPre=this;i.value=e(this);this.tx=i;this.parentNode.replaceChild(this.tx,this);this.tx.focus();this.tx.select();i.downloadLink=h(i.value,"text/plain",d(i.value));i.parentNode.insertBefore(i.downloadLink,i.nextSibling);i.downloadLink.click()},g=document.getElementsByTagName("pre"),b=0,a=g.length;for(;b<a;b++){g[b].addEventListener("dblclick",f,false)}}());
 (function(){window.URL=window.URL||window.webkitURL;function h(l,k,m){var j=new Blob([l],{type:k+";charset=UTF-8"}),i=document.createElement("a");i.innerHTML="Download: "+m;i.setAttribute("download",m);i.href=window.URL.createObjectURL(j);return i}function d(j){var i=j.match(/public(?:\s|final)+(?:class|interface|enum)\s+([^<{\s]+)/m);return(i?i[1]:"Unknown")+".java"}function e(i){var j=document.createElement("div");j.innerHTML=i.innerHTML.replace(/<br[ \/]*>/gi,"\n").replace(/<.*?>/gm,"");return j.childNodes[0].nodeValue.replace(/\xA0/g," ")}function c(j){var i=j.downloadLink;j.parentNode.replaceChild(j.originalPre,j);if(i!=null&&i.parentNode){window.URL.revokeObjectURL(i.href);i.parentNode.removeChild(i)}}var f=function(l){var k=function(m){switch(m.type){case"keydown":if(m.key==="Escape"){c(this)}break;case"dblclick":c(this)}},j=this.getBoundingClientRect(),i=document.createElement("textarea");i.addEventListener("keydown",k,false);i.addEventListener("dblclick",k,false);i.style.width=j.width+"px";i.style.height=(j.height>240?240:j.height)+"px";i.originalPre=this;i.value=e(this);this.tx=i;this.parentNode.replaceChild(this.tx,this);this.tx.focus();this.tx.select();i.downloadLink=h(i.value,"text/plain",d(i.value));i.parentNode.insertBefore(i.downloadLink,i.nextSibling);i.downloadLink.click()},g=document.getElementsByTagName("pre"),b=0,a=g.length;for(;b<a;b++){g[b].addEventListener("dblclick",f,false)}}());

* メモ: ローカルにドロップして保存(ファイル名付き) [#ua1c0148]
- [http://blog.futuresoftware.jp/?p=101 FutureSoftware開発日誌 Ver2.0 » HTML5のドラッグ&ドロップによるファイル保存]
-- `Chrome`でのみ動作
-- ファイルとしてダウンロード可能

#code{{
function makeDraggableDownloadLink(text, mimeType, fileName) {
  var blob = new Blob([text], {type: mimeType}),
         a = document.createElement('a');
  a.appendChild(document.createTextNode("download"));
  a.setAttribute('download', fileName);
  window.URL = window.URL || window.webkitURL;
  a.href = window.URL.createObjectURL(blob);
  a.addEventListener("dragstart", function(e) {
    e.dataTransfer.setData("DownloadURL", [mimeType,fileName,this.href].join(':'));
  }, false);
  return a;
}
}}

* メモ: 直接クリップボードにコピー [#baa5f2ba]
- [http://javascripter.hatenablog.com/entry/20091230/1262191418 クリップボードにコピー - 素人がプログラミングを勉強していたブログ]
- [http://fukayatsu.github.com/blog/2012/07/22/markdown-linker-for-chrome/ markdown形式でリンクをクリップボードにコピーするchrome-extension作った - fukayatsu.dev()]

 //ie, chrome-extension???
 document.execCommand("copy");

* メモ: Clipboard API [#q55b37f8]
- `Clipboard API`が使用できる`Chrome`や`Opera 12.50`の場合、コピー、カットすると自動的に元の`pre`に戻すことが可能

#code{{
var listener = function(e) {
  var tx = document.createElement("textarea"),
    rect = this.getBoundingClientRect(),
    name, ret,
  closeListener = function(e) {
    switch(e.type) {
    case 'copy':
    case 'cut':
      var dataTransfer = e.clipboardData;
      dataTransfer.items.add(this.innerText, 'text/plain');
      cleanup(this);
      e.preventDefault();
      break;
    case 'keydown':
      if(e.keyCode=="27") { // ESC
      if(e.key==="Escape") {
        cleanup(this);
      }
      break;
    case 'dblclick':
      cleanup(this);
    }
  };
  tx.addEventListener('copy',     closeListener, false);
  tx.addEventListener('cut',      closeListener, false);
  tx.addEventListener("keydown",  closeListener, false);
  tx.addEventListener("dblclick", closeListener, false);
// ...
}}

* 参考リンク [#reference]
- [http://sybian99.googlepages.com/preToTextarea.user.js pre to textarea for Greasemonkey]
- [http://www.w3.org/TR/clipboard-apis/ Clipboard API and events]
- [http://my.opera.com/desktopteam/blog/2012/07/06/marlin-1250-swim Opera Desktop Team - First bite of 12.50 ‘Marlin’: Clipboard API, redesigned key event handling, -webkit- CSS, and Notification Center]
- [http://domes.lingua.heliohost.org/webapi/intro-webplatform1.html#section-1-3 クリップボード API - Introduction to the Web Platform - DOM ECMAScripting]

* コメント [#comment]
#comment
#comment