oflow のすべての投稿

お名前.com+さくらレンタルサーバでGoogle Apps覚え書き

oflowme_apps

ドメイン取得したのでGmailも独自ドメインで利用したい。何だかんだいってGmail便利だし。
そんな事を思って最初はさくらコントロールパネルのメール転送機能でGmailに転送専用で使ってたんだけど、これがどうもすっきりしない。
ログインするのは結局「ホゲホゲ@gmail.com」で取得したドメインは関係ないし。

と、いうことで調べてたらGoogle Appsが便利そうなので変更した。

通常、さくらレンタルサーバーを使う場合は
お名前.com → ドメイン設定 → ネームサーバの変更から

プライマリネームサーバ ns1.dns.ne.jp
セカンダリネームサーバ ns2.dns.ne.jp

という設定をするはず(違う人は詳しいだろうから知らん)、けどこのままだとGoogle Appsでメールなんかが届かない。

そこでお名前.comのレンタルDNSレコード設定を使うわけです。
まず、このレンタルDNSレコード設定を使う為に、ネームサーバ設定で

プライマリネームサーバ 01.dnsv.jp
セカンダリネームサーバ 02.dnsv.jp

に戻しといてレンタルDNSレコード設定で以下のようにどんどん追加。
(ホスト名は取得したドメインに合わせといて下さい)

ホスト名 TYPE VALUE 優先度
oflow.me MX aspmx.l.google.com 10
oflow.me MX alt1.aspmx.l.google.com 20
oflow.me MX alt2.aspmx.l.google.com 30
oflow.me MX aspmx2.google.com 40
oflow.me MX aspmx3.google.com 50
mail.oflow.me CNAME ghs.google.com
calendar.oflow.me CNAME ghs.google.com
oflow.me A xx.xx.xx.xx (レンタルサーバのIPアドレス)
www.oflow.me A xx.xx.xx.xx (レンタルサーバのIPアドレス)
gyazo.oflow.me A xx.xx.xx.xx (レンタルサーバのIPアドレス)

MX: メールのやつ
CNAME: http://mail.oflow.me/ でGoogle Apps メールとかに
A: http://oflow.me/ のやつ

Google docs, Google sitesは使ってないので設定してない。
まー、これで今のところGoogle Appsでメール(ほげほげ@oflow.meなメール)とカレンダーも使えてるのでいいっかなー。

find_in_searchbar_highlight.uc.jsに機能追加したりボタンをテーマ「rein」に合わせてみた

Firefox 4.0.1, userChromeJS 1.3, Sub-Script/Overlay Loader v3.0.30modで動作確認。

検索ボックスのボタン(虫眼鏡)をクリックでページ内検索する便利なuserChrome.jsのスクリプト「find_in_searchbar_highlight.uc.js」(Firefox用スクリプトアップローダー(新)の642.js)ですが、テーマ「rein」を使ってるとハイライトボタンが浮いてしまう。
ということで変えました。

ついでにいろいろ変えてます。以下の通り。

  • 虫眼鏡クリック以外にも検索ボックス内でCtrl+EnterまたはAlt+Nでページ内検索(次へ)
  • 同様にCtrl+Shift+EnterまたはAlt+Pでページ内検索(前へ)
  • ハイライトボタンは初期状態で非表示(使えないので)
    ページ内検索を1回実行すると表示
    通常の検索(Enterのみ、Alt+Enterなど)でまたハイライトボタン非表示にする
  • ハイライトはボタンクリック以外にも検索ボックス内Ctrl+Hで切り替えできる
  • 背景色変更あたりを微調整

ダウンロード : find_in_searchbar_highlight_mod.uc.js (デフォルトボタンのまま)
ダウンロード : find_in_searchbar_highlight_mod(rein).uc.js (rein対応ボタン)
※ボタンの画像が違うだけです。たぶん。

// ==UserScript==
// @name           find_in_searchbar_highlight.uc.js (mod)
// @description    検索バーでページ内検索+検索文字のハイライト
// @include        chrome://browser/content/browser.xul
// @author         yosuke
// @compatibility  Firefox 4.0
// @Note           (概要)
// @Note           ・検索バー内にある検索ボタン(虫眼鏡)をクリックすると,検索バーに入力された文字列をページ内検索する.
// @Note           ・検索バーの右端にあるペンボタンをクリックすると,検索バーに入力された文字列をすべてハイライト表示する.
// @Note           ・検索した結果,文字列がみつからない場合,検索バー内の背景が赤になる.
// @Note           ・先頭に戻って検索するか,末尾に戻って検索する場合,検索バー内の背景が緑になる.
// @Note           (具体的な使い方)
// @Note             検索ボタンの右クリック -> ページ内検索,次を検索
// @Note             検索ボタンの左クリック -> 前を検索
// @Note             検索ボタンの中クリック -> 検索バー内の文字列を消去
// @Note             ペンボタンをクリック   -> ハイライトのオン,オフ
// @Note           (注意)
// @Note             「任意の設定」の値を変更することで各種機能を個別に設定できます.
// @Note             検索バーによるページ内検索を行う場合,検索ボタンを表示させてください.
// @Note           (追加機能:oflow)
// @Note             テーマ「rain」に合わせてアイコンを変更
// @Note             ハイライトボタンの位置を検索ボックスの中に移動
// @Note             ページ内検索をした時だけハイライトボタンを表示するように変更
// @Note             Ctrl+Enter, Alt+Nでページ内検索(次を検索)
// @Note             Ctrl+Shift+Enter, Alt+Pでページ内検索(次を検索)
// ==/UserScript==

(function() {
    /*----- 任意の設定 -----*/
    // 検索バーによるページ内検索を許可するか("true" or "false")
    const USE_FINDSEARCH = "true"
    // 強調ボタンを配置するか("true" or "false")
    const USE_HIGHLIGHTBUTTON = "true"
    // 検索バーでページ内検索を行う際にページ内検索バーを表示するか("true" or "false")
    const USE_FINDBAR = "false"
    // 先頭に戻って検索,末尾に戻って検索を許可するか("true" or "false")
    const USE_WRAP= "true"
    
    /*----- 初期設定 -----*/
    // ID, Class  Object
    var searchbar = document.getElementById("searchbar");
    var searchbox = document.getAnonymousElementByAttribute(searchbar, "anonid", "searchbar-textbox");
    var searchGoButton = document.getAnonymousElementByAttribute(searchbar, "anonid", "search-go-button");
    var inputbox = document.getAnonymousElementByAttribute(searchbar, "anonid", "input");
    var findstatus = gFindBar.getElement("find-status-icon");
    
    // Colour, Image
    const white = "#ffffff";
    const green = "#ccffcc";
    const red   = "#ffcccc";
    var onHighlight = 'data:image/png;base64,'+
    'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0'+
    'U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFgSURBVHjaYv7//z/j69evWR8+fMj19etX'+
    'HgYGBhjmxoK5gJhDTEyMOT4+/v+pU6f+AwQQM1Azy5o1a/hevXolC5RUAmIFIJYHYlksWBKIhYEW'+
    'sQEt/PXgwYPfAAHEADQNZKr21KlTD7x8+fLbfwIApAakFqQHpBcggIA0gwAQOxKjGdkQkB6QXoAA'+
    'YgISzCC/AU3jZMADTExMwBgEoGpBLmcGCCCQAYxQQ/BqxgJAehgBAogJymEkUTNcD0AAMZFhMwoA'+
    'CCAmSjSDAEAAMTGQAM6cOYMhBhBAMAP+o9uelpZGSDNYD0AAgQJCGIgtgNG7BZvmWbNmYRgG4jMy'+
    'MvoAmScAAogFSPwF4m/ApPwdlhZAmpAVo2sGqQXpAekFCCCKkzJAADFmZWXBMpMUUFAUmsJYcITj'+
    'H6jNr4Gan4WEhHwCCCAGUHYGGsIKFABlYSGoIWI4MEhOCKQWpAekFyDAAO0k7MPVi8ODAAAAAElF'+
    'TkSuQmCC';
    var offHighlight = 'data:image/png;base64,'+
    'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0'+
    'U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFYSURBVHjaYv7//z/j69evWR4+fMj59etX'+
    'bgYGBhjmwoI5gZhdTEyMOT4+/v+pU6f+AwQQM0jzmjVr+F69eiUHlFQGYkUgVgBiOSxYCohFgBax'+
    'AS389eDBg98AAcQANA1ksvbUqVMPvHz58tt/AgCkBqQWpAekFyCAgDSDABA7EqMZ2RCQHpBegABi'+
    'AhLMIP8BTQP5DycwMTEBYxCAqgW5nBkggEAGMEINwasZCwDpYQQIICYoh5FEzXA9AAHERIbNKAAg'+
    'gJgo0QwCAAHExEACOHPmDIYYQADBDPiPbju6YiyawXoAAgiEhIHYGxbHxsbGKHGOzocBkB6QXoAA'+
    'YgESf4H4GzApf4elBWT/Y3M2SC1ID0gvQABRnJQBAogxKysLlplAGUUUmsJYcITjH6jNr4Gan4WE'+
    'hHwCCCAGUHYGGsIKFOABSghBDRHDgUFyQiC1ID0gvQABBgCgmw2B3mPqtQAAAABJRU5ErkJggg==';

    /*----- 検索ボタンをページ検索ボタンに -----*/
    // ページ内検索検索関数
    function find_in_searchbar(e){
        document.getElementById('toggle-all-highlight').style.display = 'block';
        var sel = searchbar.value;
        // 中クリック -> 検索文字列消去
        if(e.button == 1){
            gFindBar.toggleHighlight(false);
            searchbar.value = "";
            searchbox.style.backgroundColor = white;
        }
        // 左クリック, Ctrl+Enter       -> ページ内検索,次を検索
        // 右クリック, Ctrl+Shift+Enter -> 前を検索
        else if(sel){
            gFindBar._findField.value = sel;
            if(e.button == 0 || (e.ctrlKey && !e.shiftKey && e.keyCode == 13) || (e.altKey && e.keyCode == 78)){
                // 左クリック or Ctrl+Enter or Alt+N
                // 次へ
                gFindBar.onFindAgainCommand(false);
            } else if (e.button == 2 || (e.ctrlKey && e.shiftKey && e.keyCode == 13) || (e.altKey && e.keyCode == 80)) {
                // 右クリック or Ctrl+Shift+Enter or Alt+P
                // 前へ
                gFindBar.onFindAgainCommand(true);
            }
            if(findstatus.getAttribute("status")=="notfound"){
                searchbox.style.backgroundColor = red;
                // 見つからなくても検索ボックスにフォーカス
                searchbox.focus();
            }
            // 折り返し判定
            else if(findstatus.getAttribute("status")=="wrapped"){
                if(USE_WRAP=="false"){
                    if(e.button == 0){
                        gFindBar.onFindAgainCommand(true);
                    }else{
                        gFindBar.onFindAgainCommand(false);
                    }
                }
                searchbox.style.backgroundColor = green;
            }else{
                searchbox.style.backgroundColor = white;
            }
        }
        // ページ検索バーを表示するかどうか
        if(USE_FINDBAR == "true"){
            gFindBar.open();
        }else if(USE_FINDBAR == "false"){
            gFindBar.close();
        }
    }
    
    // 検索ボタン設定
    if(USE_FINDSEARCH == "true"){
        searchGoButton.removeAttribute("onclick");
        searchGoButton.setAttribute("oncontextmenu","return(false);");
        searchGoButton.addEventListener("click", function(e){ find_in_searchbar (e);}, false);
        searchbar.addEventListener("click", function(){searchbox.style.backgroundColor = white;}, true);
    }
    
    /*----- ハイライトボタンの生成 -----*/
    var sw = true;
    var str = "";
    // ハイライトオン,オフ関数
    function highlight_toggle() {
        var sel = searchbar.value;
        if(sel){
            gFindBar._findField.value = sel;
            gFindBar.toggleHighlight(false);                        // ハイライト初期化
            gFindBar.toggleHighlight(true);
            // 検索結果 notfound
            if(findstatus.getAttribute("status")=="notfound"){
                newButton.setAttribute("image",offHighlight);
                searchbox.style.backgroundColor = red;
                sw = false;
            }
            else if(sw){
                newButton.setAttribute("image",onHighlight);
                searchbox.style.backgroundColor = white;
            }else if(!sw){
                if(str == sel){
                    gFindBar.toggleHighlight(false);
                    newButton.setAttribute("image",offHighlight);
                    //sw = false;
                }else{
                    sw = !sw;
                    newButton.setAttribute("image",onHighlight);
                    searchbox.style.backgroundColor = white;
                }
            }
            sw = !sw;
        }
        else{
            sw = "false";
            newButton.setAttribute("image",offHighlight);
            gFindBar.toggleHighlight(false);
        }
        str = sel;
        // ページ検索バーを表示するかどうか
        if(USE_FINDBAR == "true"){
            gFindBar.open();
        }else if(USE_FINDBAR == "false"){
            gFindBar.close();
        }

    }
    // ハイライトボタン設定
    var newButton = document.createElement("toolbarbutton");
    newButton.setAttribute("label", "u3059u3079u3066u5f37u8abfu8868u793a");
    // ツールチップテキストは検索バーと同じ「すべて強調表示」
    newButton.setAttribute("tooltiptext", "u3059u3079u3066u5f37u8abfu8868u793a");
    newButton.setAttribute("id", "toggle-all-highlight");
    newButton.addEventListener("click", highlight_toggle, false);
    newButton.setAttribute("oncontextmenu","return(false);");
    newButton.setAttribute("image",offHighlight);
    // ボタンのマージンとかの設定
    newButton.style.cssText = 'display: none; margin: -6px 0px;';
    // 検索ボックス内にボタン表示する場合は背景色透過も
    //newButton.style.cssText = 'display: none; margin: 0px -2px; background-color: transparent !important';
    if(USE_HIGHLIGHTBUTTON == "true"){
        searchbar.parentNode.insertBefore(newButton, searchbar.nextSibling);
        // 検索ボックス内にボタン表示
        // searchGoButton.parentNode.insertBefore(newButton, searchGoButton.nextSibling);
        // 検索ボックスの左側にボタン表示
        // searchbar.parentNode.insertBefore(newButton, searchbar);

    }

    // 検索ボックスのCtrl+Enterでもページ内検索(次へ)
    //               Ctrl+Shift+Enterでもページ内検索(前へ)
    //               Ctrl+Hでハイライト切り替え
    // ついでに検索バーと同じようにAlt+Nで次、Alt+Pで前も使えるようにしておく
    searchbox.addEventListener('keydown', function(e) {
        // keyCode: 13=Enter, 72=h, 78=n, 80=p
        if ((e.ctrlKey && e.keyCode == 13) || (e.altKey && (e.keyCode == 78 || e.keyCode == 80))) {
            // suggestが出てる場合があるのでページ内検索実行時は消す
            searchbox.blur();
            searchbox.focus();

            find_in_searchbar(e);

            e.stopPropagation();
            e.preventDefault();
        } else if (e.ctrlKey && e.keyCode == 72) {
            highlight_toggle();
            e.stopPropagation();
            e.preventDefault();
        }
        if (!e.ctrlKey && e.keyCode == 13) {
            // ページ内検索を使用しない場合ハイライトボタンは不要なので非表示にする
            newButton.style.display = 'none';
            // ページ内検索して背景色変わってるかもしれないので戻す
            searchbox.style.backgroundColor = white;
        }
    }, false);
    searchbox.addEventListener('keyup', function(e) {
        if (searchbar.value == '') {
            // 検索ボックスのテキストが空なら背景色戻す
            searchbox.style.backgroundColor = white;
        }
    }, false);
})();

ものぐさなのでFirefox Add-ons 「Read It Later 2.1.1」の右クリックメニューだけ日本語化する.uc.xul

Firefox 4.0.1, userChromeJS 1.3, Sub-Script/Overlay Loader v3.0.30modで動作確認。

いや、ほらアドオン日本語化するのって面倒でしょ?
Read It Laterなんて日本語化するほどのものでもないし、右クリックメニューに英語まじってると気になるってだけなんですよ!

ということで、chromeフォルダに突っ込むだけのお手軽日本語化(右クリックメニューだけ)。
訳は適当。

ダウンロード : read-it-later-2.1.1.ja.uc.xul

<?xml version="1.0" encoding="UTF-8"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<popup id="contentAreaContextMenu">
	<menuitem id="RIL_context_saveLink" insertbefore="context-bookmarklink" label="このリンク先をあとで読む" oncommand="RIL.clickSaveCallback();event.stopPropagation();"/>
	<menuitem id="RIL_context_clickMode" insertafter="context-bookmarkpage" label="あとで読むリンクを指定" oncommand="RIL.toggleClickToSaveMode();event.stopPropagation();" />
	<menuitem id="RIL_context_savePage" insertafter="context-bookmarkpage" label="このページをあとで読む" oncommand="RIL.addCurrent();event.stopPropagation();"/>
	<menuitem id="RIL_context_saveTabs" label="すべてのタブをあとで読む" oncommand="RIL.saveTabs();event.stopPropagation();" />
</popup>
</overlay>

Instagramの画像をPCで開いたらI4PCへのリンクを付けるだけのGreasemonkeyスクリプト

PCでInstagramのLikeやコメントが残せる「I4PC」が便利なのですぐそっちに移動できるようにリンク付けます。
※listagramでやったアレとほぼ同じです…。

ダウンロード : instagram_i4pc.user.js
Instagramの仕様変更に伴い終了。


// ==UserScript==
// @name           instagram i4pc
// @description    add instagram photo info, i4pc link
// @version        1.3
// @author         oflow
// @namespace      http://oflow.me/
// @include        http://instagr.am/p/*
// @exclude        https://*
// ==/UserScript==

(function() {
    var css = [
        '.profile-photo { float: none !important; position: absolute; }',
        '.profile-info { float: none !important; margin-left: 60px; }',
        '.profile-info h1 { margin-bottom: 0.3em; }',
        '.profile-info h1 span { font-weight: normal; margin-left: 0.5em; font-size: 90%; }'
    ].join('');

    function getMeta() {
        var meta = document.getElementsByTagName( 'meta' );
        for ( var i = 0, length = meta.length; i < length; i++ ) {
            if ( meta[i].getAttribute( 'property' ) == 'og:description' ) {
                addOgDescription( meta[i].getAttribute( 'content' ) );
                break;
            }
        }
    }

    function addOgDescription( content ) {
        if ( !content ) return;
        var span = document.createElement( 'span' );
        span.appendChild( document.createTextNode( content ) );
        var h1 = document.getElementsByTagName( 'h1' )[0];
        if ( h1 ) {
            h1.appendChild( span );
        }
    }

    function addI4PC() {
        var profileImg = document.getElementsByClassName( 'photo-info' )[0].getElementsByTagName( 'img' )[0];
        if ( !profileImg ) return;
        if ( !//profile_([0-9]+)_/.test( profileImg.src ) ) {
            return;
        }
        var id = RegExp.$1;
        var profileInfo = document.getElementsByClassName( 'profile-info' )[0];
        profileInfo.appendChild( document.createTextNode( ' · ' ) );
        var a = document.createElement( 'a' );
        a.href = 'http://www.i4pc.jp/user/' + id;
        a.appendChild( document.createTextNode( 'I4PC' ) );
        profileInfo.appendChild( a );
    }
    GM_addStyle( css );
    getMeta();
    addI4PC();

} )();

連続する改行を詰めるブックマークレット

某ブログやケータイサイトなんかで使われまくってる改行タグを詰めるだけです。もう1度実行すると戻ります。
<p>&nbsp;</p> なんかで行間取ってるのも詰まります。

↓のコードをダブルクリックでコピーしてブックマークに登録して下さい。

javascript:(function(){var uze=document.getElementById('uze-br');if(uze){uze.parentNode.removeChild(uze);}else{var uze=document.createElement('style');uze.id='uze-br';uze.type='text/css';uze.appendChild(document.createTextNode('br{display:block !important;content:"" !important;}p.uze,div.uze{display:none !important;}'));document.getElementsByTagName('head')[0].appendChild(uze);var p=document.evaluate('//p[text()="xA0"] | //div[text()="xA0"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(var i=0;i<p.snapshotLength;i++){p.snapshotItem(i).className='uze';}}})();

CSSで br { display: block; content: “”; } を適用してJavaScriptで&nbsp;を消してるだけ

PHP5のfgetcsvで文字化けするときの対応策 fgetcsv_reg を少し変えてみた

PHP5でfgetcsvを使用すると文字化けしたり正常に読み込めない場合の対応策として fgetcsv_reg というユーザー定義関数 ( PHP5でfgetcsvが正常に動作しない : ::yossy.blog:: )
がありますが、大量にcsvファイルを読み込んでると結構遅くなるので若干変えてみました。

殆ど同じですが$lengthの初期値1024にしてtrim(), empty()使わなかったりfeof()でファイル終端か判断してるぐらいで、気持ち早いかなって程度です。

※いい加減なので場合によっては遅くなるかもしれません。

<?php
function fgetcsv_reg( &$handle, $length = 1024, $delimiter = ',', $enclosure = '"' ) {

    $delimiter = preg_quote( $delimiter );
    $enclosure = preg_quote( $enclosure );

    $buffer = '';

    while ( !feof( $handle ) ) {
        $buffer .= fgets( $handle, $length );
        if ( preg_match_all( '/' . $enclosure . '/', $buffer, $m ) % 2 == 0 ) {
            break;
        }
    }

    $pattern = '/(' . $enclosure . '[^' . $enclosure . ']*(?:' . $enclosure . $enclosure . '[^' . $enclosure . ']*)*' . $enclosure . '|[^' . $delimiter . ']*)' . $delimiter . '/';

    $values = array();
    $len = preg_match_all( $pattern, preg_replace( '/[rn]+$/', '', $buffer ) . $delimiter, $matches );
    for ( $i = 0; $i < $len; $i++ ) {
        $values[] = str_replace( $enclosure . $enclosure, $enclosure, preg_replace( '/^' . $enclosure . '(.*)' . $enclosure . '$/s', "$1", $matches[1][$i] ) );
    }
    return $buffer ? $values : false;

}
?>

PHPのマルチバイト文字列関数で”ISO-2022-JP”, “JIS”, “ISO-2022-JP-MS”の違い

PHP5.2.1ぐらいから”ISO-2022-JP-MS”というのも使えるそうなので”ISO-2022-JP”,”JIS”とどう違うか試してみました。

<?php
/* UTF-8からISO-2022-JP, JIS, ISO-2022-JP-MSに変換してみる */
setlocale( LC_ALL, 'ja_JP.UTF-8' );

/* ダメ元で☎ ☃なども */
$str = 'アイウエオ ㈱ ㈲ ① ② Ⅰ Ⅱ ℡ ㎏ ㎎ 﨑 髙 神 ☎ ☃';

header( 'Content-Type: text/plain; charset=ISO-2022-JP' );

printf( "%sn", 'PHP' . PHP_VERSION );
$encodings = array( 'ISO-2022-JP', 'JIS', 'ISO-2022-JP-MS' );
foreach ( $encodings as $encoding ) {
    printf( "%sn", $encoding . ' : ' . mb_convert_encoding( $str, $encoding, 'UTF-8' ) );
}
?>

これを実行すると以下のようになります。

PHP5.2.17
ISO-2022-JP : ????? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
JIS : アイウエオ ? ? ? ? ? ? ? ? ? ? ? ? ? ?
ISO-2022-JP-MS : アイウエオ ㈱ ㈲ ① ② Ⅰ Ⅱ ℡ ㎏ ㎎ 﨑 髙 神 ? ?

ISO-2022-JPとJISの違いは半角カナが使えるかどうか。ISO-2022-JP-MSはそれに加えて機種依存文字や外字まで使えてしまう。ってことですかね。

メール送信で使えそうな気がしますが、”-MS”と付いてるだけあってWindows以外では化けると思います。
Macは試してませんが携帯宛だど髙などが絵文字か空白か「?」に化けてました。

ということで、半角カナを使われそうな携帯などで”JIS”、それ以外では”ISO-2022-JP”を使って”ISO-2022-JP-MS”は使わない方が無難。

instagramの画像見たときにアーカイブ(listagram)のリンク付けるだけのGreasemonkeyスクリプト

instagramでアップロードした画像を一覧表示してくれる「listagram」というサイトがめっちゃ便利なんでinstagram開いたら「アーカイブ」ってリンク追加しただけ。

ついでに説明っぽいのあったら付け足してる。

2011/02/07
プロフィール画像設定してない場合はユーザーID取得できないので「アーカイブ」のリンク追加しないように修正

ダウンロード: instagram_archive.user.js
(listagramよりI4PCの方が個人的に好きなので終了)


// ==UserScript==
// @name           instagram archives
// @description    add instagram photo info, listagram archive link
// @version        1.3
// @author         oflow
// @namespace      http://oflow.me/
// @include        http://instagr.am/p/*
// @exclude        https://*
// ==/UserScript==

(function() {
    var css = [
        '.profile-photo { float: none !important; position: absolute; }',
        '.profile-info { float: none !important; margin-left: 60px; }',
        '.profile-info h1 { margin-bottom: 0.3em; }',
        '.profile-info h1 span { font-weight: normal; margin-left: 0.5em; font-size: 90%; }'
    ].join('');

    function getMeta() {
        var meta = document.getElementsByTagName( 'meta' );
        for ( var i = 0, length = meta.length; i < length; i++ ) {
            if ( meta[i].getAttribute( 'property' ) == 'og:description' ) {
                addOgDescription( meta[i].getAttribute( 'content' ) );
                break;
            }
        }
    }

    function addOgDescription( content ) {
        if ( !content ) return;
        var span = document.createElement( 'span' );
        span.appendChild( document.createTextNode( content ) );
        var h1 = document.getElementsByTagName( 'h1' )[0];
        if ( h1 ) {
            h1.appendChild( span );
        }
    }

    function addListagram() {
        var profileImg = document.getElementsByClassName( 'photo-info' )[0].getElementsByTagName( 'img' )[0];
        if ( !profileImg ) return;
        if ( !//profile_([0-9]+)_/.test( profileImg.src ) ) {
            return;
        }
        var id = RegExp.$1;
        var profileInfo = document.getElementsByClassName( 'profile-info' )[0];
        profileInfo.appendChild( document.createTextNode( ' · ' ) );
        var a = document.createElement( 'a' );
        a.href = 'http://listagr.am/u/' + id;
        a.appendChild( document.createTextNode( 'アーカイブ' ) );
        profileInfo.appendChild( a );
    }
    GM_addStyle( css );
    getMeta();
    addListagram();

} )();

PHPでFizzBuzz問題を考えてみた

まず、FizzBuzz問題とは。

1~100までの数字で3で割り切れる時は「Fizz」、5で割り切れる時は「Buzz」、両者で割り切れる時は「FizzBuzz」と出力する。

たったこれだけです。
せんだ!みつお!なはなは!とか3の倍数と3が付くときのアレみたいな感じです。

「2分以内で書け」や「1行で書け」や「○○バイト以内で書け」や「%を使うな」などの条件を付ける場合もありますが、これをPHPで書いたらどうなるかと思いましてやってみました。

<?php
for ( $i = 1; $i <= 100; $i++ ) {
    if ( $i % 15 == 0 ) {
        print 'FizzBuzz';
    } else if ( $i % 3 == 0 ) {
        print 'Fizz';
    } else if ( $i % 5 == 0 ) {
        print 'Buzz';
    } else {
        print $i;
    }
    print "n";
}
// <プークスクス
?>

実行結果

ハッ 嘲笑なんか気にしなければこれで良いんですよ!!

では「1行で書く」ってのを考えると、これを改行入れなければいいじゃん?ってなる訳で「どれだけ短く書けるか」ってのに挑戦しました。

まず、 if { } else if { } … この辺が長いので三項演算子を使うことに。
あまりひねらない書き方ですが、それぞれを三項演算子に置き換え、1行で書いた方が短いので for文の {} や余計なスペース、最後のセミコロンも省略します。

<?php for($i=1;$i<=100;$i++)print($i%15?($i%3?($i%5?$i:'Buzz'):'Fizz'):'FizzBuzz')."n"?>

何かそれっぽくなってきた!!
この時点で89バイト。

更に短くするにはと思いついたのが
for ( $i = 1; $i <= 100; $i++ ) の部分です。ここを for ( $i = 1; $i < 101; $i++ ) にしたら1文字減りますね。 何かで見た事あった次の書き方でも動きます。 for ( $i = 0; ++$i < 101; ) これでいい気もしますが101ってのがどうも気に入らないので1減らして for ( $i = 0; $i++ < 100; ) この書き方の方が見やすいかもです。文字数変わりませんし。 [php title="1行でFizzBuzz (87バイト)"]<?php for($i=0;$i++<100;)print($i%15?($i%5?($i%3?$i:"Fizz"):"Buzz"):"FizzBuzz")."n";?>[/php] これをTwitterに書いた直後に print を echo に変えるって気付きました。 echo は print と違って ,(コンマ) で区切って出力するって方法があります。ついでに最初の <?php を <? でもいいっての思い出して [php title="79bytes"]<?for($i=0;$i++<100;)echo$i%15?($i%3?($i%5?$i:'Buzz'):'Fizz'):'FizzBuzz',"n"?>[/php] ギリギリ80バイトの壁を越えました。 もうこの辺からparse error覚悟で動けばいいや!ってスペースどこ削って大丈夫か体当たり的になってます。 echo$i なんか続けて書いていいのかよ!とツッコミ入れたい。 ただ、この書き方 15の時がどうにか出来そうな気がします。 「3で割り切れる」=「FizzもしくはFizzBuzzなのでFizzだけ出力」、「5で割り切れない」=「数字だけ」ということを頭に入れて15という数字を消すと [php gutter="0" classname="inline"]( $i % 3 ( $ % 5 ? $i : '' ) : 'Fizz' ), ( !$i % 5 ? 'Buzz' : '' )[/php] こう書くこともできます。 いや ( !$i%5 ? 'Buzz' : '' ) は逆に出来るじゃないか… ということで ( $i%5 ? '' : 'Buzz' ) それでPHPの定数で思い出した事が1つ。 定義してない定数(主にtypo)はそのまま定数名が出力されたことありませんか? このPHPのいい加減な何でも文字列を利用して 「Fizz, Buzzという定数のつもりだけど実は定義してなかったからそのまま出力してね!」作戦。 [php title="FizzBuzz 67bytes "]<?for($i=0;$i++<100;)echo$i%3?($i%5?$i:''):Fizz,$i%5?'':Buzz,"n"?>[/php] ここで67バイトまで縮めることが出来ました。 ギブアップ。 翌日、forじゃなくても良いんじゃね?て思いwhileに変えると結構短く出来ました。 [php title="FizzBuzz 63bytes"]<?while($i++<100)echo$i%3?($i%5?$i:''):Fizz,$i%5?'':Buzz,"n"?>[/php] ここで、Twitterにpostしたところ救世主 @daira4000 さんに「三項演算子の()を外して、nを直接LFにする」と教えて頂きましてさらに短くなり、最後の ?> は ; に変えても大丈夫ということでついに60バイトの壁突破。

<?while($i++<100)echo$i%3?$i%5?$i:'':Fizz,$i%5?'':Buzz,"
";

実行結果

ΩΩΩ< ()は消しても大丈夫なのか-!!!
さらに考えたけど順番が変わった程度でした。

<?while($i++<100)echo$i%3?'':Fizz,$i%5?$i%3?$i:'':Buzz,"
";

PHPでは最短56バイトで書けるらしいんですがそんな脳みそは持ち合わせておりません。おわり。