bata's log

フロントエンド系のTipsとかメモ

EmmetでHTML5の閉じタグが削除されてしまう問題

SublimeTextでHTMLコーディングをする場合、(個人的な見解として)Emmetは必須パッケージですが、HTML5で(control + e)した場合に<img /><br />の閉じタグのスラッシュを削除してしまいます。

<!-- xhtmlの場合 -->
<img src="" alt="" />

<!-- html5の場合 -->
<img src="" alt="">

html5は閉じタグを入れなくてもOKなのですが、閉じタグを入れる派の人にとっては面倒なデフォルト設定なのでユーザー設定で閉じタグを入れるように設定しました。

解決方法

Sublime Text -> Preference -> Package Settings -> Emmet -> Settings - User
上記メニューで開いたEmmet.sublime-settingsに下記の記述を追加します。

{
    "syntaxProfiles": {
        "html": {
            "self_closing_tag": "xhtml"
        }
    }
}

これでOKです。
Sublime Textはソースコードを読めば大概の事は解決できるので本当に使いやすいです。


余談ですがUserのEmmet.sublime-Settingsに設定を追加する場合は、デフォルトのファイルのカスタマイズ部分をコピーしてしまってから編集するとよいと思います。

{

    ///////////////////////////////
    // Emmet customization
    // Each section has the same meaning as the same-named JSON file
    // described here:
    // http://docs.emmet.io/customization/
    ///////////////////////////////


    // Custom snippets definitions, as per https://github.com/emmetio/emmet/blob/master/snippets.json
    "snippets": {
        "variables": {
            "lang": "ja",
            "locale": "ja-JP",
            "charset": "UTF-8",
            "indentation": "\t",
            "newline": "\n"
        },

        "html": {
            // "abbreviations": {
            //     "example": "<div class='example' title='Custom element example'>"
            // }
            "snippets": {
                "script": "<script type=\"text/javascript\" src=\"\"></script>",
                "php": "<?php  ?>"
            }
        }
    },

    // Emmet preferences
    // List of all available preferences:
    // http://docs.emmet.io/customization/preferences/
    "preferences": {
        // "css.valueSeparator": ": ",
        // "css.propertyEnd": ";"
    },

    // Output profiles for syntaxes
    // http://docs.emmet.io/customization/syntax-profiles/
    "syntaxProfiles": {
        // Enable XHTML dialect for HTML syntax
        // "html": "xhtml"
        //
        // Write chained CSS abbreviations on single line:
        // "css": "css_line"
        "html": {
            "self_closing_tag": "xhtml"
        }
    }
}

nodebrewでバージョン管理してる場合にSublimeText3でCSScombが動かない問題

SublimeTextにCSScombというめちゃくちゃ便利なパッケージがあります。CSScombはNode.jsで動いているので、使うときはNode.jsをインストールする必要があります。

CSScomb JS を Sublime Text 3 で使ってみる | Web Design Leaves
※記事では「CSScomb js」となっていますが現在は「CSScomb」と表示されるようです。

ところがNode.jsをnodebrewで管理している場合、パッケージをインストールしてもCSScombが動いてくれません。

ググっても情報が出てこないので、パッケージ内のファイルを調べているとREADMEにこのような記述がありました。
Package/CSScomb/README.md

### Caveats

If node has been installed with NVM you need to make a symlink to node in `/usr/local/bin`. Using OS X, the binary path would typically be `/Users/[your name]/.nvm/[node version]/bin/node`.

英語は苦手なのですが、Node.jsのバージョン管理ツールNVMを使っているときはシンボリックリンクを貼る必要がありますよ、と書いてあるようです。

解決方法

この情報を参考に下記コマンドでシンボリックリンクを作成したところ、CSScombがうまく動いてくれました。

$ li -s ~/.nodebrew/current/bin/node /usr/local/bin/node

なんとか解決できました。

スクロールすると表示されるナビゲーション

スクロール型のナビゲーションがあるサイトで、一定の位置までスクロールするとナビゲーションが固定で出てくるサイトがあります。

こういうの↓
http://gion-renge.jp/

これが結構よく使う演出なので使いまわせるように書いてみました。

function NavControl(el,position,height,time,easing){
    this.$el = $(el);
    this.position = position;
    this.height = height;
    this.time = time || 200;
    this.easing = easing || 'linear';
    this.$window = $(window);
    this.event();
}

NavControl.prototype = {

    event: function(){
        var that = this;
        this.$window.on('scroll', function(){
            var scrollTop = that.getScrollTop(this);
            that.decidePosition(scrollTop);
        });
    },

    getScrollTop: function(self){
        return $(self).scrollTop();
    },

    decidePosition: function(scrollTop){
        if( scrollTop > this.position ){
            this.animation(0);
        }else{
            this.animation(this.height);
        }
    },

    animation: function(n){
        this.$el.stop().animate({top: n}, this.time, this.easing);
    }
}

実行

$(function(){
    //init
    new NavControl('selector', 136, -50);
});

初期化して実行します。
第1引数にセレクター、第2引数にナビゲーションが表示されるスクロール位置、第3引数にナビゲーションのTOPの値(隠れている時のTOPの値)を設定して使用します。

第4引数はアニメーションのスピード、第5引数はイージングを設定しますが、設定無しでも動作します。

ユーザーエージェントを判定する

ユーザーエージェントを判定する簡単なユーティリティを作ってみた。

function DecideUA(){
    this.name = window.navigator.userAgent.toLowerCase();
}

DecideUA.prototype = {

    match: function(str){
        return (this.name.indexOf(str) !== -1);
    }

}

使い方

match()メソッドの引数に判定したいデバイスの文字列を入れるとture,falseで返ってきます。

//init
var ua = new DecideUA();

if(ua.match('iphone')){
    console.log('このデバイスはiPhoneです。');
}else if(ua.match('android')){
    console.log('このデバイスはAndroidです。');
}

JavaScriptでクラス継承みたいなものをやってみる

JavaScriptにはそもそもクラスなんてないし~(ry、とかプロトタイプチェーンが~(ryとかの話はひとまずスルーして、実際に使用出来そうなクラス継承を考えてみた。

クラスを継承する

クラスの継承は.call()関数や.apply関数を使用します。

function A(n){
    this.n = n;
    this.n10 = n * 10;
}

A.prototype.hoge = function(){
    return this.n + this.n10
}

function B(n){
    //Aクラスを継承
    A.call(this,n);
    //Bクラスのプロパティ
    this.n = n+n
}

//init
var b = new B(1);
console.log(b.n,b.n10) //2,10

BクラスでAクラスのプロパティthis.n10を使うことが出来るようになります。

prototypeに追加したメソッドを継承する

上記でクラスのプロパティを継承できましたが、これだけではprototypeに追加したメソッドを継承する事はできません。継承元クラスのインスタンスを継承先のprototypeに代入して、BクラスからAクラスのメソッドを使用できるようにします。

~~~
//プロトタイプにインスタンスを代入
B.prototype = new A();

//プロトタイプを代入する場合(※追記)
//B.prototype = A.prototype;

//init
var b = new B(1);
console.log(b.hoge()); //12

本来Bクラスにはないメソッドhoge()が使用可能になります。
(※追記)A.prototypeを代入してしまってもOKですね、これ。

↑は継承では無いとのご指摘あったので、、、確かに階層構造にはなってない。

http://qiita.com/LightSpeedC/items/d307d809ecf2710bd957
こちらが参考になりました。
両方共やっちゃいけないに分類されてるな...

おまけ

メソッド名が被った場合に継承先を優先させるように(上書きされないように)マージする方法です。

~~~
//オブジェクトをマージする関数
function merge(dest, base) {
    //継承元にオブジェクトがない場合
    if (!base) {
        base = {};
    }
    for (var prop in base) {
        //継承元にプロパティが存在し、かつ継承先にプロパティがない場合にマージ
        if (base.hasOwnProperty(prop) && !dest.hasOwnProperty(prop)) {
            dest[prop] = base[prop];
        }
    }
};

//A.prototypeをB.prototypeにマージする
merge(B.prototype,A.prototype);

//init
var b = new B(1);
console.log(b.hoge()); //12;