[提案] QiitaでJavascriptを使いたい

Qiita Blog(公式)：[QiitaにおいてHTML要素の属性指定ができなくなりました(17/6/20)](http://blog.qiita.com/post/162037299989/disable-html-class)

<HR>

<A NAME=t />QiitaではJavaScriptが使えないので、ページに埋め込んだJavascriptを動かすブックマークレットを作ってみました。

目的・利点としては、

* Qiitaに投稿したJavaScriptを動かして見たい/見せたい。
* JavaScript本体はページに埋め込んでいるので、長いブックマークレットを見せなくてよい。
* いろいろなページで共通であれば、閲覧者側はブックマークが1つで済んで便利かなと。

#Javascript実行用ブックマークレット

ブックマークレットを実行するとボタンが出ます。

<div name='(function(){jsoutB.innerHTML=&#39;&lt;INPUT type="button" value="アラートボタン" onClick=alert("あらーと")&gt;&#39;;})();' id='jsoutB' class='javascript' />

```javascript:javascript実行用ブックマークレット
javascript:(function(){var elm=document.getElementsByClassName("javascript");for(var i=0;i<elm.length;i++){eval(elm[i].getAttribute("name"));}})();
```

ページに埋め込んだコードをeval()によりjavascriptに変換して実行します。

* URLバーでも実行できますが、貼付けると「javascript:」部分がカットされるので手入力してください
* IE,Chrome,FireFox,Safari,iPhone Safari,Androidブラウザ,Surface IEで動作確認しました。
* Androidではコピーすると改行位置にスペースが入るので手動で消してください。

## ページに埋め込んだJavascript

```javascript:ボタンを出すJavaScriptコード
<div name='(function(){jsoutB.innerHTML=&#39;&lt;INPUT type="button" value="アラートボタン" onClick=alert("あらーと")&gt;&#39;;})();' id='jsoutB' class='javascript' />
```

DIVタグとname,class,id属性はそのまま出力されたので、Divタグのname属性にJavascriptを埋め込みました。
```< (&lt;)``` ```> (&gt;)``` ```' (&#39;)``` はエンコードしてます。

# Javascriptサンプル集

そのまま埋め込めば使えるサンプルJavaScriptを作ってみました。
このサンプルJavascriptはご自由にお使い・改変して下さい。

## テーブルフィルタ
リストボックスでテーブルのフィルタ機能です。

<div id="jsOutSelect" />

|OS|機種|
|:--|:--|
|iOS|iPhone5S|
|iOS|iPhone6|
|Android|Xperia A|

<div name='(function(){var elm=jsOutSelect.nextSibling;while(!elm.tagName||elm.tagName.toLowerCase()!="table"){elm=elm.nextSibling;}var elmsTr=elm.getElementsByTagName("tr");for (var col=0;col&lt;elmsTr[0].children.length;col++){var optxt="",opvals=new Object();for (var row=1;row&lt;elmsTr.length;row++){var name=elmsTr[row].children[col].innerHTML;if(!opvals[name]){optxt+=&#39;&lt;option value="&#39;+name+&#39;"&gt;&#39;+name+&#39;&lt;/option&gt;&#39;;opvals[name]=1;}elmsTr[row].value=~0;}elmsTr[0].children[col].innerHTML+=&#39;&lt;BR&gt;&lt;select id=&#39;+col+&#39;&gt;&lt;option value="all"&gt;全て&lt;/option&gt;&#39;+optxt+&#39;&lt;/select&gt;&#39;;elmsTr[0].getElementsByTagName("select")[col].onchange=function(){var col=this.id;for(var i=1;i&lt;elmsTr.length;i++){var name=elmsTr[i].children[col].innerHTML;if(this.value=="all"||this.value==name){elmsTr[i].value|=(1&lt;&lt;col);}else{elmsTr[i].value&=~(1&lt;&lt;col);}elmsTr[i].style.display=(elmsTr[i].value==~0)?"":"none";}};}})();' class='javascript' />

直後のテーブルにフィルタを追加します。

```html:テーブルの直前に置く
<div id="jsOutSelect" />

|OS|機種|
|:--|:--|
|iOS|iPhone5S|
|iOS|iPhone6|
|Android|Xperia A|
```

```javascript:このサンプル用に埋め込んだJavascript
<div name='(function(){var elm=jsOutSelect.nextSibling;while(!elm.tagName||elm.tagName.toLowerCase()!="table"){elm=elm.nextSibling;}var elmsTr=elm.getElementsByTagName("tr");for (var col=0;col&lt;elmsTr[0].children.length;col++){var optxt="",opvals=new Object();for (var row=1;row&lt;elmsTr.length;row++){var name=elmsTr[row].children[col].innerHTML;if(!opvals[name]){optxt+=&#39;&lt;option value="&#39;+name+&#39;"&gt;&#39;+name+&#39;&lt;/option&gt;&#39;;opvals[name]=1;}elmsTr[row].value=~0;}elmsTr[0].children[col].innerHTML+=&#39;&lt;BR&gt;&lt;select id=&#39;+col+&#39;&gt;&lt;option value="all"&gt;全て&lt;/option&gt;&#39;+optxt+&#39;&lt;/select&gt;&#39;;elmsTr[0].getElementsByTagName("select")[col].onchange=function(){var col=this.id;for(var i=1;i&lt;elmsTr.length;i++){var name=elmsTr[i].children[col].innerHTML;if(this.value=="all"||this.value==name){elmsTr[i].value|=(1&lt;&lt;col);}else{elmsTr[i].value&=~(1&lt;&lt;col);}elmsTr[i].style.display=(elmsTr[i].value==~0)?"":"none";}};}})();' class='javascript' />
```

```js:圧縮前
<script type="text/javascript">
//テーブル行取得
var elm=jsOutSelect.nextSibling;
while(!elm.tagName||elm.tagName.toLowerCase()!="table"){elm=elm.nextSibling;}
var elmsTr=elm.getElementsByTagName("tr");

for (var col=0;col<elmsTr[0].children.length;col++){
  //リストボックス作成
  var optxt="",opvals=new Object();
  for (var row=1;row<elmsTr.length;row++){
    var name=elmsTr[row].children[col].innerHTML;
    if(!opvals[name]){
      optxt+='<option value="'+name+'">'+name+'</option>';
      opvals[name]=1;
    }
    elmsTr[row].value=~0;
  }
  elmsTr[0].children[col].innerHTML+='<BR><select id='+col+'><option value="all">全て</option>'+optxt+'</select>';

  //リストを変更した時の絞り込み処理
  elmsTr[0].getElementsByTagName("select")[col].onchange=function(){
    var col=this.id;
    for(var i=1;i<elmsTr.length;i++){
      var name=elmsTr[i].children[col].innerHTML;
      if(this.value=="all"||this.value==name)
        {elmsTr[i].value|=(1<<col);}else{elmsTr[i].value&=~(1<<col);}
      elmsTr[i].style.display=(elmsTr[i].value==~0)?"":"none";
    }
  };
}
</script>
```

## スライドショーもどき
ボタン押下する度に画像とタイトルを順番に表示。またはサムネイル画像クリックで表示。

<IMG id="jsSlideImg2" HEIGHT=150 ALT="[ここに画像が表示]"><span id="jsTitle2">[ここにタイトルが表示]</span>
<INPUT type='button' id="jsNextButton2"/>

<IMG SRC=https://qiita-image-store.s3.amazonaws.com/0/52320/10c118c1-ef93-7cd0-e5b6-62c6aa2e3b09.png TITLE="スライド1" HEIGHT=50 class=jspic> <IMG SRC=https://qiita-image-store.s3.amazonaws.com/0/52320/9c28d89c-efc5-6b29-c243-99c50d1a4ddc.png TITLE="スライド2" HEIGHT=50 class=jspic> <IMG SRC=https://qiita-image-store.s3.amazonaws.com/0/52320/ee066ea5-8426-6165-290f-4e3bf21ee44e.png TITLE="スライド3" HEIGHT=50 class=jspic>

<div name='(function(){function onClickJsNextButton2(){var elms=document.getElementsByClassName("jspic");if (jsSlideImg2.parentNode.tagName.toLowerCase()=="a"){jsSlideImg2.parentNode.href=elms[jsSlideImg2.value].src;}jsSlideImg2.src=elms[jsSlideImg2.value].src;jsTitle2.innerHTML=elms[jsSlideImg2.value].title;jsSlideImg2.value=(jsSlideImg2.value+1) % elms.length;}var elms=document.getElementsByClassName("jspic");for(var i=0;i&lt;elms.length;i++){elms[i].value=i;elms[i].onclick=function(){jsSlideImg2.value=this.value;onClickJsNextButton2();return false;};}jsSlideImg2.value=0;jsNextButton2.value=&#39;画像切替&#39;;jsNextButton2.onclick=function(){onClickJsNextButton2();};onClickJsNextButton2();})();' class='javascript' />

````html:スライドとタイトルとボタンを表示したい場所に記述
<IMG id="jsSlideImg2" HEIGHT=150><span id="jsTitle2"/>
<INPUT type='button' id="jsNextButton2"/>
````

サムネイル画像一覧のURLとTITLEを書き変えます。

````html:サムネイル一覧を表示したい場所に記述
<!-- img属性に「class=jspic」を追加 --><!--見やすくするために改行を入れてます-->
<IMG SRC=https://qiita-image-store.s3.amazonaws.com/0/52320/10c118c1-ef93-7cd0-e5b6-62c6aa2e3b09.png TITLE="スライド1" HEIGHT=50 class=jspic> 
<IMG SRC=https://qiita-image-store.s3.amazonaws.com/0/52320/9c28d89c-efc5-6b29-c243-99c50d1a4ddc.png TITLE="スライド2" HEIGHT=50 class=jspic> 
<IMG SRC=https://qiita-image-store.s3.amazonaws.com/0/52320/ee066ea5-8426-6165-290f-4e3bf21ee44e.png TITLE="スライド3" HEIGHT=50 class=jspic>
````

```javascript:このサンプル用に埋め込んだJavascript
<div name='(function(){function onClickJsNextButton2(){var elms=document.getElementsByClassName("jspic");if (jsSlideImg2.parentNode.tagName.toLowerCase()=="a"){jsSlideImg2.parentNode.href=elms[jsSlideImg2.value].src;}jsSlideImg2.src=elms[jsSlideImg2.value].src;jsTitle2.innerHTML=elms[jsSlideImg2.value].title;jsSlideImg2.value=(jsSlideImg2.value+1) % elms.length;}var elms=document.getElementsByClassName("jspic");for(var i=0;i&lt;elms.length;i++){elms[i].value=i;elms[i].onclick=function(){jsSlideImg2.value=this.value;onClickJsNextButton2();return false;};}jsSlideImg2.value=0;jsNextButton2.value=&#39;画像切替&#39;;jsNextButton2.onclick=function(){onClickJsNextButton2();};onClickJsNextButton2();})();' class='javascript' />
```

# JavaScript作成と関連ブックマークレット

## JavaScriptを埋め込み用に変換する秀丸スクリプト

```c:秀丸スクリプト
replaceall "<" , "&lt;" , regular, nocasesense, nohilight;
replaceall ">" , "&gt;" , regular, nocasesense, nohilight;
replaceall "'" , "&#39;" , regular, nocasesense, nohilight;
replaceall "^ +" , "" , regular, nocasesense, nohilight;
replaceall " *//[^&\"\n]*$" , "" , regular, nocasesense, nohilight;
replaceall "[\t\n]" , "" , regular, nocasesense, nohilight;
replaceall "^(.*)$" , "<div name='(function(){\\1})();' class='javascript' />" , regular, nocasesense, nohilight;
```

## コード確認用ブックマークレット

```javascript:
javascript:(function(){var elm=document.getElementsByClassName("javascript");for(var i=0;i<elm.length;i++){alert(elm[i].getAttribute("name"));break;}})();
```

埋め込んだjavascriptをアラート画面で確認するブックマークレットです。```break;```を外せば全件確認できます。

## 選択コード実行ブックマークレット

```javascript:
javascript:(function(){eval(document.getSelection().getRangeAt(0).toString().replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&#39;/g,"'"));})();
```

```javascript:Qiitaでconsole.logを有効にする場合
javascript:(function(){delete console.log;eval(document.getSelection().getRangeAt(0).toString().replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&#39;/g,"'"));})();
```

選択した文字列をjavascriptとして実行するブックマークレットです。
```<script type="text/javascript">``` ```</script>```の中身だけを選択します。