MJHD

エモさ駆動開発

2016年のLinux環境

Linux デスクトップ環境 2016 - eagletmt's blogに触発されて書いた.
Macの便利なところを取り入れつつタイル型ウィンドウマネージャを活かす設定にしたかった.

ディストリビューション

ArchLinux.パッケージの更新も早く,yaourtを導入するとバカみたいにパッケージが増えるので最強.

ディスプレイマネージャ

LightDM.Greeterとしてwebkit-greeterを使っている.おしゃれなテーマが多いのでおすすめ.

テーマはhttps://github.com/jqln-0/Bevelを使っている. こんなの

ウィンドウマネージャ

XMonad.シンプルでいくらでもカスタマイズ出来る.しかも結構安定している.(ただしHaskell)

feh,xmobar,trayer,dockyを合わせて使用している.
また,nautilusでデスクトップアイコンも表示している.

f:id:wait0000:20160323130355p:plain

ターミナル

terminologyを使用している.結構リッチなエフェクトが沢山ある.

f:id:wait0000:20160323130500p:plain

TerminatorがSGRプロトコルに対応していない? - Devlion Memo

日本語入力

fcitxでmozcを使用している.
たまにgtk系のソフトでキーボードが効かなくなる?

エディタ

vim.去年は少しだけevil付きのemacsに浮気したが,やはりvimなしでは生きていけなかった.

f:id:wait0000:20160323131235p:plain

vim-startifyでvimのロゴを起動画面に設定する - Devlion Memo

スクリーンショット

shutterというソフトを使っている.
Ctrl+F2でデスクトップ全体, Ctrl+F3で範囲選択,
Ctrl+F4でウィンドウを選んでスクリーンショットを保存,など割り当てている.
Macのキーボードショートカットに似せたつもり.

paplayでシャッター音を鳴らすことでそれっぽくなる.


        ,((controlMask, xK_F2), spawn "shutter -f -e -n -o ~/Downloads/%Y-%m-%d-%T.png && paplay /usr/share/sounds/freedesktop/stereo/screen-capture.oga")
        ,((controlMask, xK_F3), spawn "shutter -s -e -n -o ~/Downloads/%Y-%m-%d-%T.png && paplay /usr/share/sounds/freedesktop/stereo/screen-capture.oga")
        ,((controlMask, xK_F4), spawn "shutter -w -e -n -o ~/Downloads/%Y-%m-%d-%T.png && paplay /usr/share/sounds/freedesktop/stereo/screen-capture.oga")

その他ソフト

mfiler4でファイル管理.mfiler4のすゝめ - Devlion Memo
clementineで音楽.
mplayerで動画.

パララックス効果っぽいjQueryプラグイン

パララックス効果っぽいjQueryプラグイン作ってみた. 適当.

SVGファイルは,一緒に動かしたいレイヤーごとにグループ化して,IDを割り振っといてください.
layersでそのID名を指定します.
指定した順に視差が設定されます.
※パスやグループにあらかじめtransform属性が存在すると動きません.削除してください.

サンプル f:id:wait0000:20160329202422p:plain

jquery.parallax.js


(function ($) {
    $.fn.parallax = function(options) {
        var defaults = {
            svgFile: "",
            layers: [],
            distance: 0.1
        };

        var setting = $.extend(defaults, options);

        var $this = this;

        $.get(setting.svgFile, function (data) {
            $this.append($(data.documentElement));

            $this.mousemove(function (e) {
                var width = $this.width();
                var height = $this.height();

                $.each(setting.layers, function (i, val) {
                    $("#" + val).attr({
                        "transform": "translate(" + (e.clientX - width / 2) * (setting.layers.length - i) * setting.distance + ", " + (e.clientY - height / 2) * (setting.layers.length - i) * setting.distance + ")"
                    });
                });
            });
        });
    };
})(jQuery);

HTML


<!doctype html>
<html>
    <head>
        <script src="https://code.jquery.com/jquery-2.2.2.min.js" integrity="sha256-36cp2Co+/62rEAAYHLmRCPIych47CvdM+uTBJwSzWjI=" crossorigin="anonymous"></script>
    </head>
    <body>
        <div id="parallax"></div>
        <script type="text/javascript">
$(function () {
    $("#parallax").parallax({
        svgFile: "test.svg",
        layers: ["layer-1", "layer-2", "layer-3"]
    });
});
        </script>
    </body>
</html>

指定の要素にYoutubeをはっつける

こんな感じ.

https://jsfiddle.net/0b7dtvqc

Youtube Iframe APIとかいうの使った.

jquery.youtube.js

(function($) {
    $.fn.youtubePlayer = function(options) {

        function loadPlayer(element, settings, callback) {
            $.getScript("//www.youtube.com/iframe_api");
            // スコープ注意
            window.onYouTubeIframeAPIReady = function () {
                var options = {
                    videoId: settings.videoId,
                    playerVars: {
                        rel: 0,
                        controls: 0,
                        showinfo: 0,
                        showsearch: 0,
                        hd: settings.hd ? 1 : 0,
                        wmode: "transparent",
                        loop: settings.loop ? 1 : 0,
                        playlist: ""
                    },
                    events: {
                        onReady: function (e) {
                            player.mute();
                            player.playVideo();
                        },
                        onStateChange: function (e) {
                            if (e.data == 2 || e.data == 0) {
                                player.playVideo();
                            }
                        }
                    }
                };

                player = new YT.Player(element.attr("id"), options);

                callback(player);
            };
        }

        function resizePlayer(element, ratio) {
            element.css({
                width: $(window).width(),
                height: $(window).width() * (1 / ratio)
            });
        }

        var defaults = {
            videoId: "",
            loop: true,
            hd: false,
            ratio: 16/9
        };

        var setting = $.extend(defaults, options);

        var $this = this;

        loadPlayer($this, setting, function (player) {
            $this = $("#" + $this.attr("id"));
        });

        resizePlayer($this, settings.ratio);

        var isResizing = false;
        $(window).resize(function (e) {
            if (isResizing) {
                return;
            }

            resizePlayer($this, settings.ratio);
            
            isResizing = true;

            resizingTimer = setTimeout(function () {
                isResizing = false;
            }, 10);
        });
    }
})(jQuery);

使う側

<div id="player">
</div>

<script type="text/javascript">
$(function () {
	$("#player").youtubePlayer({
  	videoId: "seLF3oCjCv8"
  });
});
</script>

JetDrive 520 240GBを買ってみた

今までは…

MacBookAir 2012 Mid,128GBを使っていたが, 128GB中,125GBを常に使用するというひもじい生活を送っていた.

そこで,買いました

f:id:wait0000:20160301202347j:plain

開けました

f:id:wait0000:20160301202609j:plain f:id:wait0000:20160301202619j:plain f:id:wait0000:20160301202639j:plain f:id:wait0000:20160301202737j:plain

まずはJetDriveにUSB変換コネクタをつなげます

f:id:wait0000:20160301202805j:plain f:id:wait0000:20160301203147j:plain

Macに接続して,ディスクのコピーを行います

f:id:wait0000:20160301203017j:plain

緑に光ったり,青に光ったりします

f:id:wait0000:20160301204508j:plain f:id:wait0000:20160301203728j:plain

もし,Could not recognize /dev/(null)とか言われたら,編集からロックを解除をしましょう

開けます

f:id:wait0000:20160301210435j:plain

取り出します

f:id:wait0000:20160301210759j:plain

装着して完了

f:id:wait0000:20160301210626j:plain

最後にこれを足にはっつけておわり

f:id:wait0000:20160301211355j:plain

幸せ…

f:id:wait0000:20160301221624p:plain

PayPalで定期支払いをする

PayPalでは公式のサンプルコードが手に入り,それを使うことでExpressCheckoutという一番簡単な決済方法を使うことができる. だがPayPalにはもう一つの支払い方法として定期支払い(Recurring)が存在する. 今回はそのメモ.

ちなみに,今回使うpaypalfunctions.phpファイルはここで手に入る.

定期支払い関数を作る

paypalfunctions.phpを編集して,以下のコードを追加する.


    function CallRecurringExpressCheckout( $billingDescription, $currencyCodeType, $paymentType, $returnURL,
                                      $cancelURL)
    {
        //------------------------------------------------------------------------------------------------------------------------------------
        // Construct the parameter string that describes the SetExpressCheckout API call in the shortcut implementation
        
        $nvpstr="&L_BILLINGTYPE0=RecurringPayments";
        $nvpstr = $nvpstr . "&L_BILLINGAGREEMENTDESCRIPTION0=" . $billingDescription;
        $nvpstr = $nvpstr . "&RETURNURL=" . $returnURL;
        $nvpstr = $nvpstr . "&CANCELURL=" . $cancelURL;
        
        $_SESSION["currencyCodeType"] = $currencyCodeType;    
        $_SESSION["PaymentType"] = $paymentType;

        //'--------------------------------------------------------------------------------------------------------------- 
        //' Make the API call to PayPal
        //' If the API call succeded, then redirect the buyer to PayPal to begin to authorize payment.  
        //' If an error occured, show the resulting errors
        //'---------------------------------------------------------------------------------------------------------------
        $resArray=hash_call("SetExpressCheckout", $nvpstr);
        $ack = strtoupper($resArray["ACK"]);
        if($ack=="SUCCESS" || $ack=="SUCCESSWITHWARNING")
        {
            $token = urldecode($resArray["TOKEN"]);
            $_SESSION['TOKEN']=$token;
        }
           
        return $resArray;
    }

    function CreateRecurringPaymentsProfile($fromDate, $description, $amount, $currencyCodeType, $period, $frequency, $token) {
        $nvpstr="&PROFILESTARTDATE=" . $fromDate;
        $nvpstr = $nvpstr . "&CURRENCYCODE=" . $currencyCodeType;
        $nvpstr = $nvpstr . "&AMT=" . $amount;
        $nvpstr = $nvpstr . "&DESC=" . $description;
        $nvpstr = $nvpstr . "&BILLINGPERIOD=" . $period;
        $nvpstr = $nvpstr . "&CURRENCYCODE=" . $currencyCode;
        $nvpstr = $nvpstr . "&BILLINGFREQUENCY=" . $frequency;
        $nvpstr = $nvpstr . "&TOKEN=" . $token;
        
        $_SESSION["currencyCodeType"] = $currencyCodeType;    
        $_SESSION["PaymentType"] = $paymentType;

        //'--------------------------------------------------------------------------------------------------------------- 
        //' Make the API call to PayPal
        //' If the API call succeded, then redirect the buyer to PayPal to begin to authorize payment.  
        //' If an error occured, show the resulting errors
        //'---------------------------------------------------------------------------------------------------------------
        $resArray=hash_call("CreateRecurringPaymentsProfile", $nvpstr);
        $ack = strtoupper($resArray["ACK"]);
        if($ack=="SUCCESS" || $ack=="SUCCESSWITHWARNING")
        {
            $token = urldecode($resArray["TOKEN"]);
            $_SESSION['TOKEN']=$token;
        }
           
        return $resArray;
    }

そして,この関数を呼び出すPHPファイルは以下のように記述する.


      $planAmount = 3980;
      $planDescription = "定期支払い(毎月) ".$planAmount."円";
      $returnURL = "http://localhost/review.php";
      $cancelURL = "http://localhost/";

      // 後で使う
      $_SESSION["desc"]   = $planDescription;
      $_SESSION["amount"] = $planAmount;

        $resArray = CallRecurringExpressCheckout ($planDescription, $currencyCodeType, $paymentType, $returnURL, $cancelURL);

    $ack = strtoupper($resArray["ACK"]);
    if($ack=="SUCCESS" || $ack=="SUCCESSWITHWARNING")
    {
        $token = urldecode($resArray["TOKEN"]);
        $_SESSION['reshash']=$token;
        RedirectToPayPal ( $token );
    } 
    else  
    {
        //Display a user friendly Error on the page using any of the following error information returned by PayPal
        $ErrorCode = urldecode($resArray["L_ERRORCODE0"]);
        $ErrorShortMsg = urldecode($resArray["L_SHORTMESSAGE0"]);
        $ErrorLongMsg = urldecode($resArray["L_LONGMESSAGE0"]);
        $ErrorSeverityCode = urldecode($resArray["L_SEVERITYCODE0"]);
        
        if ($ini["debug"]) {
            echo "SetExpressCheckout API call failed. ";
            echo "Detailed Error Message: " . $ErrorLongMsg;
            echo "Short Error Message: " . $ErrorShortMsg;
            echo "Error Code: " . $ErrorCode;
            echo "Error Severity Code: " . $ErrorSeverityCode;
        }
    }

ちなみにこの段階では定期支払いの期間,料金の設定などは要らないらしい.

そして,GetShipmentDetail関数を呼び出すreview.phpを作成し, その後,定期支払いを確定する以下のPHPスクリプトを作成する.

(POSTでreview.phpからGetShipmentDetailで取得したTOKENを受け取ってる前提)


            $currencyCodeType = "JPY";

            $resArray = CreateRecurringPaymentsProfile((new DateTime())->format("c"), $_SESSION["desc"], $_SESSION["amount"], $currencyCodeType, "Month", 1, $_POST["token"]); // 一ヶ月の定期支払い
            
            $ack = strtoupper($resArray["ACK"]);
            if ($ack == "SUCCESS" || $ack == "SUCCESSWITHWARNING") {
                info("支払いに成功しました.");
            } else {
                fatal("支払いに失敗しました.", var_dump($resArray));
            }

ページのプログレスバーを表示する

二、三時間うーんうーん言ってみたけど良いタイトルが思いつかないので,とりあえず「ページのプログレスバー」と,やつを呼ぶことにする.

こんなやつ. f:id:wait0000:20160213033540p:plain

これをCSSだけで実現したいと思う.

https://jsfiddle.net/ctp4j3zc/2

before擬似要素によって直線を表現し,after要素によってマルポチを表現している. classなしが白抜きの丸,activeが二重丸,disabledが黒丸となっている.

jQueryとSVGでクリッカブルマップ

クリッカブルマップというのは,こんなの.

f:id:wait0000:20160104214251p:plain

今回はクリッカブルという名のもとでクリック機能に対応していないのだが,便宜上クリッカブルマップと呼ぶ. 実際,クリック対応も数行追加するだけで楽々と対応できる.

用意するもの

マップ画像の作成

f:id:wait0000:20160104214800p:plain
inkscapeを使い,適当に日本地図を書く.
そして,inkscapeXMLエディタを開き,各地域,都道府県などにidを追加する.
あとは,PlainSVGとして書き出すだけ.(今回はjapan-map.svgとして書き出した)

jQueryプラグインを書く

jquery.svg-japan-map.js

(function($) {
    $.fn.svgJapanMap = function(options) {

        function composeIdName(prefix, name, area) {
            var id = "#";
            
            if (prefix != "") {
                id += prefix + "-";
            }

            if (name != "") {
                id += name + "-"
            }

            id += area;
            return id;
        }

        var defaults = {
            svgFile: "",
            prefix:  "",
            onHover: function(e) {},
            onOut: function(e) {},
            associated: []
        };
        var setting = $.extend(defaults, options);

        setting.associated.push("");

        // SVGに設定したid
        var areas = [
            "hokkaido",
            "tohoku",
            "kanto",
            "chubu",
            "hokuriku",
            "kansai",
            "chugoku",
            "shikoku",
            "kyushu",
            "okinawa"
        ];

        var $this = this;

        $.get(setting.svgFile, function (data) {
            var in_event = "mouseenter";
            var out_event = "mouseleave";

            // たまにIEでうまく動かない対策
            if (navigator.userAgent.match("MSIE") || navigator.userAgent.match("Trident")) {
                in_event  = "mouseover";
                out_event = "mouseout";
            }

            $this.append($(data.documentElement));

            $.each(areas, function(i, area) {
                $.each(setting.associated, function(j, name) {
                    $(composeIdName(setting.prefix, name, area)).bind(in_event, function (e) {
                        e.areaName = area;
                        setting.onHover(e);

                        $.each(setting.associated, function (k, name2) {
                            $(composeIdName(setting.prefix, name2, area)).css({
                                "opacity": "0.5"
                            });
                        });

                        return false;
                    }).bind(out_event, function(e) {
                        setting.onOut(e);

                        $.each(setting.associated, function (k, name2) {
                            $(composeIdName(setting.prefix, name2, area)).css({
                                "opacity": "1.0"
                            });
                        });

                        return false;
                    });
                });
            });
        });

    };
})(jQuery);

こんな感じでSVGajax的にダウンロードしてDOMに無理やり埋め込む.
こうすることでjQueryのidセレクタを使い,各図形にイベントを設置できる.

今回は,合わせて左の丸や,地域名にも反応させたかったため,associateという設定項目を用意した.
合わせて,各図形にcircle-kanto,text-kantoなどとidを設定した.

使うだけ

<!DOCTYPE html>
<html>
    <head>
        <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
        <script src="./jquery.svg-japan-map.js"></script>
    </head>
    <body>

        <div id="map-holder"></div>
        <div id="map-popup" style="position: absolute; left: -100px; top: 0; width: 100px; height: 30px;"></div>

        <script>
$(document).ready(function() {
    $("#map-holder").svgJapanMap({
        svgFile: "./japan-map.svg",
        prefix: "",
        onHover: function(e) {
            $("#map-popup").text(e.areaName);
            $("#map-popup").css({
                "left": e.clientX + 10,
                "top":  e.clientY + 10
            });
        },
        onOut: function(e) {
            $("#map-popup").css({
                "left": -100,
                "top":  0
            });
        },
        associated: ["circle","text"]
    });
});
        </script>

    </body>
</html>

こんなコードを書いて完成.無事,ホバーに反応する日本地図ができた.