<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" version="2.0">
  <channel>
    <title>dara-j</title>
    <link>http://dara-j.asablo.jp/blog/</link>
    <description/>
    <language>ja</language>
    <generator>mc 0.0</generator>
    <pubDate>Sun, 18 Oct 2015 21:58:42 +0900</pubDate>
    <item>
      <title>sudo.cmd / su.cmd</title>
      <link>http://dara-j.asablo.jp/blog/2015/10/18/7852508</link>
      <guid>http://dara-j.asablo.jp/blog/2015/10/18/7852508</guid>
      <pubDate>Sun, 18 Oct 2015 21:57:13 +0900</pubDate>
      <dcterms:modified>2015-10-18T21:58:42+09:00</dcterms:modified>
      <dcterms:created>2015-10-18T21:58:42+09:00</dcterms:created>
      <description>&lt;h3&gt;コマンドラインから管理者に昇格したい&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
たとえば、&lt;a class="external_link" href="http://www.atmarkit.co.jp/fwin2k/win2ktips/988symlink/symlink.html" target="_blank" title="Windows Vista／Windows Server 2008でシンボリック・リンクを作成する － ＠IT"&gt;mklinkでシンボリックリンクを作りたい&lt;/a&gt;場合、いちいちcmd.exeを右クリックから「管理者として実行」するのは非常に面倒くさく、いま開いてるプロンプトから権限昇格できると便利だよね、と思って調べると、まぁ&lt;a class="external_link" href="https://www.google.co.jp/search?q=wsh+%E7%AE%A1%E7%90%86%E8%80%85%E6%A8%A9%E9%99%90&amp;ie=utf-8&amp;oe=utf-8&amp;hl=ja" target="_blank" title="wsh 管理者権限 - Google 検索"&gt;いろいろな方々がすでにやってたりする&lt;/a&gt;わけです。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
要は、WSHでShell.Application（エクスプローラを外部から操作するためのActiveXインターフェイス）で実行ファイルに対して「管理者として実行」で起動させる、という仕組みを使う、と。&#13;
&lt;/P&gt;&#13;
&#13;
&lt;h3&gt;んで、久々になんちゃってコマンド&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
んで、まぁ、suとかsudoとかを作ってみようかと。いや、先ほどの&lt;a class="external_link" href="https://www.google.co.jp/search?q=wsh+%E7%AE%A1%E7%90%86%E8%80%85%E6%A8%A9%E9%99%90&amp;ie=utf-8&amp;oe=utf-8&amp;hl=ja" target="_blank" title="wsh 管理者権限 - Google 検索"&gt;Google検索の結果&lt;/a&gt;に出てくるあちこちの記事でもすでに実現されてるんだけど、なんとなく自分でもやってみるか、という程度で。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
suとsudoを別々に実装してもいいんだけど、cmd.exeを「管理者として実行」できればsu、任意のコマンドならsudoになるので、同じスクリプトを別のバッチファイルから呼び出す方式で実装することに。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ダウンロード&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
こちらからダウンロードをどうぞ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="http://www.ne.jp/asahi/dara-j/web/sample/sudo_command.zip" title="sudo_command.zip"&gt;sudo / suコマンド一式&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
zipには&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;scripts/sudo.js&lt;/li&gt;&#13;
 &lt;li&gt;su.cmd&lt;/li&gt;&#13;
 &lt;li&gt;sudo.cmd&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
の3つのファイルが格納されてるので、この構造を維持したままパスが通ったところに設置するとコマンドラインからいつでも使えるようになります。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ソース - scripts/sudo.js&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
スクリプトのソースはこんな感じ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;textarea readonly="readonly" style="background-color:#e5eed1;color:#223d05;font-family:'Courier New',monospace;font-size:12px;line-height:110%;overflow:auto;height:600px;width:97%;border:dashed 1px #555;margin-top:5px;padding:5px"&gt;var fso = new ActiveXObject("Scripting.FileSystemObject");&#13;
var shell = new ActiveXObject("WScript.Shell");&#13;
var args = (function() {&#13;
    var results = [];&#13;
    for(var en = new Enumerator(WScript.Arguments); ! en.atEnd(); en.moveNext()) {&#13;
        results[results.length] = en.item();&#13;
    }&#13;
    results.toArgs = function() {&#13;
        var list = [];&#13;
        for(var i = 0, l = this.length; i &lt; l; i++) {&#13;
            list[list.length] = /\s/.test(this[i]) ? '"'+this[i]+'"' : this[i];&#13;
        }&#13;
        return list;&#13;
    };&#13;
    return results;&#13;
})();&#13;
var is_console = /cscript\.exe$/i.test(WScript.FullName);&#13;
&#13;
Error.prototype.toString = function() {&#13;
    var buf = [&#13;
        (this.description || this.message || 'error')&#13;
    ];&#13;
    if(this.number != null) {&#13;
        buf = buf.concat([' (', this.number, ')'])&#13;
    }&#13;
    return buf.join('');&#13;
};&#13;
&#13;
try {&#13;
    if(!args.length) {&#13;
        // コマンド指定がない場合はメッセージを表示して終了&#13;
        throw new Error([&#13;
            "指定のコマンドを管理者権限で実行します。",&#13;
            "",&#13;
            "[cscript | wscript] sudo.js [コマンド[ 文字列]]",&#13;
            ""&#13;
        ].join("\r\n"));&#13;
    }&#13;
    &#13;
    // 実行するコマンドと引数の整備&#13;
    var&#13;
        cmd_args = args.concat(),&#13;
        cmd = cmd_args.shift();&#13;
    &#13;
    if(/^cmd(\.exe)?$/i.test(cmd) &amp;&amp; /^\//.test(cmd_args)) {&#13;
        // 実行するコマンドがcmd.exeの場合は、&#13;
        // 先行してカレントディレクトリ変更するよう引数を調整&#13;
        var new_args = [&#13;
            cmd_args.shift(),&#13;
            [&#13;
                fso.GetFolder(shell.CurrentDirectory).Drive,&#13;
                'cd "' + shell.CurrentDirectory + '"'&#13;
            ].join(' &amp;&amp; ')&#13;
        ];&#13;
        if(cmd_args.length) {&#13;
            new_args[1] = new_args[1] + ' &amp;&amp; ';&#13;
            cmd_args = new_args.concat(cmd_args);&#13;
        } else {&#13;
            cmd_args = new_args;&#13;
        }&#13;
    }&#13;
    &#13;
    // コマンド実行&#13;
    new ActiveXObject("Shell.Application")&#13;
        .ShellExecute(cmd, cmd_args.join(' '), shell.CurrentDirectory, "runas");&#13;
    &#13;
} catch(e) {&#13;
    if(is_console) {&#13;
        WScript.StdErr.WriteLine(e);&#13;
        WScript.StdOut.Write('Enter キーで終了します. . . ');&#13;
        WScript.StdIn.ReadLine();&#13;
    } else {&#13;
        WScript.Echo(e);&#13;
    }&#13;
}&#13;
&lt;/textarea&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
キモは最後のほうにある「new ActiveXObject("Shell.Application").ShellExecute()」のところで、ここで第4引数に"runas"を与えると、エクスプローラのコンテキストメニューから「管理者として実行」を行ったことになる、という感じです。詳しくは以下のリンク先を参照。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="https://msdn.microsoft.com/ja-jp/library/windows/desktop/gg537745(v=vs.85).aspx" title="Shell.ShellExecute method (Windows)"&gt;Shell.ShellExecute method (Windows)&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ソース - sudo.cmd&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
sudoのバッチはこんな内容です。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;textarea readonly="readonly" style="background-color:#e5eed1;color:#223d05;font-family:'Courier New',monospace;font-size:12px;line-height:110%;overflow:auto;height:60px;width:97%;border:dashed 1px #555;margin-top:5px;padding:5px"&gt;@echo off&#13;
cscript //nologo "%~dP0\scripts\sudo.js" %*&#13;
&#13;
&lt;/textarea&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
バッチに渡された引数をそのままsudo.jsに丸投げしてるだけの簡単なつくりです。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ソース - su.cmd&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
suのバッチはこんな感じ。&#13;
&lt;p&gt;&#13;
&lt;textarea readonly="readonly" style="background-color:#e5eed1;color:#223d05;font-family:'Courier New',monospace;font-size:12px;line-height:110%;overflow:auto;height:60px;width:97%;border:dashed 1px #555;margin-top:5px;padding:5px"&gt;@echo off&#13;
cscript //nologo "%~dP0\scripts\sudo.js" cmd /k&#13;
exit&#13;
&#13;
&lt;/textarea&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
sudo.cmdでは引数をそのまま丸投げしてたところを、明示的に「cmd.exe /k」しています。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
あと、スクリプトを実行すると新しいプロンプトが開くので、なにも考えずに使ってるとコマンドプロンプトのウィンドウだらけになってウザいので最後にexitしてますが、これはお好みで削除してもよいでしょう。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
あ、それからsudo.js側で小技を入れているので、suした場合は元のディレクトリを引き継ぎます。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;使い道とか&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
suしてmklinkしてシンボリックリンクをバンバン作成するとか、hostsいじるのにsudo notepadするとか、まぁそんな感じでしょうか。&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>WSH</dc:subject>
      <dc:subject>コマンドプロンプト</dc:subject>
    </item>
    <item>
      <title>即吊ブックマークレット改善版</title>
      <link>http://dara-j.asablo.jp/blog/2015/05/26/7656250</link>
      <guid>http://dara-j.asablo.jp/blog/2015/05/26/7656250</guid>
      <pubDate>Tue, 26 May 2015 20:48:50 +0900</pubDate>
      <dcterms:modified>2015-05-26T20:53:49+09:00</dcterms:modified>
      <dcterms:created>2015-05-26T20:49:51+09:00</dcterms:created>
      <description>&lt;h3&gt;iOSでうまくいかなかったので…&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="/blog/2015/05/21/7638061"&gt;前のエントリ&lt;/a&gt;に載せたブックマークレットはソースが長すぎてiCloudで同期できなくてiOSでの動作確認もままならなかったので、意地になって改善しました。なんとか使い物になるかなぁ、と。&#13;
&lt;/p&gt;&#13;
&lt;h3&gt;改善版ブックマークレット&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;img src="http://www.ne.jp/asahi/dara-j/web/news_150526/sokutsuru20150526.png" style="width:480px"/&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="javascript:(function(f){var%20w=window,d=w.document,b=d.body,u=w.location.href,ex=function(){var%20a=Array.prototype.slice.call(arguments),d=(a.shift()||{}),s=(a.shift()||{});for(var%20p%20in%20s)d[p]=s[p];return%20a.length?ex.apply(null,[d].concat(a)):d},ct=function(n,a,s){var%20r=d.createElement(n);a&amp;&amp;ex(r,a);s&amp;&amp;ex(r.style,s);return%20r},to=w.setTimeout,end=function(e){to(function(){e.parentNode.removeChild(e)},100)},bd='solid%201px%20#999',ib='inline-block',rt='right',st={cm:{fontSize:'12px',lineHeight:1.2,fontFamily:'sans-serif',color:'#000',position:'static'},frm:{textAlign:'left',backgroundColor:'#fff',position:'fixed',width:'318px',padding:'0',top:0,right:0,zIndex:0xffff,border:bd},ttl:{textAlign:'center',fontWeight:900,fontSize:'16px',margin:'2px',backgroundColor:'#f9c',color:'#c71585'},hp:{display:'block',margin:'2px',color:'#f9c',textAlign:rt,border:'none'},text:{width:'235px',border:bd},lb:{width:'60px',marginRight:'5px',display:ib,textAlign:rt},btn:{width:'120px',margin:'10px',padding:'4px',border:bd,backgroundColor:'#eee',display:ib}},tr=function(a){var%20b=a.getElementsByTagName('input');for(var%20i=0,l=b.length;i&amp;lt;l;i++){var%20e=b[i];if((e.type=='text'&amp;&amp;!e.value.length)||(e.type=='checkbox'&amp;&amp;!e.checked)){e.disabled=true}}to(function(){a.submit();end(a)},0)},ps=function(e){var%20a='documentElement',ref=w[a]||d[a]||b;if(ref.clientWidth&amp;lt;480)ex(e.style,{left:0,right:null})},ap=function(e,c){e.appendChild(c);return%20e};b.appendChild((function(){var%20a='_blank',frm=ct('form',{method:'get',action:f,target:a,onsubmit:function(){tr(frm)}},ex({},st.cm,st.frm)),ttl=ct('div',{innerHTML:'S.K.T.R'},ex({},st.cm,st.ttl)),hp=ct('a',{href:'http://drinker.slfeed.net/archive/requestparameter.php',innerHTML:'help',target:a},ex({},st.cm,st.hp)),_t='text',_c='checkbox';ap(ap(frm,ttl),hp);var%20b=[ct('input',{type:_t,name:'url',value:u,readonly:'readonly'}),ct('input',{type:_t,name:'hashtag'}),ct('input',{type:_c,name:'images',value:'all'}),ct('input',{type:_t,name:_t}),(function(){if(!/^https:\/\/(m.+\.)?twitter\.com/.test(u))return%20null;return%20ct('input',{type:_c,name:'reply',value:'1'})})(),ct('input',{type:_t,name:'status'}),ct('input',{type:_c,name:'terminal',value:1}),ct('input',{type:_c,name:'mention',value:1}),ct('input',{type:_t,name:'callback'})];for(var%20i=0,l=b.length;i&amp;lt;l;i++){var%20c=b[i],d=null;ln=ct('div',{},{margin:'2px'});if(!c)continue;ex(c.style,st.cm,st[c.type]||{});var%20d=ct('span',{innerHTML:c.name},ex({},st.cm,st.lb));ap(ap(ln,d),c);ap(frm,ln)}ln=ct('div');ex(ln.style,{margin:'5px',textAlign:'center'});ap(frm,ln);var%20e=ct('button',{type:'submit',innerHTML:'GO'},ex({},st.cm,st.btn,{borderColor:'#555'}));ap(ln,e);e=ct('a',{innerHTML:'cancel',href:'#',onclick:function(){end(frm);return%20false}},ex({},st.cm,st.btn));ap(ln,e);ps(frm);return%20frm})())})('http://drinker.slfeed.net/archive/')" onclick="prompt('S.K.R.T', decodeURIComponent(this.href));return false" title="これをブックマークツールバーにドラッグドロップするか、クリックで表示されるソースをコピーして使ってね"&gt;即吊ダイアログ[改]&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
デスクトップブラウザなら↑のリンクをブックマークツールバーにドラッグドロップしてください。リンクをクリックするとpromptでjavascript:なURLを表示するので、スマートフォンやらタブレットの場合はこれをコピーした上で適当なページをブックマーク、編集で貼り付けてください。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ソース&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
こんな感じです。ブックマークレットにするにあたってはこのソースを&lt;a class="external_link" href="http://dean.edwards.name/packer/"&gt;packer&lt;/a&gt;で圧縮して&amp;lt;をエスケープしています。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;textarea readonly="readonly" style="background-color:#e5eed1;color:#223d05;font-family:'Courier New',monospace;font-size:12px;line-height:110%;overflow:auto;height:600px;width:97%;border:dashed 1px #555;margin-top:5px;padding:5px"&gt;(function(act){&#13;
  var&#13;
    w = window,&#13;
    d = w.document,&#13;
    b = d.body,&#13;
    u = w.location.href,&#13;
    ex = function() {&#13;
      var&#13;
        a = Array.prototype.slice.call(arguments),&#13;
        d = (a.shift() || {}),&#13;
        s = (a.shift() || {});&#13;
      for(var p in s) d[p] = s[p];&#13;
      return a.length ? ex.apply(null, [d].concat(a)) : d;&#13;
    },&#13;
    ct = function(n, a, s) {&#13;
      var r = d.createElement(n);&#13;
      a &amp;&amp; ex(r, a);&#13;
      s &amp;&amp; ex(r.style, s);&#13;
      return r;&#13;
    },&#13;
    to = w.setTimeout,&#13;
    end = function(e) {&#13;
      to(function() {&#13;
        e.parentNode.removeChild(e);&#13;
      }, 100);&#13;
    },&#13;
    bd = 'solid 1px #999', ib = 'inline-block', rt = 'right',&#13;
    st = {&#13;
      cm : {&#13;
        fontSize : '12px',&#13;
        lineHeight : 1.2,&#13;
        fontFamily : 'sans-serif',&#13;
        color : '#000',&#13;
        position: 'static'&#13;
      },&#13;
      frm : {&#13;
        textAlign : 'left',&#13;
        backgroundColor : '#fff',&#13;
        position : 'fixed',&#13;
        width : '318px',&#13;
        padding : '0',&#13;
        top : 0,&#13;
        right : 0,&#13;
        zIndex : 0xffff,&#13;
        border : bd&#13;
      },&#13;
      ttl : {&#13;
        textAlign : 'center',&#13;
        fontWeight : 900,&#13;
        fontSize : '16px',&#13;
        margin : '2px',&#13;
        backgroundColor : '#f9c',&#13;
        color : '#c71585'&#13;
      },&#13;
      hp : {&#13;
        display : 'block',&#13;
        margin : '2px',&#13;
        color : '#f9c',&#13;
        textAlign : rt,&#13;
        border : 'none'&#13;
      },&#13;
      text : {&#13;
        width : '235px',&#13;
        border : bd&#13;
      },&#13;
      lb : {&#13;
        width : '60px',&#13;
        marginRight : '5px',&#13;
        display : ib,&#13;
        textAlign : rt&#13;
      },&#13;
      btn : {&#13;
        width : '120px',&#13;
        margin : '10px',&#13;
        padding : '4px',&#13;
        border : bd,&#13;
        backgroundColor : '#eee',&#13;
        display : ib&#13;
      }&#13;
    },&#13;
    tr = function(frm) {&#13;
      var ls = frm.getElementsByTagName('input');&#13;
      for(var i=0, l = ls.length; i&amp;lt;l; i++) {&#13;
        var e = ls[i];&#13;
        if((e.type=='text' &amp;&amp; !e.value.length) || (e.type == 'checkbox' &amp;&amp; !e.checked)) {&#13;
          e.disabled = true;&#13;
        }&#13;
      }&#13;
      to(function() {&#13;
        frm.submit();&#13;
        end(frm)&#13;
      }, 0);&#13;
    },&#13;
    ps = function(e) {&#13;
      var de = 'documentElement', ref = w[de] || d[de] || b;&#13;
      if(ref.clientWidth &amp;lt; 480) ex(e.style, { left : 0, right : null });&#13;
    },&#13;
    ap = function(e, c) { e.appendChild(c); return e };&#13;
  b.appendChild((function() {&#13;
    var bk = '_blank',&#13;
      frm = ct('form',&#13;
          {&#13;
            method : 'get',&#13;
            action : act,&#13;
            target : bk,&#13;
            onsubmit : function() { tr(frm) }&#13;
          },&#13;
          ex({}, st.cm, st.frm)),&#13;
      ttl = ct('div',&#13;
          {&#13;
            innerHTML : 'S.K.T.R'&#13;
          },&#13;
          ex({}, st.cm, st.ttl)),&#13;
      hp = ct('a',&#13;
          {&#13;
            href : 'http://drinker.slfeed.net/archive/requestparameter.php',&#13;
            innerHTML : 'help',&#13;
            target : bk&#13;
          },&#13;
          ex({}, st.cm, st.hp)),&#13;
      _t = 'text', _c = 'checkbox';&#13;
    ap(ap(frm, ttl), hp);&#13;
    var its = [&#13;
      ct('input', {&#13;
        type : _t,&#13;
        name : 'url',&#13;
        value : u,&#13;
        readonly : 'readonly'&#13;
      }),&#13;
      ct('input', {&#13;
        type : _t,&#13;
        name : 'hashtag'&#13;
      }),&#13;
      ct('input', {&#13;
        type : _c,&#13;
        name : 'images',&#13;
        value : 'all'&#13;
      }),&#13;
      ct('input', {&#13;
        type : _t,&#13;
        name : _t&#13;
      }),&#13;
      (function(){&#13;
        if(!/^https:\/\/(m.+\.)?twitter\.com/.test(u)) return null;&#13;
        return ct('input', {&#13;
              type : _c,&#13;
              name : 'reply',&#13;
              value : '1'&#13;
            });&#13;
      })(),&#13;
      ct('input', {&#13;
        type : _t,&#13;
        name : 'status'&#13;
      }),&#13;
      ct('input', {&#13;
        type : _c,&#13;
        name : 'terminal',&#13;
        value : 1&#13;
      }),&#13;
      ct('input', {&#13;
        type : _c,&#13;
        name : 'mention',&#13;
        value : 1&#13;
      }),&#13;
      ct('input', {&#13;
        type : _t,&#13;
        name : 'callback'&#13;
      })&#13;
    ];&#13;
    for(var i = 0, l = its.length; i &amp;lt; l; i++) {&#13;
      var&#13;
        im = its[i],&#13;
        lb = null;&#13;
        ln = ct('div', {}, { margin : '2px' });&#13;
      if(!im) continue;&#13;
      ex(im.style, st.cm, st[im.type] || {});&#13;
      var lb = ct('span', { innerHTML : im.name }, ex({}, st.cm, st.lb));&#13;
      ap(ap(ln, lb), im);&#13;
      ap(frm, ln);&#13;
    }&#13;
    ln = ct('div');&#13;
    ex(ln.style, {margin : '5px', textAlign : 'center' });&#13;
    ap(frm, ln);&#13;
    &#13;
    var btn = ct('button', {&#13;
        type : 'submit',&#13;
        innerHTML : 'GO'&#13;
      },&#13;
      ex({}, st.cm, st.btn, { borderColor : '#555' }));&#13;
    ap(ln, btn);&#13;
    &#13;
    btn = ct('a', {&#13;
        innerHTML : 'cancel',&#13;
        href : '#',&#13;
        onclick : function() { end(frm);return false }&#13;
      },&#13;
      ex({}, st.cm, st.btn));&#13;
    ap(ln, btn);&#13;
    &#13;
    ps(frm);&#13;
    return frm;&#13;
  })())&#13;
})('http://drinker.slfeed.net/archive/')&#13;
&lt;/textarea&gt;&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>web</dc:subject>
    </item>
    <item>
      <title>即吊ブックマークレット</title>
      <link>http://dara-j.asablo.jp/blog/2015/05/21/7638061</link>
      <guid>http://dara-j.asablo.jp/blog/2015/05/21/7638061</guid>
      <pubDate>Thu, 21 May 2015 01:35:49 +0900</pubDate>
      <dcterms:modified>2015-05-26T20:51:48+09:00</dcterms:modified>
      <dcterms:created>2015-05-21T01:36:47+09:00</dcterms:created>
      <description>&lt;h3&gt;またの名を「ソク吊嵐」&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="http://drinker.slfeed.net/archive/" title="即吊☆キャプチャー|WEBキャプチャーをTwitterに投稿しちゃうアプリケーション"&gt;即吊☆キャプチャー|WEBキャプチャーをTwitterに投稿しちゃうアプリケーション&lt;/a&gt; ってなサイトがあってですな。サイトの画面をキャプチャしてさくっとTwitterに投げ込むわけですよ。いたく便利で。&#13;
&lt;/p&gt;&#13;
&lt;blockquote cite="http://drinker.slfeed.net/archive/post.php" title="即吊☆キャプチャー"&gt;&#13;
投稿するキャプチャー画像にコメント、ハッシュタグを入れる。特定のツイートにリプライするなど出来ます。&#13;
&lt;div style="text-align:right"&gt;&#13;
&lt;cite&gt;&lt;a class="external_link" href="http://drinker.slfeed.net/archive/post.php" title="即吊☆キャプチャー"&gt;即吊☆キャプチャー&lt;/a&gt;&lt;/cite&gt;&#13;
&lt;/div&gt;&#13;
&lt;/blockquote&gt;&#13;
&#13;
&lt;h3&gt;勢いです。勢い。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="http://drinker.slfeed.net/archive/requestparameter.php"&gt;オプションもいろいろ&lt;/a&gt;あって、&lt;a class="external_link" href="http://drinker.slfeed.net/archive/post.php"&gt;ブックマークレットも用意されて&lt;/a&gt;るんだけども、prompt()連発のウィザード形式で、少々戸惑っちゃうんですわ。すぐに慣れるんだけども。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
そこでなんとなく勢いでダイアログベースのブックマークレットを作ってみたわけなんですわ。ええ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="javascript:(function(act){var%20w=window,d=w.document,u=w.location.href,ex=function(){var%20args=Array.prototype.slice.call(arguments),ds=(args.shift()||{}),sr=(args.shift()||{});for(var%20p%20in%20sr){ds[p]=sr[p]}return%20args.length?ex.apply(null,[ds].concat(args)):ds;},dc=function(n){return%20d.createElement(n);},esc=function(s)%20{return%20s.replace(/&amp;amp;/g,'&amp;amp;amp;').replace(/&amp;lt;/g,'&amp;amp;lt;').replace(/&amp;gt;/g,'&amp;amp;gt;').replace(/&amp;apos;/g,'&amp;amp;apos;').replace(/&amp;quot;/g,'&amp;amp;quot;');},term=function(e){setTimeout(function(){e.parentNode.removeChild(e);},100)},st={d:{fontSize:'14px',lineHeight:1.4},fm:{textAlign:'left',backgroundColor:'#fff',color:'#000',position:'absolute',width:'600px',padding:'10px',top:0,right:0,zIndex:9999,border:'solid%201px%20#999'},ttl:{textAlign:'center',fontWeight:'bold',fontSize:'20px',margin:'-5px%20-5px%205px%20-5px',backgroundColor:'#f9c',color:'#c71585'},txt:{width:'360px',border:'solid%201px%20#999'},lbl:{width:'195px',marginRight:'5px',display:'inline-block',textAlign:'right'},btn:{width:'150px',margin:'5px%205px%200%205px',padding:'4px%2010px',border:'solid%201px%20#666',backgroundColor:'#eee'}},trimFields=function(fm){for(var%20ls=fm.getElementsByTagName('input'),i=0,l=ls.length;i&amp;lt;l;i++){if((ls[i].type=='text'&amp;amp;&amp;amp;!ls[i].value.length)||(ls[i].type=='checkbox'&amp;amp;&amp;amp;!ls[i].checked)){ls[i].disabled=true;}}setTimeout(function(){fm.submit();term(fm)},0)};d.body.appendChild((function(){var%20fm=ex(dc('form'),%20{method:'get',action:act,target:'_blank',onsubmit:function(){trimFields(fm)}}),title=ex(dc('div'),{innerHTML:esc('%E3%82%BD%E3%82%AF%E5%90%8A%E5%B5%90%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AD%E3%82%B0')}),btn=null;ex(fm.style,st.d,st.fm);ex(title.style,st.d,st.ttl);fm.appendChild(title);var%20items=[{lbl:'%E5%90%8A%E3%82%8BURL',ttl:'%E5%8D%B3%E5%90%8A%E3%81%97%E3%81%9F%E3%81%84URL%E3%82%92%E5%85%A5%E3%82%8C%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%EF%BC%88%E5%BF%85%E9%A0%88%E3%81%A7%E3%81%99%E3%80%82%EF%BC%89',ele:ex(dc('input'),{type:'text',name:'url',value:u,readonly:'readonly'})},{lbl:'%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%B0',ttl:'%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%82%BF%E3%82%B0%E3%82%92%E4%BB%98%E3%81%91%E3%81%BE%E3%81%99%E3%80%82%E5%85%A8%E8%A7%92%E5%8D%8A%E8%A7%92%E7%A9%BA%E7%99%BD%E3%80%81%E3%82%AB%E3%83%B3%E3%83%9E%E3%81%A7%E5%A4%9A%E9%87%8D%E3%81%AB%E4%BB%98%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82',ele:ex(dc('input'),{type:'text',name:'hashtag'})},{lbl:'%E3%82%B5%E3%82%A4%E3%83%88%E5%85%A8%E4%BD%93%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3%E3%82%92%E8%A9%A6%E8%A1%8C',ttl:'all%E3%81%A8%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B%E3%81%A8%E5%87%BA%E6%9D%A5%E3%82%8B%E9%99%90%E3%82%8AWEB%E3%82%B5%E3%82%A4%E3%83%88%E5%85%A8%E4%BD%93%E3%82%92%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3%E3%83%BC%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E9%A0%91%E5%BC%B5%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82',ele:ex(dc('input'),{type:'checkbox',name:'images',value:'all'})},{lbl:'%E8%BF%BD%E5%8A%A0%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88',ttl:'%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E3%82%92%E4%BB%98%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E5%87%BA%E6%9D%A5%E3%81%BE%E3%81%99%E3%80%82',ele:ex(dc('input'),{type:'text',name:'text'})},(function(){if(!/^https:\/\/twitter\.com/.test(u))return%20{};return%20{lbl:'%E3%81%93%E3%81%AE%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%81%AB%E3%83%AA%E3%83%97%E3%83%A9%E3%82%A4',ttl:'1%E3%81%A8%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B%E3%81%A8%E5%90%8A%E3%82%8B%E3%82%B5%E3%82%A4%E3%83%88%E3%81%8C%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%81%AA%E3%82%89%E3%81%B0%E3%80%81%E3%81%9D%E3%81%AE%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%81%AB.@%E3%81%A7%E3%83%AA%E3%83%97%E3%83%A9%E3%82%A4%E3%82%92%E4%BB%98%E3%81%91%E3%81%A6%E6%8A%95%E7%A8%BF%E3%81%97%E3%81%BE%E3%81%99%E3%80%82',ele:ex(dc('input'),{type:'checkbox',name:'reply',value:'1'})};})(),{lbl:'%E8%BF%94%E4%BF%A1%E5%85%83%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88URL',ttl:'%E5%90%8A%E3%82%8B%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E7%8B%99%E3%81%A3%E3%81%9F%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%81%AB.@%E3%81%A7%E3%83%AA%E3%83%97%E3%83%A9%E3%82%A4%E3%82%92%E4%BB%98%E3%81%91%E3%81%A6%E6%8A%95%E7%A8%BF%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%EF%BC%88%E3%83%84%E3%82%A4%E3%83%BC%E3%83%88%E3%81%AEURL%E5%85%A5%E3%82%8C%E3%81%A6%E3%81%AD%E3%80%82%EF%BC%89',ele:ex(dc('input'),{type:'text',name:'status'})},{lbl:'%E8%81%B7%E5%A0%B4%E3%83%A2%E3%83%BC%E3%83%89',ttl:'1%E3%81%A8%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B%E3%81%A8%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E9%A2%A8CSS%E3%83%A2%E3%83%BC%E3%83%89%E3%81%A7%E6%8A%95%E7%A8%BF%E3%81%97%E3%81%BE%E3%81%99%E3%80%82%E3%81%8A%E4%BB%95%E4%BA%8B%E5%A0%B4%E3%81%A7%E3%82%82%E6%81%A5%E3%81%9A%E3%81%8B%E3%81%97%E3%81%8F%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82%E3%81%8B%E3%82%82',ele:ex(dc('input'),{type:'checkbox',name:'terminal',value:'1'})},{lbl:'%E8%87%AA%E5%88%86%E3%81%AB%E3%83%8A%E3%83%AB%E3%83%88',ttl:'1%E3%81%A8%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B%E3%81%A8%E3%83%94%E3%83%AA%E3%82%AA%E3%83%89%E7%84%A1%E3%81%97%E3%81%AE@%E3%81%A7%E3%81%93%E3%81%A3%E3%81%9D%E3%82%8A%E9%AD%9A%E6%8B%93%E3%81%97%E3%81%9F%E3%81%AE%E3%82%92%E8%87%AA%E5%88%86%E3%81%AB%E5%90%91%E3%81%91%E3%81%A6%E3%83%A1%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%97%E3%81%BE%E3%81%99%E3%80%82',ele:ex(dc('input'),{type:'checkbox',name:'mention',value:'1'})},{lbl:'%E6%88%BB%E3%82%8A%E5%85%88',ttl:'%E5%90%8A%E3%82%8A%E7%B5%82%E3%82%8F%E3%81%A3%E3%81%9F%E3%82%89%E9%A3%9B%E3%81%B3%E3%81%9F%E3%81%84URI%E3%81%AB%E3%82%92%E5%85%A5%E3%82%8C%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82%E3%83%9A%E3%83%BC%E3%82%B8%E5%87%BA%E5%8A%9B%E5%89%8D%E3%81%AB%E3%83%9A%E3%83%BC%E3%82%B8%E9%81%B7%E7%A7%BB%E3%81%97%E3%81%A1%E3%82%83%E3%81%86%E3%81%AE%E3%81%A7%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E5%8B%95%E4%BD%9C%E3%81%8C%E6%97%A9%E3%81%84%E3%81%A7%E3%81%99%E3%81%8C%EF%BC%9E%EF%BC%9C',ele:ex(dc('input'),{type:'text',name:'callback'})}];for(var%20i=0,l=items.length,item=items[i],lbl;i&lt;l;i++,item=items[i]){var%20ln=dc('div');ex(ln.style,{margin:'3px%200'});if('lbl'%20in%20item){lbl=ex(dc('span'),{innerHTML:esc(item.lbl)});ex(lbl.style,st.d,st.lbl);ln.appendChild(lbl);}if(('ttl'%20in%20item)&amp;amp;&amp;amp;lbl){ex(lbl,{'title':item.ttl});}if('ele'%20in%20item){if(item.ele.type=='text'){ex(item.ele.style,st.d,st.txt);}ln.appendChild(item.ele);}fm.appendChild(ln);}ln=dc('div');ex(ln.style,{marginTop:'10px',borderTop:'solid%201px%20#ccc'});ex(ln.style,{marginTop:'10px',textAlign:'center'});fm.appendChild(ln);btn=ex(dc('button'),{type:'submit',innerHTML:esc('%E5%90%8A%E3%82%8B%EF%BC%81')});ex(btn.style,st.d,st.btn);ln.appendChild(btn);btn=ex(dc('button'),{type:'button',innerHTML:esc('%E3%82%84%E3%82%81%E3%82%8B'),onclick:function(){term(fm)}});ex(btn.style,st.d,st.btn);ln.appendChild(btn);return%20fm;})())})('http://drinker.slfeed.net/archive/')" onclick="prompt('src',unescape(this.href));return false" title="これをブックマークツールバーにドラッグドロップするか、クリックで表示されるソースをコピーして使ってね"&gt;即吊ダイアログ&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;b style="color:red"&gt;※：2015.5.25 ダイアログにスタイル適用したり、実験中パラメータ「callback」に対応したりで更新しました。&lt;/b&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;b style="color:red"&gt;※：2015.5.26 ブックマークレットのURIが長すぎるせいか、iCloudでの同期がうまくいきません＆iOSだとうまく動かないかも。&lt;/b&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;b style="color:red"&gt;→ &lt;a href="/blog/2015/05/26/7656250"&gt;iCloudで同期できるサイズまで小さくしてiOS 8で動作するバージョンを作成&lt;/a&gt;しました。&lt;/b&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;p&gt;&#13;
吊りたいページでブックマークレットを起動するとこんなダイアログが出ます。&#13;
&lt;img src="http://www.ne.jp/asahi/dara-j/web/news_150521/sokutsuru20150525.png" style="width:480px"/&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
Firefox 38とChrome 42（どちらもWindows）でしか試してないし、オプションも追加コメントとお仕事場モードくらいしか試してないんだけども、まぁ一応使えるのではないかと。サイトによってはレイアウト崩れたりいろいろ問題ありそうだけども。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
中身はこんな感じ（雑です）。&#13;
&lt;pre&gt;&#13;
(function(act){&#13;
  var w=window,&#13;
    d=w.document,&#13;
    u=w.location.href,&#13;
    ex=function(){&#13;
      var args=Array.prototype.slice.call(arguments),ds=(args.shift()||{}),sr=(args.shift()||{});&#13;
      for(var p in sr){&#13;
        ds[p]=sr[p]&#13;
      }&#13;
      return args.length?ex.apply(null,[ds].concat(args)):ds;&#13;
    },&#13;
    dc=function(n){&#13;
      return d.createElement(n);&#13;
    },&#13;
    esc=function(s) {&#13;
      return s&#13;
        .replace(/&amp;amp;/g,'&amp;amp;amp;')&#13;
        .replace(/&amp;lt;/g,'&amp;amp;lt;')&#13;
        .replace(/&amp;gt;/g,'&amp;amp;gt;')&#13;
        .replace(/'/g,'&amp;amp;apos;')&#13;
        .replace(/"/g,'&amp;amp;quot;');&#13;
    },&#13;
    term=function(e){&#13;
      setTimeout(function(){&#13;
        e.parentNode.removeChild(e);&#13;
      },100)&#13;
    },&#13;
    st={&#13;
      d:{&#13;
        fontSize:'14px',&#13;
        lineHeight:1.4&#13;
      },&#13;
      fm:{&#13;
        textAlign:'left',&#13;
        backgroundColor:'#fff',&#13;
        color:'#000',&#13;
        position:'absolute',&#13;
        width:'600px',&#13;
        padding:'10px',&#13;
        top:0,&#13;
        right:0,&#13;
        zIndex:9999,&#13;
        border:'solid 1px #999'&#13;
      },&#13;
      ttl:{&#13;
        textAlign:'center',&#13;
        fontWeight:'bold',&#13;
        fontSize:'20px',&#13;
        margin:'-5px -5px 5px -5px',&#13;
        backgroundColor:'#f9c',&#13;
        color:'#c71585'&#13;
      },&#13;
      txt:{&#13;
        width:'360px',&#13;
        border:'solid 1px #999'&#13;
      },&#13;
      lbl:{&#13;
        width:'195px',&#13;
        marginRight:'5px',&#13;
        display:'inline-block',&#13;
        textAlign:'right'&#13;
      },&#13;
      btn:{&#13;
        width:'150px',&#13;
        margin:'5px 5px 0 5px',&#13;
        padding:'4px 10px',&#13;
        border:'solid 1px #666',&#13;
        backgroundColor:'#eee'&#13;
      }&#13;
    },&#13;
    trimFields=function(fm){&#13;
      for(var ls=fm.getElementsByTagName('input'),i=0,l=ls.length;i&amp;lt;l;i++){&#13;
        if((ls[i].type=='text'&amp;amp;&amp;amp;!ls[i].value.length)||(ls[i].type=='checkbox'&amp;amp;&amp;amp;!ls[i].checked)){&#13;
          ls[i].disabled=true;&#13;
        }&#13;
      }&#13;
      setTimeout(function(){fm.submit();term(fm)},0)&#13;
    };&#13;
  d.body.appendChild((function(){&#13;
    var fm=ex(dc('form'), {&#13;
        method:'get',&#13;
        action:act,&#13;
        target:'_blank',&#13;
        onsubmit:function(){trimFields(fm)}&#13;
      }),&#13;
      title=ex(dc('div'),{innerHTML:esc('ソク吊嵐ダイアログ')}),&#13;
      btn=null;&#13;
    ex(fm.style,st.d,st.fm);&#13;
      ex(title.style,st.d,st.ttl);&#13;
    fm.appendChild(title);&#13;
    var items=[&#13;
      {lbl:'吊るURL',ttl:'即吊したいURLを入れてください（必須です。）',ele:ex(dc('input'),{type:'text',name:'url',value:u,readonly:'readonly'})},&#13;
      {lbl:'ハッシュタグ',ttl:'ハッシュタグを付けます。全角半角空白、カンマで多重に付けることができます。',ele:ex(dc('input'),{type:'text',name:'hashtag'})},&#13;
      {lbl:'サイト全体キャプチャを試行',ttl:'allとリクエストすると出来る限りWEBサイト全体をキャプチャーしようと頑張ります。',ele:ex(dc('input'),{type:'checkbox',name:'images',value:'all'})},&#13;
      {lbl:'追加コメント',ttl:'コメントを付けることが出来ます。',ele:ex(dc('input'),{type:'text',name:'text'})},&#13;
      (function(){&#13;
        if(!/^https:\/\/twitter\.com/.test(u))return {};&#13;
        return {lbl:'このツイートにリプライ',ttl:'1とリクエストすると吊るサイトがツイートならば、そのツイートに.@でリプライを付けて投稿します。',ele:ex(dc('input'),{type:'checkbox',name:'reply',value:'1'})};&#13;
      })(),&#13;
      {lbl:'返信元ツイートURL',ttl:'吊るサイトを狙ったツイートに.@でリプライを付けて投稿します。（ツイートのURL入れてね。）',ele:ex(dc('input'),{type:'text',name:'status'})},&#13;
      {lbl:'職場モード',ttl:'1とリクエストするとターミナル風CSSモードで投稿します。お仕事場でも恥ずかしくありません。かも',ele:ex(dc('input'),{type:'checkbox',name:'terminal',value:'1'})},&#13;
      {lbl:'自分にナルト',ttl:'1とリクエストするとピリオド無しの@でこっそり魚拓したのを自分に向けてメンションします。',ele:ex(dc('input'),{type:'checkbox',name:'mention',value:'1'})},&#13;
      {lbl:'戻り先',ttl:'吊り終わったら飛びたいURIにを入れてください。ページ出力前にページ遷移しちゃうのでちょっと動作が早いですが＞＜',ele:ex(dc('input'),{type:'text',name:'callback'})}&#13;
    ];&#13;
    for(var i=0,l=items.length,item=items[i],lbl;i&amp;lt;l;i++,item=items[i]){&#13;
      var ln=dc('div');ex(ln.style,{margin:'3px 0'});&#13;
      if('lbl' in item){&#13;
        lbl=ex(dc('span'),{innerHTML:esc(item.lbl)});&#13;
        ex(lbl.style,st.d,st.lbl);&#13;
        ln.appendChild(lbl);&#13;
      }&#13;
      if(('ttl' in item)&amp;amp;&amp;amp;lbl){&#13;
        ex(lbl,{'title':item.ttl});&#13;
      }&#13;
      if('ele' in item){&#13;
        if(item.ele.type=='text'){&#13;
          ex(item.ele.style,st.d,st.txt);&#13;
        }&#13;
        ln.appendChild(item.ele);&#13;
      }&#13;
      fm.appendChild(ln);&#13;
    }&#13;
    ln=dc('div');ex(ln.style,{marginTop:'10px',borderTop:'solid 1px #ccc'});&#13;
    ex(ln.style,{marginTop:'10px',textAlign:'center'});&#13;
    fm.appendChild(ln);&#13;
    btn=ex(dc('button'),{type:'submit',innerHTML:esc('吊る！')});ex(btn.style,st.d,st.btn);&#13;
    ln.appendChild(btn);&#13;
    btn=ex(dc('button'),{type:'button',innerHTML:esc('やめる'),onclick:function(){term(fm)}});ex(btn.style,st.d,st.btn);&#13;
    ln.appendChild(btn);&#13;
    return fm;&#13;
  })())&#13;
})('http://drinker.slfeed.net/archive/')&#13;
&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>web</dc:subject>
    </item>
    <item>
      <title>tumblrのキーボードショートカットが便利になっとる。</title>
      <link>http://dara-j.asablo.jp/blog/2012/10/17/6605357</link>
      <guid>http://dara-j.asablo.jp/blog/2012/10/17/6605357</guid>
      <pubDate>Wed, 17 Oct 2012 21:41:27 +0900</pubDate>
      <dcterms:modified>2012-10-17T21:42:12+09:00</dcterms:modified>
      <dcterms:created>2012-10-17T21:42:12+09:00</dcterms:created>
      <description>&lt;h3&gt;すんごい久しぶりにtumblrのことなど&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;b&gt;それ以前にブログ更新するのがすんごい久しぶり&lt;/b&gt;、ってのは置いておいて。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
いまだにメインブラウザがFirefoxなもので、tumblrのダッシュボード向けに、執念深く古いグリモン＋Minibuffer＋LDRize＋Autopagerizeという環境で回しているんだけども、最近ふと気が付いたらダッシュボードでjした時に「カクッ」と動くようになってることに気付いた。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;いつのまにか標準キーバインドが復活しとる&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
結構前からダッシュボードには、標準でキーバインドが組み込まれてて、使いづらいので&#13;
&lt;a class="external_link" href="http://otsune.tumblr.com/post/144605866/dara-j-otsune-dara-j"&gt;これをキャンセルするグリモンスクリプト&lt;/a&gt;を組み込んでたんだけど、どうやらこれが効かなくなったらしい。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="http://dara-j.tumblr.com/post/33360830000/tumblr-enable-dashboard-key-commands"&gt;何日か前にこれに気付いて、なんとかキャンセルできるようにした&lt;/a&gt;んだが、今日になったらまたコードが効かなくなってた。矢継ぎ早なアップデートみたい。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;なんとか解除してみる&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
仕方ないのでまたJSのデバッグコンソールをごにょごにょいじって調べたところ、いつの間にやら&lt;b&gt;キーバインドを処理するための Tumblr.KeyCommands なるオブジェクト&lt;/b&gt;が加わってて、これが &lt;a class="external_link" href="http://dara-j.tumblr.com/post/33765464069"&gt;suspended プロパティ&lt;/a&gt;やら、suspend() メソッドなんかが実装されてることが分かったので、ためしにグリモンで&#13;
&lt;pre&gt;&#13;
unsafeWindow.Tumblr.KeyCommands.suspend();&#13;
&lt;/pre&gt;&#13;
なんてやってみたら見事にキャンセルできた。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ところで、標準キーバインドってなにができるん？&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
KeyCommands 周りを調べてる過程で気づいたんだけど、&lt;b&gt;「like」とか「reblog」、「notes」、「play」なんて興味深いメソッドが実装されてて&lt;/b&gt;興味が出たので、どんなキー操作ができるのかを調べてみた。&lt;a class="external_link" href="http://dara-j.tumblr.com/post/33766000287/dashboard-2012-10-17"&gt;tumblrのほうにエントリ挙げた&lt;/a&gt;けどあんまり見やすくないので、以下にもう一度まとめておく。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;table cellpadding="1" cellspacing="2" border="1"&gt;&#13;
&lt;tbody&gt;&#13;
	&lt;tr&gt;&lt;th&gt;j（ジェイ）&lt;/th&gt;&lt;td&gt;次のpostへ移動&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;k（ケー）&lt;/th&gt;&lt;td&gt;前のpostへ移動&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;l（エル）&lt;/th&gt;&lt;td&gt;like / like解除&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;n（エヌ）&lt;/th&gt;&lt;td&gt;notesを開く / 閉じる&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;r（アール）&lt;/th&gt;&lt;td&gt;reblog（別ウィンドウが開く）&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;R（Shift＋アール）&lt;/th&gt;&lt;td&gt;即時reblog&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;E（Shift＋イー）&lt;/th&gt;&lt;td&gt;キュー（投稿予約）へreblog&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;スペース&lt;/th&gt;&lt;td&gt;動画再生？（未確認）&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;カーソルキー左&lt;/th&gt;&lt;td&gt;前のページへ&lt;/td&gt;&lt;/tr&gt;&#13;
	&lt;tr&gt;&lt;th&gt;カーソルキー右&lt;/th&gt;&lt;td&gt;次のページへ&lt;/td&gt;&lt;/tr&gt;&#13;
&lt;/tbody&gt;&#13;
&lt;/table&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;謎の処理もあるんだけども&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
この他に修飾キー（Windowsの場合はWindowsキー、Macの場合はoptionキーと思われる）を押しながら以下のkeyCodeでTumblr.blog_switcher()という処理を呼び出してるみたい。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;table cellpadding="1" cellspacing="1" border="1"&gt;&#13;
&lt;tbody&gt;&#13;
	&lt;tr&gt;&#13;
		&lt;th&gt;Windows&lt;/th&gt;&#13;
		&lt;td&gt;9（Tab）、27（Esc）、192（？？？）&lt;/td&gt;&#13;
	&lt;/tr&gt;&#13;
	&lt;tr&gt;&#13;
		&lt;th&gt;Mac&lt;/th&gt;&#13;
		&lt;td&gt;9、27、192、37（カーソル左）、39（カーソル右）&lt;/td&gt;&#13;
	&lt;/tr&gt;&#13;
&lt;/tbody&gt;&#13;
&lt;/table&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
なんだけど、これが何をするのかよくわからんし、自分の環境ではなにも起きないので&lt;b&gt;とりあえず無視&lt;/b&gt;。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;標準キーバインドのほうが便利くさいので方針転換&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
先のキーバインドの機能、大体はこれまでのグリモン環境でもできてたことなんだけども、&lt;b&gt;即時reblog&lt;/b&gt;は自分の環境ではできなかったので非常に魅力的。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ということで、www.tumblr.com ではMinibufferもLDRizeも外すことにして、標準キーバインドを使うようにするよう方針転換。ついでといってはなんだが、標準同士の組み合わせのほうが安定してるのは目に見えてるのでAutopagerizeも外して、settings/dashboard で「Enable endless scrolling」を有効に。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
標準のendless scrollingを有効にしたのでiPadで見る場合なんかはかえって便利になったりといううれしい誤算もあり、結構うれしかったり。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;でもちょっと手を入れないと&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
ただ、標準機能のままだとpostの移動が「カクッ」となっててこれはちょっと気持ち悪いのでなんとかならんかと調べたところ、 Tumblr.KeyCommands が「animate_scroll」というプロパティを持っていた。さっそくこれをtrueに設定したら案の定スムーズスクロールするようになって快適。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
また、animate_scroll = true の状態でも個人的にはちょっと速度が速いように感じられたので、一緒に見つけてた「scroll_speed」プロパティをデフォルトの100から150にしたら結構いい感じ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
これらの設定（どころか、キーバインドの有効/無効の切り替えすら）はtumblrの設定からいじれないので、ひとまず&#13;
&lt;pre&gt;&#13;
unsafeWindow.Tumblr.KeyCommands.animate_scroll = true;&#13;
unsafeWindow.Tumblr.KeyCommands.scroll_speed = 150;&#13;
&lt;/pre&gt;&#13;
みたいなグリモンスクリプトを作って対応。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;オマケ：ブックマークレットも作ってみたよ&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
いちいち起動しなきゃなんないのは面倒だけど、おんなじようなことを行うブックマークレットも作ってみた。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="javascript:(function(){if(Tumblr&amp;&amp;Tumblr.KeyCommands){with(Tumblr.KeyCommands){animate_scroll=true;scroll_speed=150}}})()" onclick="prompt('src',unescape(this.href));return false"&gt;スムーズスクロールを有効に&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
中身はこんな感じも。&#13;
&lt;pre&gt;&#13;
(function() {&#13;
    if(Tumblr &amp;&amp; Tumblr.KeyCommands) {&#13;
        with(Tumblr.KeyCommands) {&#13;
            animate_scroll = true;&#13;
            scroll_speed = 150&#13;
        }&#13;
    }&#13;
})()&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;
</description>
      <dc:subject>tumblr</dc:subject>
    </item>
    <item>
      <title>dataスキームの画像をブロックしてみる - Chrome編</title>
      <link>http://dara-j.asablo.jp/blog/2012/03/22/6384658</link>
      <guid>http://dara-j.asablo.jp/blog/2012/03/22/6384658</guid>
      <pubDate>Thu, 22 Mar 2012 03:52:25 +0900</pubDate>
      <dcterms:modified>2012-03-22T03:52:50+09:00</dcterms:modified>
      <dcterms:created>2012-03-22T03:52:50+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
&lt;a href="/blog/2012/03/22/6384656"&gt;前のエントリ&lt;/a&gt;の続きで、今度はGoogle Chrome行ってみよう。といっても、それほど書くことあるわけじゃないので比較的アッサリ気味の内容で。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
他にもいろいろあるんだけど、Firefoxでソースをざっくり眺めて馴染みがでたので、ターゲットは&lt;a class="external_link" href="https://chrome.google.com/webstore/detail/cfhdojbkjhnklbpkdaibdccddilifddb"&gt;Adblock Plus&lt;/a&gt;。現在タイトルに「(Beta)」がついてる1.2版です。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
こちらもFirefox版と同じく、単純に「data:image/*」みたいな登録をしてもフィルタリングされないので、またまたデバッグコードを仕掛けて調べてみることに。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
extensionのインストールされたディレクトリをざっと眺めてみたらmanifest.jsonてのがあったのでそちらを見てみる。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
manifest.jsonの内容から推測するに、メインで使用されるのはどうやら「contentScript2.js」らしいのでそちらを見てみたところ、beforeloadHandlerという関数からshouldBlock()にURLを渡して判断してるっぽいのでその辺りにデバッグコードを仕掛けて調べたら、dataスキームURIを相対URLとみなして、現在のドキュメントURLからの絶対URLに変換してた。こりゃ引っかからんわ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
コードにパッチ当てちゃってもいいんだけど、モノは試しで「http://*/*data:image/*」なんてフィルタ登録してみたら&lt;b&gt;あっさりうまくいっちゃった&lt;/b&gt;。まぁURLの途中に「:」を挟んだパターンがあったら誤爆する可能性もあるんだけど、とりあえずこれでいいか。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ただ、URLフィルタにマッチした場合でもHTTPでの通信そのものは発生しちゃうみたいで、それだったら「##img[src*="data:image"]」のほうが誤爆の恐れもないし安全かも。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
あ、あとcssでbackground-imageに指定してる場合なんかはブロックされないっぽいです。&#13;
&lt;/p&gt;
</description>
      <dc:subject>ブラウザ</dc:subject>
    </item>
    <item>
      <title>dataスキームの画像をブロックしてみる</title>
      <link>http://dara-j.asablo.jp/blog/2012/03/22/6384656</link>
      <guid>http://dara-j.asablo.jp/blog/2012/03/22/6384656</guid>
      <pubDate>Thu, 22 Mar 2012 03:06:18 +0900</pubDate>
      <dcterms:modified>2012-03-22T03:53:54+09:00</dcterms:modified>
      <dcterms:created>2012-03-22T03:07:27+09:00</dcterms:created>
      <description>&lt;h3&gt;面白いネタ、いただきました。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="http://blog.2maru.com/"&gt;にーまるどっとこむ&lt;/a&gt;（旧「&lt;a class="external_link" href="http://typex2.wordpress.com/"&gt;突然消失するかもしれないブログ&lt;/a&gt;」）の&lt;a class="external_link" href="https://twitter.com/#!/typex20"&gt;なかのきえた&lt;/a&gt;さんから、こんなメンションが飛んできた。&#13;
&lt;blockquote cite="https://twitter.com/#!/typex20/status/182136949254012928" title="Twitter / @typex20: @dara_j_ Adbloc PlusではData ..."&gt;&#13;
Adbloc PlusではData URIはフィルター対象に指定出来ないのですが、何か技術的に難しい理由があるのでしょうか？&#13;
&lt;div style="text-align:right"&gt;&#13;
&lt;cite&gt;&lt;a href="https://twitter.com/#!/typex20/status/182136949254012928" title="Twitter / @typex20: @dara_j_ Adbloc PlusではData ..."&gt;Twitter / @typex20: @dara_j_ Adbloc PlusではData ...&lt;/a&gt;&lt;/cite&gt;&#13;
&lt;/div&gt;&#13;
&lt;/blockquote&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="https://addons.mozilla.org/ja/firefox/addon/adblock-plus/"&gt;Adblock Plus&lt;/a&gt;はこれまで使ったことなかったんだけど、なんだかえらく興味をひかれたので調べてみることに。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;よくわからんが使ってしてみると&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
ちょっと調べたところ、Firefox用とChrome用があるみたいなんだけど、とりあえずFirefoxのほうを試してみる。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
まずはAdblock Plusをインストールし、適当にググってみたページなんかを参考にして見よう見まねで&#13;
&lt;pre&gt;&lt;code&gt;data:image/*&#13;
&lt;/code&gt;&lt;/pre&gt;&#13;
みたいな感じで登録、手持ちであったdataスキームで画像やらスクリプトを食わせているページを開いてみたが、なんの変化も見られない。ふむ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ドキュメント類もろくすっぽ読まずに機能拡張のソースコードを追っていき、&lt;a class="external_link" href="https://developer.mozilla.org/En/NsIContentPolicy"&gt;nsIContentPolicy&lt;/a&gt;というインターフェイスの実装を提供しているということがわかったので、&lt;a class="external_link" href="http://adblockplus.org/jsdoc/adblockplus/symbols/src/modules_ContentPolicy.jsm.html"&gt;ContentPolicy.jsmというモジュール&lt;/a&gt;のあちこちにデバッグコードをひっかけて調べたところ、&lt;b&gt;内部で持っているスキームのホワイトリストにマッチするので、URLの突き合わせが行われる前にブロックされないことが確定&lt;/b&gt;していると判明。さて、ホワイトリストはどこに持ってるんだ？&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ググってみると、あるもんだ。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
キーワードは失念したがググってみたところ、&lt;a class="external_link" href="http://adblockplus.org/en/preferences#whitelistschemes"&gt;adblockplus.orgのドキュメント&lt;/a&gt;が見つかった。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
これ見ると、どうやら「extensions.adblockplus.whitelistschemes」で値を持ってるみたい。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
さっそくabout:config開いて「adblockplus.whitelist」くらいでフィルタかけてみたらこんな感じで設定項目が見つかった。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a target="_blank" href="http://www.ne.jp/asahi/dara-j/web/2012_0322/img/about_config.png" title="クリックで大きいサイズを表示"&gt;&#13;
&lt;img src="http://www.ne.jp/asahi/dara-j/web/2012_0322/img/about_config-thumb.png" /&gt;&#13;
&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
なるほど、先のドキュメント通りに許可スキームをスペース区切りで持ってるので、"data"を取り除いてみることに。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;img src="http://www.ne.jp/asahi/dara-j/web/2012_0322/img/whitelistschemes.png" /&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
一旦ブラウザを再起動して再度dataスキームを使ったページにアクセスしてみたら、&lt;b&gt;こんどはちゃんと画像もスクリプトもロードされない&lt;/b&gt;！おお、やった。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;実はもっと簡単な方法があったのねん…&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
なんてとこまで調べたあたりで、&lt;a class="external_link" href="https://twitter.com/#!/typex20"&gt;なかのきえた&lt;/a&gt;さんからこんなツイートが。&#13;
&lt;blockquote cite="https://twitter.com/#!/typex20/status/182374444851920897" title="Twitter / @typex20: @dara_j_ これで消せたみたいですけど、これで ..."&gt;&#13;
これで消せたみたいですけど、これであってます？→「##img[src*="data:image"]」&#13;
&lt;div style="text-align:right"&gt;&#13;
&lt;cite&gt;&lt;a href="https://twitter.com/#!/typex20/status/182374444851920897" title="Twitter / @typex20: @dara_j_ これで消せたみたいですけど、これで ..."&gt;Twitter / @typex20: @dara_j_ これで消せたみたいですけど、これで ...&lt;/a&gt;&lt;/cite&gt;&#13;
&lt;/div&gt;&#13;
&lt;/blockquote&gt;&#13;
よくよく（よくよく、じゃなくても）調べてみたら、&lt;a class="external_link" href="http://d.hatena.ne.jp/k2jp/20090810/1249867823"&gt;ブロックリストの書き方を解説してるページ&lt;/a&gt;で詳しく解説されてるじゃない！&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
これはURLフィルタではなく、「非表示要素フィルタ」というものらしく、要素の属性に対してのマッチングパターンを記述できると。なんだ、&lt;b&gt;こっちのほうが圧倒的に簡単じゃん&lt;/b&gt;… orz&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ただ、負け惜しみじゃないんだけど、この書き方だと&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;画像の場合はimg要素で読み込んでいるものだけが対象、cssでbackground-imageなんかに指定してる場合はブロックできない&lt;/li&gt;&#13;
 &lt;li&gt;script要素には（表示もクソもないので）効果がない&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
という違いはありますが。えぇ、&lt;b&gt;負け惜しみじゃないですよ？&lt;/b&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ということで、サンプルページをば&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
作ってみました。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a target="_blank" href="http://www.ne.jp/asahi/dara-j/web/2012_0322/datascheme1.html"&gt;dataスキーム使ったサンプルページ&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
img要素で画像表示してるところと、cssでbackground-imageにdataスキーム指定してるところと両方あるので、「data:image/*」と「img[src*="data:image"]」のフィルタの違いをご堪能あれ。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;オマケ情報&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
URLフィルタ使う場合は、「data:*」みたいな乱暴な指定もできます。これだとcssだろうがscriptだろうがなんでもブロックできるっぽいです。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;次はChorme版だ。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
と思ったけど、ちょっと記事が長くなったので別エントリを起こす予定です。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;追記&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="/blog/2012/03/22/6384658"&gt;Chrome編&lt;/a&gt;、簡単に書きました。&#13;
&lt;/p&gt;
</description>
      <dc:subject>ブラウザ</dc:subject>
    </item>
    <item>
      <title>ローカルストレージを確認したり消したりするブックマークレット</title>
      <link>http://dara-j.asablo.jp/blog/2012/03/19/6382357</link>
      <guid>http://dara-j.asablo.jp/blog/2012/03/19/6382357</guid>
      <pubDate>Mon, 19 Mar 2012 12:31:51 +0900</pubDate>
      <dcterms:modified>2012-03-19T12:46:22+09:00</dcterms:modified>
      <dcterms:created>2012-03-19T12:32:34+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
TLでローカルストレージ絡みの話がちょろちょろ流れてたので、興味があったのと多少は需要がありそうな気がしたのでざっくり作ってみた。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
用途は、スマートフォンやタブレットなどのモバイルOSで、例えばiOSなんかはorigin指定で削除することもできないし、消す場合はCookieやらなにやら一絡げで削除しちゃうので、「このoriginのlocalStorageだけ消したい！」というような用途で使ってください。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
なお、削除すると元ページの機能が意図通りに動かなくなる可能性があるので慎重に。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ブックマークレット&lt;/h3&gt;&#13;
&lt;h4&gt;ローカルストレージの内容確認&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
こんな感じ。&#13;
&lt;p&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="javascript:(function(l,a){if(!l){alert('no-data')}else{for(var%20k%20in%20l)a.push(k+'-&gt;'+l[k].length+'chars');alert(!a.length?'no-data':a.join('\n'))}})(window.localStorage,[])" onclick="prompt('src',unescape(this.href));return false"&gt;ローカルストレージの内容確認&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h4&gt;ローカルストレージを削除&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
こんな感じ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="javascript:(window.localStorage&amp;&amp;window.localStorage.clear())" onclick="prompt('src',unescape(this.href));return false"&gt;ローカルストレージを削除&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;インストール方法&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
どちらのブックマークレットも、リンクをクリックくするとソースがpromptで表示されるので、スマートフォンやらタブレットデバイスの場合はこれをコピーして使ってください。デスクトップブラウザの場合はそのままドラッグドロップでよいかと。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;注意点とか&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
Web Storageは&lt;a class="external_link" href="http://keicode.com/script/jsonp-same-origin-policy.php"&gt;同一生成元ポリシー&lt;/a&gt;なので、確認/削除のスコープは当然これに縛られます。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
また、処理対象にしているのはwindow.localStorageのみなので、ラッパーかませてCookie使ってるページとか、globalStorage使ってるページとかでは効力ないかと。&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
    </item>
    <item>
      <title>そうそう、いまさらTwitter始めました。</title>
      <link>http://dara-j.asablo.jp/blog/2012/03/13/6373625</link>
      <guid>http://dara-j.asablo.jp/blog/2012/03/13/6373625</guid>
      <pubDate>Tue, 13 Mar 2012 05:35:47 +0900</pubDate>
      <dcterms:modified>2012-03-13T05:36:38+09:00</dcterms:modified>
      <dcterms:created>2012-03-13T05:36:38+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
といっても、去年の10月くらいからなんですがね。もう右サイドのメニューには載っけてましたが。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="https://twitter.com/#!/dara_j_"&gt;こちら&lt;/a&gt;で細々やってます。&#13;
&lt;/p&gt;
</description>
      <dc:subject>お知らせ</dc:subject>
    </item>
    <item>
      <title>忍者ツールズアクセス解析経由の広告用トラッキングクッキーについて</title>
      <link>http://dara-j.asablo.jp/blog/2012/03/13/6373624</link>
      <guid>http://dara-j.asablo.jp/blog/2012/03/13/6373624</guid>
      <pubDate>Tue, 13 Mar 2012 05:29:54 +0900</pubDate>
      <dcterms:modified>2012-03-14T03:10:08+09:00</dcterms:modified>
      <dcterms:created>2012-03-13T05:30:51+09:00</dcterms:created>
      <description>&lt;h3&gt;追記：2012年3月14日&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;div class="box"&gt;&#13;
&lt;p&gt;&#13;
サムライファクトリーから3月13日付で「業務提携先へのデータ提供停止」のお知らせが出ました。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;a class="external_link" href="http://www.ninja.co.jp/information/all_category/info/5688/"&gt;『忍者アクセス解析』業務提携先へのデータ提供の停止｜お知らせ｜忍者ツールズ&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ただし、トラッキングの拒否方法については「お使いのブラウザのcookieを削除」と案内されており、オプトアウトの手続きについてはこれまで通りプライバシーポリシー経由で各社のオプトアウト手続きページをちくちくと探す必要があります。&#13;
&lt;/p&gt;&#13;
&lt;/div&gt;&#13;
&lt;/p&gt;&#13;
&lt;h3&gt;忍者ツールズ経由でのトラッキングについて&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
当ブログで以前より設置していた&lt;a class="external_link" href="http://www.ninja.co.jp/"&gt;忍者ツールズ&lt;/a&gt;によるアクセス解析（&lt;a class="external_link" href="http://www.samurai-factory.jp/"&gt;株式会社サムライファクトリー&lt;/a&gt;提供）において、サムライファクトリー社の提携企業が発行するトラッキングクッキーが使用されていることが判明したためお知らせいたします。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
このことにより、&lt;b style="color:red"&gt;当ブログを訪問された皆様が気づかぬうちにWeb上の行動履歴がトラッキングされている&lt;/b&gt;可能性があります。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
この行動履歴追跡はいわゆる「&lt;a class="external_link" href="http://ja.wikipedia.org/wiki/%E8%A1%8C%E5%8B%95%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E5%BA%83%E5%91%8A"&gt;行動ターゲティング広告&lt;/a&gt;」で、直接個人情報を取り扱うわけではないのですが、&lt;b&gt;複数のサイトをまたがって追跡されるという性質からプライバシー上問題なしともいえない行為&lt;/b&gt;のため、このような追跡を好ましく思わない場合は&lt;b&gt;オプトアウトを行ってトラッキングクッキーを拒否されることをお勧め&lt;/b&gt;いたします。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
当方で実際にトラッキングクッキーを確認できたのは&lt;a class="external_link" href="http://www.microad.jp/privacy/"&gt;株式会社マイクロアド&lt;/a&gt;のみですが、&lt;a class="external_link" href="http://www.samurai-factory.jp/policy/tieup.html"&gt;サムライファクトリーのこちらのページ&lt;/a&gt;によればアクセス解析における提携企業は3社あるようです。各提携企業のオプトアウトはそれぞれ以下から行えます。&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;株式会社フリークアウト → &lt;a class="external_link" href="http://fout.jp/?page_id=125"&gt;こちら&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;株式会社マイクロアド → &lt;a class="external_link" href="http://send.microad.jp/w3c/"&gt;こちら&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;株式会社リクルート → &lt;a class="external_link" href="http://c-team.jp/cookie.html"&gt;こちら&lt;/a&gt;&lt;br/&gt;※ リクルートアドネットワークは&lt;b&gt;全部で15社&lt;/b&gt;あるようです…&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
また、当ブログではアクセス解析のみの利用でしたが、このほかに&lt;b&gt;&lt;a class="external_link" href="http://www.ninja.co.jp/admax/"&gt;忍者AdMax（広告配信サービス）&lt;/a&gt;での提携で8社&lt;/b&gt;あるようです。詳しい情報は&lt;a class="external_link" href="http://www.samurai-factory.jp/policy/tieup.html"&gt;サムライファクトリーのプライバシーポリシーページ&lt;/a&gt;をご覧ください。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
この状況は&lt;a class="external_link" href="http://www.ninja.co.jp/information/all_category/info/4148/"&gt;昨年3月のプライバシーポリシー改定&lt;/a&gt;以降からだったようですが、当方でこの改定を見落としていたためお知らせが遅くなってしまいました。大変申し訳ございませんでした。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
なお、当該のアクセス解析はすでに当ブログより削除し、これを機に忍者ツールズを退会いたしました。&lt;b&gt;今後は同社・他社問わず外部のアクセス解析サービスは一切利用しない&lt;/b&gt;ことといたします。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
本件は、当ブログのみならず忍者アクセス解析を設置している他のサイト様においても同様のことですので、&lt;b&gt;繰り返しになりますが、行動ターゲティング広告による追跡を好ましく思わない場合はオプトアウトされることをお勧め&lt;/b&gt;いたします。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;はてなブックマークボタンにおける問題&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
忍者ツールズの問題に先立って、&lt;a class="external_link" href="http://matome.naver.jp/odai/2133135680730086201"&gt;はてなブックマークボタンで同種の問題&lt;/a&gt;が発生していました（私が忍者ツールズの問題を知ったのも実は&lt;a class="external_link" href="https://twitter.com/#!/bulkneets/status/178331348891729920"&gt;こちらの騒動の流れから&lt;/a&gt;でした）。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
はてなのサービスは利用していないのでこちらに関してはなにか知見があるわけではないのですが、トラッキングクッキーの発行元も同じマイクロアド社であることや、ツール読み込みの外部JSの変更によっていきなりトラッキングを開始したことなどで非常に参考になるため、関連リンクを記しておきます。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://d.hatena.ne.jp/mala/20120308/1331193381"&gt;ブログパーツやソーシャルボタンの類でアクセスログが残るのは当然だけどトラッキングされるのは当たり前にはなっていない - 最速転職研究会&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://matome.naver.jp/odai/2133135680730086201"&gt;はてなブックマークボタンの行動履歴追跡クッキー問題まとめ【私家版】 - NAVER まとめ&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://matome.naver.jp/odai/2133131006928771201"&gt;はてなブックマークボタンのトラッキング問題で高木浩光先生が決別ツイートをするに至った経緯まとめ - NAVER まとめ&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://blog.tokumaru.org/2012/03/blog-post.html"&gt;徳丸浩の日記: はてなブックマークボタンを外しました&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://www.nantoka.com/~kei/diary/?20120312S1"&gt;サーバ管理者日誌 はてなブックマークを経由したトラッキングに関するお詫び&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://d.hatena.ne.jp/Dullahan/20120311/1331410665"&gt;はてなブックマークボタン問題に関して（追記あり） - 脳無しの呟き《土鍋と麦酒と炬燵猫》&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://d.hatena.ne.jp/Dullahan/20120312/1331556353"&gt;はてなブックマークボタン問題に関して（その２） - 脳無しの呟き《土鍋と麦酒と炬燵猫》&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://d.hatena.ne.jp/katoyuu/20120312/boycotthatebu"&gt;はてなブックマークボタンを外した - 戯れ言&lt;/a&gt;&lt;/li&gt;&#13;
 &lt;li&gt;&lt;a class="external_link" href="http://it.slashdot.jp/story/12/03/12/0014216/"&gt;はてブボタンを表示するスクリプトがスパイウェア的な挙動をしていたことが話題に | スラッシュドット・ジャパン IT&lt;/a&gt;&lt;/li&gt;&#13;
&lt;/ul&gt;
</description>
      <dc:subject>お知らせ</dc:subject>
    </item>
    <item>
      <title>無限箱の箱が全部ピンクになるまでがんばるブックマークレット</title>
      <link>http://dara-j.asablo.jp/blog/2012/02/24/6346935</link>
      <guid>http://dara-j.asablo.jp/blog/2012/02/24/6346935</guid>
      <pubDate>Fri, 24 Feb 2012 11:21:36 +0900</pubDate>
      <dcterms:modified>2012-02-28T02:27:29+09:00</dcterms:modified>
      <dcterms:created>2012-02-24T11:23:11+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
なんとなく&lt;strike&gt;無限なめこ&lt;/strike&gt;&lt;a class="external_link" target="_blank" href="http://iqp.6.ql.bz/box/infinity/"&gt;無限箱&lt;/a&gt;ですべてが&lt;strike&gt;黄金なめこ&lt;/strike&gt;ピンク箱になるまで自動的に抜きまくるブックマークレットを作ってみた。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&lt;strong style="color:red"&gt;※：いろいろ事情があってキノコから箱になったようです。&lt;/strong&gt;あと、なんか様子がおかしくなって逃げ回るようになってたり。&#13;
&lt;p&gt;&#13;
&lt;a href="javascript:(function(){var _f=arguments.callee,ns=$.makeArray($('#main&gt;img')),i=0,g=0,fl=Math.floor,fnd=function(i){return arObj[fl(i/COL)]?arObj[fl(i/COL)][i%ROW]:null};setTimeout(function(){var t=(fnd(i)||{isAnimation:false}).isAnimation?null:ns[i++],TM=50;if(t){if(!/((golden)|(box2))/.test(t.src)){var p=$(t).position();p.left++;p.top++;onMouseDown({preventDefault:$.noop,pageX:p.left,pageY:p.top,touches:[{pageX:p.left+1,pageY:p.top+1}]})}else{TM=0;if(++g&gt;=ns.length){alert('completed!!');return}}}setTimeout(t?arguments.callee:_f,TM);},0);})();" onclick="prompt('source:',unescape(this.href));return false"&gt;無限&lt;strong&gt;箱&lt;/strong&gt;用ブックマークレット&lt;/a&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;strike&gt;いまのとこWinのFirefox10とChrome17でしか動作確認取れてません。&lt;/strike&gt;IEはちょっと無理っぽいので無視の方向で。&#13;
&lt;/p&gt;&#13;
&lt;h4&gt;追記&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
&lt;strike&gt;ちぇ、iPadだとすんなり動かないか…&lt;/strike&gt;&#13;
&lt;/p&gt;&#13;
&lt;h4&gt;追記2&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
&lt;strike&gt;Androidもダメだな。なんかが根本的にダメなのか。&lt;/strike&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
一応ソースも載せておこう。&#13;
&lt;pre&gt;javascript:(function(){&#13;
    var&#13;
        _f=arguments.callee,&#13;
        ns=$.makeArray($('#main&gt;img')),&#13;
        i=0,g=0,&#13;
        fl=Math.floor,&#13;
        fnd=function(i){&#13;
            return arObj[fl(i/COL)]?arObj[fl(i/COL)][i%ROW]:null&#13;
        };&#13;
    setTimeout(function(){&#13;
        var t=(fnd(i)||{isAnimation:false}).isAnimation?null:ns[i++],TM=50;&#13;
        if(t){&#13;
            if(!/((golden)|(box2))/.test(t.src)){&#13;
                var p=$(t).position();&#13;
                p.left++;&#13;
                p.top++;&#13;
                onMouseDown({&#13;
                    preventDefault:$.noop,&#13;
                    pageX:p.left,pageY:p.top,&#13;
                    touches:[{pageX:p.left+1,pageY:p.top+1}]&#13;
                })&#13;
            }else{&#13;
                TM=0;&#13;
                if(++g&gt;=ns.length){&#13;
                    alert('completed!!');return&#13;
                }&#13;
            }&#13;
        }&#13;
        setTimeout(t?arguments.callee:_f,TM);&#13;
    },0);&#13;
})();&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;h4&gt;追記3&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
iOS/Android対応で修正。たぶん動くはず…&#13;
&lt;/p&gt;&#13;
&lt;h4&gt;追記4：ブックマークレットの登録方法&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
デスクトップブラウザなら「無限箱用ブックマークレット」のリンクをブックマークバーにそのままドラッグドロップするだけでOKです。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
スマートフォンやタブレットデバイスの場合は以下の要領で登録・編集してください。&#13;
&lt;ol&gt;&#13;
&lt;li&gt;このページでもどこでも適当に新規ブックマークを追加する&lt;/li&gt;&#13;
&lt;li&gt;「無限箱用ブックマークレット」をタップしてプロンプト表示されるブックマークレットURLをクリップボードにコピー&lt;/li&gt;&#13;
&lt;li&gt;最初に新規登録したブックマークのURLをコピーしたもので置き換え、適当にタイトルを入れる&lt;/li&gt;&#13;
&lt;/ol&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
現在動作が確認できているのはFirefox10(Win) / Chrome 17(Win) / Safari 5.1(Mac, iOS5.0.1) / Android 2.3.3 くらいです。&#13;
&lt;/p&gt;&#13;
&lt;h4&gt;追記5&lt;/h4&gt;&#13;
&lt;p&gt;タイミングによっては&lt;strike&gt;黄金なめこ&lt;/strike&gt;ピンク箱も抜いてしまうバグの修正&lt;/p&gt;&#13;
&lt;p&gt;ってか、なにやってんだ、俺…&lt;/p&gt;&#13;
&lt;h4&gt;追記6（2012-02-28 02:24）&lt;/h4&gt;&#13;
&lt;p&gt;箱対応&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
    </item>
    <item>
      <title>SafariとChromeの判別があやしくなったので改善してみる</title>
      <link>http://dara-j.asablo.jp/blog/2011/08/25/6070926</link>
      <guid>http://dara-j.asablo.jp/blog/2011/08/25/6070926</guid>
      <pubDate>Thu, 25 Aug 2011 20:10:51 +0900</pubDate>
      <dcterms:modified>2011-12-28T14:12:11+09:00</dcterms:modified>
      <dcterms:created>2011-08-25T20:01:10+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
夏も終わり間近というこのタイミングで今年最初のエントリになっちゃうんだけども、デスクトップ版Safariが5.1になったことで以前書いた「&lt;a href="/blog/2010/12/18/5588728"&gt;SafariとChromeを判別してみる&lt;/a&gt;」の方法が通用しなくなっちゃったのであわてて更新してみる。ほんとは中華パッド3号とか4号とかのこと書きたかったんだけども。&#13;
&lt;/p&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
// WebKitかどうか。&#13;
window.is_webkit = (function() {&#13;
	try {&#13;
		return window.navigator.taintEnabled == undefined;&#13;
	} catch(e) {&#13;
		return false;&#13;
	}&#13;
})();&#13;
&#13;
// モバイルブラウザかどうか&#13;
window.is_mobile = (function() {&#13;
	return window.is_webkit &amp;&amp; ! isNaN(window.orientation);&#13;
})();&#13;
&lt;/script&gt;&#13;
&lt;h3&gt;前回のおさらい&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
&lt;a href="/blog/2010/12/18/5588728"&gt;前回&lt;/a&gt;のアプローチは、SafariとChromeでwindow.constructorが違っている（SafariはObject、ChromeはDOMWindow）ことを利用してこんなアプローチをしてた。&#13;
&lt;pre&gt;&#13;
// Safariはtrue、Chromeはfalseを返す関数&#13;
&amp;lt;script type="text/javascript"&amp;gt;&#13;
window.check1 = function() {&#13;
  try {&#13;
    return window.constructor.prototype.alert == undefined;&#13;
  } catch(e) {&#13;
    // IEとかエラーでるし。&#13;
    alert(e.message || e.description);&#13;
  }&#13;
}&#13;
&amp;lt;/script&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(check1())"&amp;gt;check1&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
window.check1 = function() {&#13;
  try {&#13;
    return window.constructor.prototype.alert == undefined;&#13;
  } catch(e) {&#13;
    // IEとかエラーでるし。&#13;
    return (e.message || e.description);&#13;
  }&#13;
}&#13;
&lt;/script&gt;&#13;
&lt;button type="button" onclick="alert(check1())"&gt;check1&lt;/button&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ところが、Safari5.1からはwindow.constructorが&lt;strong&gt;DOMWindowConstructor&lt;/strong&gt;とやらに変わっちゃったので、Chromeと判別されちゃう。さて、困りました。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;Safari Developer Libraryを探したら&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
んで、急いでAppleの&lt;a href="http://developer.apple.com/library/safari/navigation/" class="external_link"&gt;Safari Developer Library&lt;/a&gt;の&lt;a href="http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html" class="external_link"&gt;Document Additions Reference&lt;/a&gt;で&lt;a href="http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html%23//apple_ref/doc/uid/TP40009349-CH5-DontLinkElementID_9" class="external_link"&gt;プロパティ&lt;/a&gt;を確認したところ、「webkitCurrentFullScreenElement」「webkitFullScreenKeyboardInputAllowed」「webkitIsFullScreen」なんてのが見つかった。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
念のためChromeのJavaScriptコンソールで「document.webkit」まで入力してタブキーで候補をさらってみたところ「Current～」とか「FullScreen～」、「Is～」とかは表示されなかったのでなんとなくで「webkitIsFullScree」を採用することに決定。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ただし、プロパティの名前からしてbooleanを返すだろうから、単純に&#13;
&lt;pre&gt;&#13;
!document.webkitIsFullScreen&#13;
&#13;
&lt;/pre&gt;&#13;
なんて試しても判別がつかないので、undefinedかどうかをテストすることにして、こんな感じに。&#13;
&lt;pre&gt;&#13;
&amp;lt;script type="text/javascript"&amp;gt;&#13;
window.check2 = function() {&#13;
  try {&#13;
    return window.constructor.prototype.alert == undefined ||&#13;
           document.webkitIsFullScreen !== undefined;&#13;
  } catch(e) {&#13;
    return e.message || e.description;&#13;
  }&#13;
}&#13;
&amp;lt;/script&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(check2())"&amp;gt;check2&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
window.check2 = function() {&#13;
  try {&#13;
    return window.constructor.prototype.alert == undefined ||&#13;
           document.webkitIsFullScreen !== undefined;&#13;
  } catch(e) {&#13;
    return e.message || e.description;&#13;
  }&#13;
}&#13;
&lt;/script&gt;&#13;
&lt;button type="button" onclick="alert(check2())"&gt;check2&lt;/button&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;で、こうなりました。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
この変更を適用すると、こんな感じに。前回同様is_webkitとis_mobileの判定が出来る前提で。&#13;
&lt;pre&gt;&#13;
&amp;lt;script type="text/javascript"&amp;gt;&#13;
// Safariかどうか&#13;
window.is_safari2 = (function() {&#13;
    // WebKitじゃなきゃ当然Safariじゃないわな&#13;
    if(! window.is_webkit) return false;&#13;
    if(window.is_mobile) {&#13;
        // モバイル版の場合、SVGをサポートしてたらSafari&#13;
        return !! window.SVGColor;&#13;
    } else {&#13;
        // デスクトップ版の場合、windowコンストラクタのプロトタイプで判別&#13;
        try {&#13;
            // ＊ ココ修正！！ ＊&#13;
            // どっちかtrueならSafari&#13;
            return window.constructor.prototype.alert == undefined ||&#13;
                   document.webkitIsFullScreen !== undefined;&#13;
        } catch(e) {&#13;
            // そもそもwindow.constructor とか そのプロトタイプにアクセスできない&#13;
            // ブラウザもあるので try - catch しとく&#13;
            return false;&#13;
        }&#13;
    }&#13;
})();&#13;
&#13;
// Chromeかどうか&#13;
window.is_chrome2 = (function() {&#13;
    // WebKitじゃなきゃ(ry&#13;
    if(! window.is_webkit) return false;&#13;
    // 後は基本的にSafariと逆&#13;
    if(window.is_mobile) {&#13;
        return ! window.SVGColor;&#13;
    } else {&#13;
        try {&#13;
            // ＊ ココ修正！！ ＊&#13;
            return window.constructor.prototype.alert != undefined &amp;&amp;&#13;
                   document.webkitIsFullScreen === undefined;&#13;
        } catch(e) {&#13;
            return false;&#13;
        }&#13;
    }&#13;
})();&#13;
&#13;
&amp;lt;/script&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
window.is_safari2 = (function() {&#13;
	if(! window.is_webkit) return false;&#13;
	if(window.is_mobile) {&#13;
		return !! window.SVGColor;&#13;
	} else {&#13;
		try {&#13;
			return window.constructor.prototype.alert == undefined ||&#13;
				document.webkitIsFullScreen !== undefined;&#13;
		} catch(e) {&#13;
			return false;&#13;
		}&#13;
	}&#13;
})();&#13;
window.is_chrome2 = (function() {&#13;
	if(! window.is_webkit) return false;&#13;
	if(window.is_mobile) {&#13;
		return ! window.SVGColor;&#13;
	} else {&#13;
		try {&#13;
			return window.constructor.prototype.alert != undefined &amp;&amp;&#13;
				document.webkitIsFullScreen === undefined;&#13;
		} catch(e) {&#13;
			return false;&#13;
		}&#13;
	}&#13;
})();&#13;
&#13;
&lt;/script&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(window.is_safari2)"&amp;gt;Safariっすか？（改）&amp;lt;/button&amp;gt;&#13;
&amp;lt;button type="button" onclick="alert(window.is_chrome2)"&amp;gt;Chromeっすか？（改）&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;button type="button" onclick="alert(window.is_safari2)"&gt;Safariっすか？（改）&lt;/button&gt;&#13;
&lt;button type="button" onclick="alert(window.is_chrome2)"&gt;Chromeっすか？（改）&lt;/button&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
Chrome 13まではこれで大丈夫だけど、フルスクリーンがどうのこうのなんて機能はOS X Lion向けっぽいのでいずれこれでも判別できなくなっちゃいそうではあるが。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
つか、そろそろ中華パッドネタ書いときたいなぁ。もうすでに旬をすぎちゃってるんだけども。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h4&gt;追記&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
Safari且つChromeとか判定されたり、前回の記事と同時に表示すると上書きされちゃったりなど細々と考慮漏れがあったりしたのでちくちく修正してました。もう平気かな。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h4&gt;追記2（2011.12.28）&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
ありゃ、気付いたらChromeもdocument.webkitIsFullScreenとかサポートしちゃってるしorz さて、どうするべ…&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
→ window.chrome が使えそう。なぜこれに気付かないし。&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>ブラウザ</dc:subject>
    </item>
    <item>
      <title>ブラウザで開いているページのURLをEvernoteにメールするブックマークレット</title>
      <link>http://dara-j.asablo.jp/blog/2010/12/18/5588741</link>
      <guid>http://dara-j.asablo.jp/blog/2010/12/18/5588741</guid>
      <pubDate>Sat, 18 Dec 2010 06:26:37 +0900</pubDate>
      <dcterms:modified>2010-12-18T06:33:46+09:00</dcterms:modified>
      <dcterms:created>2010-12-18T06:27:34+09:00</dcterms:created>
      <description>&lt;h3&gt;需要があるかはわかりませんが...&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
半年くらい前からちょろちょろとEvernote使ってるんだけども、dara-j的にはWebの内容をクリップするのが主目的なんです。たとえばTumblrのダッシュボードに流れてきたQuoteの元記事見に行って気に入った部分があったらクリップするとか。FirefoxのWebクリッパーなんかはかなり出来がいいので、なかなか快適に使えるわけです。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
が、、内容をじっくり呼んでる時間がないときなんかは後回しにするためにちゃっちゃとタイトルとURLだけクリップしときたい、ってケースもままあるわけで。そんな時はメールで飛ばしちゃうのが手っ取り早いので、ページタイトルとURLをクリップボードに入れるJSActionスクリプトとか作ってみてたんだけど、これだと既定のノートブックに入るだけでしばらくすると後で探しづらかったり。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
そこはEvernote、ちゃんとサブジェクトの書き方でターゲットのノートブックやタグを指定はできるんだけど、いちいち書くのも結構面倒になってくるわけで。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
で、こういう用途ならブックマークレットを経由してmailtoで開いてやれば投稿用のtoアドレスやらタグをつけたサブジェクトを指定できて結構クイックに扱えるかな、と思って作ってみました。前置きが長かったな。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;まずはソース&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
こんな感じ。&#13;
&lt;pre&gt;&#13;
(function(opt){&#13;
    var a = '', t = document.title, u = location.href, e = encodeURIComponent, s = ' ';&#13;
    location.href =&#13;
        'mailto:' + a +&#13;
        '?subject=' + e(t + s + opt) +&#13;
        '&amp;body=' + e([t, u].join('\n'));&#13;
})(prompt('input #tag and/or @notebook', '') || '');&#13;
&#13;
&#13;
&lt;/pre&gt;&#13;
で、実際のブックマークレットはこんなの。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
→ &lt;a href="javascript:(function(opt)%7Bvar%20a='',t=document.title,u=location.href,e=encodeURIComponent,s='%20';location.href='mailto:'+a+'%3Fsubject='+e(t+s+opt)+'%26body='+e(%5Bt,u%5D.join('%5Cn'));%7D)(prompt('input%20%23tag%20and%2For%20%40notebook','')||'');&#13;
" onclick="return func20101219_01(this)"&gt;Evernoteにメール&lt;/a&gt;&lt;br /&gt;&#13;
&lt;input id="for_prompt20101219_01" type="checkbox" /&gt;クリックしたらソースを表示&#13;
&lt;/p&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
function func20101219_01(a) {&#13;
	if(! document.getElementById("for_prompt20101219_01").checked) return true;&#13;
	prompt("ブックマークレットのソース", a.href);&#13;
	return false;&#13;
}&#13;
&lt;/script&gt;&#13;
&lt;p&gt;&#13;
「クリックしたらソースを表示」のチェックボックスをOnにすると、クリック時にpromptでソースをポップアップするので、iPhoneなんかのドラッグドロップでブックマークレット登録できないブラウザ使ってる場合にちょっぴり便利。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;ざっと解説&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
メインの関数式に渡す引数はprompt()の実行結果から受け取るようにしてて、これをページタイトルとくっつけたものをサブジェクトに指定してます。なので、「未読」ってタグをつけたい場合はprompt()に「#未読」って入れてやればOKと。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
タグやノートブックを複数指定する場合はそれぞれの間をスペースで区切ります。ノートブック「個人用」にタグ「未読」と「url」をつけるなら、「#未読 #url @個人用」みたいな感じで。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;改造とか&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
関数内の変数'a'はtoアドレスに使われるので、ここに自分のEvernoteメールアドレスをあらかじめ入れておけば送信先を選択やら入力やらしなくてもよくなります。さらに関数式への引数もリテラルで書いておけば、ブックマークレットを起動すればメーラーがすぐに起動するので後は送信するだけで目的を果たせるようになります。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ただし引数をリテラル記述する場合、マルチバイト文字はそのまま使えないので、あらかじめescapeしたものを使ってください。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;改造が面倒だろうからジェネレータ&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
って、ブックマークレットのソースを改造するのはちとめんどくさいので、ジェネレータを作って起きました。自分が良く使うパターンで生成してブックマークしておくと便利じゃないかと。&#13;
&lt;/p&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
function generate_bookmarklet_20101219_01() {&#13;
	var opt = [$("notebook_name_20101219_01").value.length ? ("@" + $("notebook_name_20101219_01").value) : ""].concat(&#13;
		$("tag_list_20101219_01").value.split(/\s+/g).map(function(t) {&#13;
			return "#" + t;&#13;
		})).join(" ");&#13;
	var src = [&#13;
		"javascript:(function(opt){",&#13;
		"var t=document.title,u=location.href,e=encodeURIComponent,s=' ';",&#13;
		"location.href='mailto:",&#13;
		$("mailto_addr_20101219_01").value,&#13;
		"?subject='+e(t+s+opt)+'",&#13;
		"&amp;body='+e([t,u].join('\\n'));",&#13;
		"})('", encodeURIComponent(opt), "')"&#13;
	].join("");&#13;
	var label = $("link_title_20101219_01").value;&#13;
	$("generated_bookmarklet_20101219_01").innerHTML = "";&#13;
	&#13;
	var link = Object.extend(document.createElement("a"), {&#13;
		href : src,&#13;
		innerHTML : (label.length ? label : "Mail to Evernote").escapeHTML()&#13;
	});&#13;
	$("generated_bookmarklet_20101219_01").appendChild(link);&#13;
	link.onclick = function() {&#13;
		if(!$("for_prompt20101219_02").checked) return true;&#13;
		prompt("ブックマークレットのソース", link.href);&#13;
		return false;&#13;
	}&#13;
}&#13;
&lt;/script&gt;&#13;
&lt;p&gt;&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;toアドレス：&lt;input id="mailto_addr_20101219_01" type="text" style="width:300px" value="" /&gt;&lt;/li&gt;&#13;
 &lt;li&gt;ターゲットのノートブック：&lt;input id="notebook_name_20101219_01" type="text" style="width: 250px" value="" /&gt;&lt;/li&gt;&#13;
 &lt;li&gt;タグ（スペース区切り）：&lt;input id="tag_list_20101219_01" type="text" style="width: 250px" value="" /&gt;&lt;/li&gt; &lt;li&gt;リンクタイトル：&lt;input id="link_title_20101219_01" type="text" style="width: 250px" value="Mail to Evernote" /&gt;&#13;
&lt;/ul&gt;&#13;
&lt;div&gt;&lt;button type="button" onclick="generate_bookmarklet_20101219_01()"&gt;ブックマークレット作成&lt;/button&gt;&lt;/div&gt;&#13;
&lt;div id="generated_bookmarklet_20101219_01"&gt;（ここにブックマークレットが作成されます）&lt;/div&gt;&#13;
&lt;div&gt;&lt;input id="for_prompt20101219_02" type="checkbox"&gt;クリックしたらソースを表示&lt;/div&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
使い方は、&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;toアドレスに自分のEvernoteメールアドレス（@m.evernote.com）を入力&lt;/li&gt;&#13;
 &lt;li&gt;ターゲットのノートブックやタグを入力。@や#は不要、タグは半角スペースで区切って複数指定可能&lt;/li&gt;&#13;
 &lt;li&gt;リンクタイトルに入れた文字列が、生成されるブックマークレットの見出しになる&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
てな感じ。ジェネレータがうまく動かなかったらコメントください。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h4&gt;追記&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
あー、ジェネレータでノートブック名やタグにマルチバイト文字使うと、IEじゃ化けちゃうなぁ...&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>Evernote</dc:subject>
    </item>
    <item>
      <title>SafariとChromeを判別してみる</title>
      <link>http://dara-j.asablo.jp/blog/2010/12/18/5588728</link>
      <guid>http://dara-j.asablo.jp/blog/2010/12/18/5588728</guid>
      <pubDate>Sat, 18 Dec 2010 04:32:45 +0900</pubDate>
      <dcterms:modified>2011-08-25T20:17:47+09:00</dcterms:modified>
      <dcterms:created>2010-12-18T04:33:56+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
&lt;b style="color:red"&gt;※：Safari 5.1がChromeと区別できなくなったので&lt;a href="/blog/2011/08/25/6070926"&gt;修正版&lt;/a&gt;作ってみました。（11.08.25）&lt;/b&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
はい、またも3週間もほったらかしにしてたわけですが、ようやく&lt;a href="/blog/2010/11/25/5534921"&gt;前回&lt;/a&gt;の続きで、レンダリングエンジンがWebKitだった場合にAppleのSafariなのか、GoogleのChromeなのかを判別してみようかと。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
当初の考えでは、まずSafariなのかChromeなのかを判断して、それからモバイル版なのかを見ようと思ってたんだけど、「SafariとモバイルSafariにはあって、ChromeとモバイルChromeには存在しないプロパティ」またはその逆ってのが見つからなかったのよね。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
仕方ないのでデスクトップ版同士、モバイル版同士の差異を探して、&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;まずはモバイル版かどうか判断し&lt;/li&gt;&#13;
 &lt;li&gt;その後にそれぞれSafariかChromeかをチェックする&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
という方法に落ち着いた。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
あ、この記事では便宜上、Androidの標準ブラウザを「モバイル版Chrome」とか呼んじゃってるけど、これたぶん正式な名前じゃないみたい。あくまで便宜上の呼称と思ってくださいな。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;まずはモバイル版かどうか見分ける&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
これは&lt;a href="/blog/2010/11/25/5534921"&gt;前回&lt;/a&gt;の最後にふれてたけど、モバイル版ブラウザにはデバイスの向きを示す「window.orientation」というNumberなプロパティがあり、これはデスクトップ版には&lt;b&gt;今のところ&lt;/b&gt;実装されてないのでこれを使ってみる。&#13;
&lt;pre&gt;&#13;
&amp;lt;script type="text/javascript"&amp;gt;&#13;
// WebKitかどうか。&#13;
window.is_webkit = (function() {&#13;
    try {&#13;
        return window.navigator.taintEnabled == undefined;&#13;
    } catch(e) {&#13;
        return false;&#13;
    }&#13;
})();&#13;
&#13;
// モバイルブラウザかどうか&#13;
window.is_mobile = (function() {&#13;
    return window.is_webkit &amp;amp;&amp;amp; ! isNaN(window.orientation);&#13;
})();&#13;
&amp;lt;/script&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
// WebKitかどうか。&#13;
window.is_webkit = (function() {&#13;
	try {&#13;
		return window.navigator.taintEnabled == undefined;&#13;
	} catch(e) {&#13;
		return false;&#13;
	}&#13;
})();&#13;
&#13;
// モバイルブラウザかどうか&#13;
window.is_mobile = (function() {&#13;
	return window.is_webkit &amp;&amp; ! isNaN(window.orientation);&#13;
})();&#13;
&lt;/script&gt;&#13;
事前にWebKitであるかもあわせて判別しておく。&#13;
&lt;/p&gt;&#13;
あとはこの情報を参照すればいいだけ。&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(window.is_mobile)"&amp;gt;モバイル版のWebKit？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;button type="button" onclick="alert(window.is_mobile)"&gt;モバイル版のWebKit？&lt;/button&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;Safariであるかどうか - モバイル編&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
まずモバイル版の違い。エミュレータベースでしか確認してないけど、Android 2.3（Gingerbread）になってもモバイル版のChromeはまだSVGをサポートしてない模様。しかもありがたいことにWebKitはDOMとかブラウザ由来のオブジェクトのコンストラクタがちゃんとwindowのプロパティとしてアクセスできるので、SVG関連のコンストラクタの有無をチェックすればいいわけだ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
が、モバイルSafariのほうもSVGの実装が段階的に進んでいるため、バージョンによって存在するものとしないものがあるので、なるべく基本的なオブジェクトを使う必要がある。&#13;
&lt;p&gt;&#13;
ここではSVGColorを使うことにする。要はwindow.SVGColor が undefined かどうかを見るというわけ。コードは後述。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;Safariであるかどうか - デスクトップ編&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
で、今度はデスクトップ版の場合だが、これがなかなか苦しかった。さすがに各ブラウザともHTML5街道へまっしぐら状態なのでなかなかブラウザ固有のものが見つからないのだ。windowのプロパティをfor..inで列挙してみると、たまに片方にしか存在しないプロパティ名が見つかるのだが、単に&lt;a class="external_link" href="http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/8_Types.html#section-8.6.1"&gt;DontEnum属性&lt;/a&gt;がついてるだけでオブジェクトとしては存在してたりするし。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
そんなわけで単純な存在の有無のチェックじゃ実現できないんだけど、windowプロパティの列挙時に値までチェックしてみたところちょっと面白いことに気づいた。たとえばデベロッパコンソール上でwindowのコンストラクタを出力してみると、Safariの場合は&#13;
&lt;pre&gt;&#13;
&amp;gt; window.constructor&#13;
  function Object() {&#13;
      [native code]&#13;
  }&#13;
&#13;
&lt;/pre&gt;&#13;
Chromeの場合は&#13;
&lt;pre&gt;&#13;
&amp;gt; window.constructor&#13;
  function DOMWindow() { [native code] }&#13;
&#13;
&lt;/pre&gt;&#13;
と、コンストラクタ関数がまったく異なっているようなのだ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
Safariの場合、コンストラクタがObject()ってことは、window固有のプロパティはコンストラクタから継承してるわけではないと推測できるし、ChromeのほうはモロにDOMWindowという名前なのでこれにwindow固有プロパティが実装されてそうだと推測できる。ってことで、Chromeで試してみた。&#13;
&lt;pre&gt;&#13;
&amp;gt; window.constructor.prototype.alert&#13;
  function alert() { [navite code] }&#13;
&#13;
&lt;/pre&gt;&#13;
お！いい感じですよ？じゃ、Safariでは？&#13;
&lt;pre&gt;&#13;
&amp;gt; window.constructor.prototype.alert&#13;
  undefined&#13;
&#13;
&lt;/pre&gt;&#13;
よし！予想通り！！要するに、window.constructor.prototype.alert が undefined ならSafari、そうでないならChromeと判断して間違いない、と。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
これ試したのはChrome 8だったので、以前のバージョンがどういう実装になっていたのか、USBブート可能なポータブル版のChrome 4やら5やらを探し出してきて試してみたところ、まったく同じ状況だったのでこれで問題なさそう。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;で、こうなる、と。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
ようやく判別方法が固まったので、以下のような感じで。あ、先ほどのis_webkitとis_mobileの判断がでてることが前提でね。&#13;
&lt;pre&gt;&#13;
&amp;lt;script type="text/javascript"&amp;gt;&#13;
// Safariかどうか&#13;
window.is_safari = (function() {&#13;
    // WebKitじゃなきゃ当然Safariじゃないわな&#13;
    if(! window.is_webkit) return false;&#13;
    if(window.is_mobile) {&#13;
        // モバイル版の場合、SVGをサポートしてたらSafari&#13;
        return !! window.SVGColor;&#13;
    } else {&#13;
        // デスクトップ版の場合、windowコンストラクタのプロトタイプで判別&#13;
        try {&#13;
            // undefinedならSafari&#13;
            return window.constructor.prototype.alert == undefined;&#13;
        } catch(e) {&#13;
            // そもそもwindow.constructor とか そのプロトタイプにアクセスできない&#13;
            // ブラウザもあるので try - catch しとく&#13;
            return false;&#13;
        }&#13;
    }&#13;
})();&#13;
&#13;
// Chromeかどうか&#13;
window.is_chrome = (function() {&#13;
    // WebKitじゃなきゃ(ry&#13;
    if(! window.is_webkit) return false;&#13;
    // 後は基本的にSafariと逆&#13;
    if(window.is_mobile) {&#13;
        return ! window.SVGColor;&#13;
    } else {&#13;
        try {&#13;
            return window.constructor.prototype.alert != undefined;&#13;
        } catch(e) {&#13;
            return false;&#13;
        }&#13;
    }&#13;
})();&#13;
&#13;
&amp;lt;/script&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;script type="text/javascript"&gt;&#13;
// Safariかどうか&#13;
window.is_safari = (function() {&#13;
	// WebKitじゃなきゃ当然Safariじゃないわな&#13;
	if(! window.is_webkit) return false;&#13;
	if(window.is_mobile) {&#13;
		// モバイル版の場合、SVGをサポートしてたらSafari&#13;
		return !! window.SVGColor;&#13;
	} else {&#13;
		// デスクトップ版の場合、windowコンストラクタのプロトタイプで判別&#13;
		try {&#13;
			// undefinedならSafari&#13;
			return window.constructor.prototype.alert == undefined;&#13;
		} catch(e) {&#13;
			// そもそもwindow.constructor とか そのプロトタイプにアクセスできない&#13;
			// ブラウザもあるので try - catch しとく&#13;
			return false;&#13;
		}&#13;
	}&#13;
})();&#13;
&#13;
// Chromeかどうか&#13;
window.is_chrome = (function() {&#13;
	// WebKitじゃなきゃ(ry&#13;
	if(! window.is_webkit) return false;&#13;
	// 後は基本的にSafariと逆&#13;
	if(window.is_mobile) {&#13;
		return ! window.SVGColor;&#13;
	} else {&#13;
		try {&#13;
			return window.constructor.prototype.alert != undefined;&#13;
		} catch(e) {&#13;
			return false;&#13;
		}&#13;
	}&#13;
})();&#13;
&#13;
&lt;/script&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(window.is_safari)"&amp;gt;Safariっすか？&amp;lt;/button&amp;gt;&#13;
&amp;lt;button type="button" onclick="alert(window.is_chrome)"&amp;gt;Chromeっすか？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;button type="button" onclick="alert(window.is_safari)"&gt;Safariっすか？&lt;/button&gt;&#13;
&lt;button type="button" onclick="alert(window.is_chrome)"&gt;Chromeっすか？&lt;/button&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;そのうちライブラリにするよ。多分。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
ということで、ようやく当初の目的どおりの判別ができるようになりましたとさ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ここまでのスクリプトはすべて、window.onloadを待たずに判断できるので、単独ライブラリで実装して一番最初に読み込むスクリプトに仕立て上げちゃえばいいんだけど、ちょっとまとめるのがめんどくさいので、まぁそのうち。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h4&gt;追記&lt;/h4&gt;&#13;
&lt;p&gt;&#13;
ちなみに、window.constructor.prototype のプロパティでの判断は、モバイル版では通用しません。モバイル版ChromeはSafariと同じで window.constructor.prototype.alert は undefined になります。と思いました。確か。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="try { alert(window.constructor.prototype.alert); } catch(e) { alert(e); }"&amp;gt;window.constuctor.prototype.alert は？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;button type="button" onclick="try { alert(window.constructor.prototype.alert); } catch(e) { alert(e); }"&gt;window.constuctor.prototype.alert は？&lt;/button&gt;&#13;
&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>ブラウザ</dc:subject>
    </item>
    <item>
      <title>JSでブラウザを判別してみよう</title>
      <link>http://dara-j.asablo.jp/blog/2010/11/25/5534921</link>
      <guid>http://dara-j.asablo.jp/blog/2010/11/25/5534921</guid>
      <pubDate>Thu, 25 Nov 2010 05:07:32 +0900</pubDate>
      <dcterms:modified>2010-11-25T05:16:39+09:00</dcterms:modified>
      <dcterms:created>2010-11-25T05:08:28+09:00</dcterms:created>
      <description>&lt;p&gt;&#13;
油断してたらまた4ヶ月も更新してなかったのだが、なんとなくJSでブラウザ判別を行うという、わりとありがちな事に挑戦してみる。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ライブラリとしてまとめようと思ってたんだけど、そろそろ眠いので、今日のところは断片的な記述にしておこう。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;何を判別する？&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
メジャーどころだったらたいていはレンダリングエンジン≒ブラウザが成立しそうなもんなんだけど、WebKitの場合はSafariとChromeの両方がなかなか普及してるので、「レンダリングエンジンが何であるか」と「ブラウザが何であるか」の2種類を判別することにする。で、Safari/Chromeの場合はモバイル版かどうかも見ないとね。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ということで、レンダリングエンジンは&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;Trident&lt;/li&gt;&#13;
 &lt;li&gt;Gecko&lt;/li&gt;&#13;
 &lt;li&gt;Presto&lt;/li&gt;&#13;
 &lt;li&gt;WebKit&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
、ブラウザは&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;IE&lt;/li&gt;&#13;
 &lt;li&gt;Firefox&lt;/li&gt;&#13;
 &lt;li&gt;Opera&lt;/li&gt;&#13;
 &lt;li&gt;Safari&lt;/li&gt;&#13;
 &lt;li&gt;Chrome&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
を判別してみる。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;まずは、Presto ＝ Opera。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
めちゃくちゃ手抜きなんだけど、window.operaがundefinedじゃなければPrestoっつーことで。しかもPrestoだったら何も考えずにOperaっつーことで。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;button type="button" onclick="alert(!! window.opera)"&gt;レンダリングエンジンははPresto?&lt;/button&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(!! window.opera)"&amp;gt;レンダリングエンジンははPresto?&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;button type="button" onclick="alert(!! window.opera)"&gt;ブラウザはOpera?&lt;/button&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(!! window.opera)"&amp;gt;ブラウザはOpera?&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;次はGecko ＝ Firefox。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
まぁ、GeckoをみんなFirefoxとみなすのは乱暴なのはわかってるんだけども、こちらも手抜き。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
昔、MooToolsの1.2.2のブラウザ判定部分のソース見たときは、window.document.getBoxObjectForがundefinedでなければGeckoてな判断してたみたいなんだけど、Firefox 3.6の環境で試したらこれが成立しなくなってたのでwindowのプロパティを総当りで調べたところ、window.mozInnerScreenXあたりが使えそうなので組み合わせで判別してみる。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;button type="button" onclick="alert(window.document.getBoxObjectFor != undefined || window.mozInnerScreenX != undefined);"&gt;レンダリングエンジンはGecko？&lt;/button&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(window.document.getBoxObjectFor != undefined || window.mozInnerScreenX != undefined);"&amp;gt;レンダリングエンジンはGecko？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;button type="button" onclick="alert(window.document.getBoxObjectFor != undefined || window.mozInnerScreenX != undefined);"&gt;ブラウザはFirefox？&lt;/button&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(window.document.getBoxObjectFor != undefined || window.mozInnerScreenX != undefined);"&amp;gt;ブラウザはFirefox？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;IEかどうか、までは簡単。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
IEかどうかを判別するのは、window.ActiveXObjectをチェックするのが定番なんだけども、念のため&lt;a class="external_link" href="http://msdn.microsoft.com/en-us/library/ff974676%28v=VS.85%29.aspx"&gt;MSDNを見てみたら、なんかIE9で廃止になっちゃいそうな記述&lt;/a&gt;が。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
びっくりしてIE9ベータで確認したらnullは返してこなかったんだけど、ちょっと怖いのでもうひとつの定番「window.document.all」を使うことに。でもこれ、Operaも実装してるんだったよな、確か。&#13;
っつーことで、こんな感じに。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;button type="button" onclick="alert(!!((window.ActiveXObject || window.document.all) &amp;&amp; !window.opera))"&gt;レンダリングエンジンはTrident？&lt;/button&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(!!((window.ActiveXObject || window.document.all) &amp;amp;&amp;amp; !window.opera))"&amp;gt;レンダリングエンジンはTrident？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;IEのバージョンは細かく見てみたい。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
で、IEの場合は他のブラウザよりもバージョンの違いをなるべく厳密に判別したくなるので、&#13;
&lt;ul&gt;&#13;
 &lt;li&gt;IE6よりも前&lt;/li&gt;&#13;
 &lt;li&gt;IE6&lt;/li&gt;&#13;
 &lt;li&gt;IE7&lt;/li&gt;&#13;
 &lt;li&gt;IE8&lt;/li&gt;&#13;
 &lt;li&gt;IE9&lt;/li&gt;&#13;
&lt;/ul&gt;&#13;
をなんとか判別してみようかといろいろ探してみたところ、これまたMSDNに&lt;a class="external_link" href="http://msdn.microsoft.com/en-us/library/ms537509%28v=VS.85%29.aspx"&gt;Detecting Internet Explorer More Effectively&lt;/a&gt;なんてぴったりの記事が見つかった。冒頭のほうではユーザエージェントで判別する方法を記載してるんだけど、これじゃ心もとないのでもう少し読み進めてみたら、&lt;a class="external_link" href="http://msdn.microsoft.com/en-us/library/ms537509%28v=VS.85%29.aspx#4"&gt;「Another IE version detector snippet」と題するコメントが&lt;/a&gt;。&#13;
&lt;blockquote cite="http://msdn.microsoft.com/en-us/library/ms537509(v=VS.85).aspx#4" title="Detecting Internet Explorer More Effectively"&gt;&#13;
Another IE version detector snippet&lt;br /&gt;&#13;
function getIEVersion(odoc){&lt;br /&gt;&#13;
if (odoc.body.style.scrollbar3dLightColor!=undefined)&lt;br /&gt;&#13;
 {&lt;br /&gt;&#13;
 if (odoc.body.style.opacity!=undefined) {return 'IE9';}&lt;br /&gt;&#13;
 else if (odoc.body.style.msBlockProgression!=undefined) {return 'IE8';}&lt;br /&gt;&#13;
 else if (odoc.body.style.msInterpolationMode!=undefined) {return 'IE7';}&lt;br /&gt;&#13;
 else if (odoc.body.style.textOverflow!=undefined) {return 'IE6'}&lt;br /&gt;&#13;
 else {return 'IE5.5 or lower';}&lt;br /&gt;&#13;
 }&lt;br /&gt;&#13;
} &#13;
&lt;div style="text-align: right"&gt;&#13;
 &lt;cite&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms537509(v=VS.85).aspx#4" title="Detecting Internet Explorer More Effectively"&gt;Detecting Internet Explorer More Effectively&lt;/a&gt;&lt;/cite&gt;&#13;
&lt;/div&gt;&#13;
&lt;/blockquote&gt;&#13;
なるほど、styleプロパティでチェックするのね。ただこのサンプルどおりbody.styleをチェックする方法だとページロードが完了しないと判定できないので不便なので、head要素でチェックをしてみることに。あ、あとIE9かどうかの判別はwindow.msPerformanceでチェックしたほうがよさげ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
で、こんなコードを実行して、&#13;
&lt;script type="text/javascript"&gt;&#13;
window.detected_ie_name = (function() {&#13;
    if(window.ActiveXObject == undefined &amp;&amp; window.document.all == undefined) return "IEじゃない";&#13;
    if(window.msPerformance != undefined) return "IE9";&#13;
    var h = document.getElementsByTagName("head")[0];&#13;
    if(h.style.msBlockProgression != undefined) return "IE8";&#13;
    if(h.style.msInterpolationMode != undefined) return "IE7";&#13;
    if(h.style.textOverflow != undefined) return "IE6";&#13;
    return "IE5.5かそれ以前";&#13;
})();&#13;
&lt;/script&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;script type="text/javascript"&amp;gt;&#13;
window.detected_ie_name = (function() {&#13;
    if(window.ActiveXObject == undefined &amp;amp;&amp;amp; window.document.all == undefined) return "IEじゃない";&#13;
    if(window.msPerformance != undefined) return "IE9";&#13;
    var h = document.getElementsByTagName("head")[0];&#13;
    if(h.style.msBlockProgression != undefined) return "IE8";&#13;
    if(h.style.msInterpolationMode != undefined) return "IE7";&#13;
    if(h.style.textOverflow != undefined) return "IE6";&#13;
    return "IE5.5かそれ以前";&#13;
})();&#13;
&amp;lt;/script&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
こんな感じのボタンを貼ってみる。&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="alert(window.detected_ie_name)"&amp;gt;IEのバージョンは？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
&lt;button type="button" onclick="alert(window.detected_ie_name)"&gt;IEのバージョンは？&lt;/button&gt;&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;WebKitか否か。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
MooTools 1.2.2では、navigator.taintEnabledのチェックでもって判別してた。これなんぞ？と思ったら、&lt;a class="external_link" href="http://www.antimon2.atnifty.com/lab/2007/11/mootools4legacybrowser.html"&gt;よい解説&lt;/a&gt;が見つかった。&#13;
&lt;blockquote cite="http://www.antimon2.atnifty.com/lab/2007/11/mootools4legacybrowser.html" title="非対応ブラウザでMooToolsを完全に無効にする方法 - 研究室"&gt;&#13;
navigator.taintEnabled() というのは、「ユーザーに非通知でデータ送信が可能かどうか（データテイント機能の使用有無）を返すメソッド」です。「何それ？」て思われた方、ご安心ください。Netscape Navigator 3.x の時代の、古い古ーい仕様で、データテイント機能は現在使われておりません。多くのブラウザは、ただfalseを返すだけです。&lt;br /&gt;&#13;
ただしSafari（WebKit）では、このメソッドそのものを定義していません。&#13;
&lt;div style="text-align: right"&gt;&#13;
 &lt;cite&gt;&lt;a href="http://www.antimon2.atnifty.com/lab/2007/11/mootools4legacybrowser.html" title="非対応ブラウザでMooToolsを完全に無効にする方法 - 研究室"&gt;非対応ブラウザでMooToolsを完全に無効にする方法 - 研究室&lt;/a&gt;&lt;/cite&gt;&#13;
&lt;/div&gt;&#13;
&lt;/blockquote&gt;&#13;
だそうで、まんま使わせてもらおう。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
&lt;button type="button" onclick="try { alert(window.navigator.taintEnabled == undefined) } catch(e) { alert(false); }"&gt;レンダリングエンジンはWebKit？&lt;/button&gt;&#13;
&lt;pre&gt;&#13;
&amp;lt;button type="button" onclick="try { alert(window.navigator.taintEnabled == undefined) } catch(e) { alert(false); }"&amp;gt;レンダリングエンジンはWebKit？&amp;lt;/button&amp;gt;&#13;
&#13;
&lt;/pre&gt;&#13;
って、IETester使ってるせいか、デフォルトIE以外だとwindow.navigator.taintEnabledにアクセスしただけで例外吐くのでtry catchで囲まなきゃ。&#13;
&lt;/p&gt;&#13;
&#13;
&lt;h3&gt;Safariか、Chromeか。&lt;/h3&gt;&#13;
&lt;p&gt;&#13;
これはあんまりいい方法が見つからなかったので、両方でSafari5とChrome7の両方でwindowのプロパティを洗いざらい列挙してめぼしいところをいくつか試してみたところ、window.TouchListの有無がよさそうだった。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
と思って今試したら、Safariでもwindow.TouchListがundefined返してきた。あれぇ？会社で試したときと違うなあ。&#13;
&lt;/p&gt;&#13;
&lt;p&gt;&#13;
ということで、ちょっと別の方法探さなきゃ。ちなみにモバイル版かの判別は今のところwindow.orientationがNaNじゃなければモバイルってな判定でよさげ。&#13;
&lt;/p&gt;
</description>
      <dc:subject>JavaScript</dc:subject>
      <dc:subject>ブラウザ</dc:subject>
    </item>
    <item>
      <title>SmartPadから書きこんでみるテスト。</title>
      <link>http://dara-j.asablo.jp/blog/2010/07/28/5253546</link>
      <guid>http://dara-j.asablo.jp/blog/2010/07/28/5253546</guid>
      <pubDate>Wed, 28 Jul 2010 03:47:02 +0900</pubDate>
      <dcterms:modified>2010-07-28T04:14:40+09:00</dcterms:modified>
      <dcterms:created>2010-07-28T04:09:06+09:00</dcterms:created>
      <description>&lt;p&gt;アクセスログ見てたら、解像度が800 x 480 x 16bitな人が見に来てた。
&lt;/p&gt;
&lt;p&gt;UAには「Android 1.6」て出てのでEKEN系かePad/FlyTouchの人だろうか。お仲間のようで、なんかうれしい。
&lt;/p&gt;
&lt;p&gt;てなことをスマパから書きこんでみているが、たったこれだけの文章でも結構ストレスだなあ。
&lt;/p&gt;
&lt;p&gt;フリック入力にはそれなりに馴れてるつもりだったんだけど位置の誤検出による入力ミスはちょっとイライラくる。
&lt;/p&gt;
&lt;p&gt;テンキーパッドで「た」はともかく「ま」を「あ」で検出しちゃうのと、DELキーの二重検出はしんどいなあ。
&lt;/p&gt;
&lt;p&gt;て、これだけで30分近くかかってるし orz
&lt;/p&gt;</description>
      <dc:subject>雑記</dc:subject>
      <dc:subject>中華パッド</dc:subject>
    </item>
  </channel>
</rss>
