JavaScriptのテンプレート文字列について

開発部のS.Kです。

今回は、JavaScriptのテンプレート文字列について紹介します。

これはECMAScript6で組み込まれた新しい機能です。 他にも様々な機能が追加されていますが、テンプレート文字列は汎用性が高く、様々な場面で使える機能です。

「`」(バッククォート)で囲うと利用できます。 内部に変数などを埋め込んで表示できるのが特徴です。

例えば、以前は文字列の途中で変数を入れるにはこのように書いていました。

var name = 'GSOL';
console.log('Hello ' + name + ' !!');

これをテンプレート文字列にすると、

var name = 'GSOL';
console.log(`Hello ${name} !!`);

と書けます。

地味ですが、きれいに書けるので開発者的には嬉しい機能です。

以上、簡単ですがテンプレート文字列の紹介でした。

markdownエディタの紹介

今回は、markdownエディタについて紹介します。

markdownは書きやすくで便利なので、よく使っています。 しかしローカル上のmarkdownファイルを編集するエディタは、意外と定番のものが無い気がします。 なので個人的に使ってみたmarkdownエディタを紹介してみます。

Haroopad

非常にシンプルで使いやすいと思います。 メモ帳にmarkdownのプレビュー画面が追加されたような感じです。 後述するAtomなどは多機能でタブなども使えますが、もっとシンプルに使うならこちらのほうが良いと思います。 すこしフォントが微妙ですが、設定で変えることができます。

Atom

markdown専用のエディタではなく、様々なプログラミング言語の編集に使えるエディタです。 多機能でカスタマイズも柔軟にでき、様々な機能の追加パッケージが公開されています。

Typora

markdownかつWYSIWYGというユニークなエディタです。 markdownの記法を書くと、自動的に表示が更新されていきます。 普段直接markdownを書くとテーブルなどが少し書きづらいのですが、Typoraはテーブルを作ると専用の操作メニューが表示されて、非常に簡単に編集ができるようになっています。 いきなり表示が更新されることなどから、若干操作しにくい感じはありますが、おもしろいエディタだと思います。

markdownエディタの紹介は以上です。

markdownはシンプルで覚えやすく、日常のメモ書きから開発資料まで幅広く役立ちます。 このブログも含めてmarkdownで書けるサービスも数多くありますので、試してみてはいかがでしょうか。

自社githubアカウントの紹介

開発部のTです。

自社githubアカウントについて簡単に紹介しようと思います。

自社githubアカウント

github.com

github上で公開しているリポジトリ

自社intra-martソリューション関係

IMBoxデスクトップ通知、iACスケジュール連携ソリューションのユーティリティやプラグインgithub上に公開しています。

PeerJS

PeerJSからForkして一部修正を加えてます。 Web会議ソリューションのSignalingサーバー使用しています。

Dockerfile

社内の開発等に使用しているDockerfileを公開しています。 Docker Hubでimageも公開してます。自社Docker Hubのページ

以上、自社github(とDocker Hub)アカウントの簡単な紹介でした。

react.jsの入門書を購入しました

開発部のTです。

以前から探していたReactの入門書が先日発売したので、 会社の経費で1冊購入しました。 (お願いしたら二つ返事で購入してくれる会社に感謝です)

WebデベロッパーのためのReact開発入門 JavaScript UIライブラリの基本と活用

WebデベロッパーのためのReact開発入門 JavaScript UIライブラリの基本と活用

Reactって何?って開発メンバーもまだいるような状況なので、 この本でReactの基本を固めてサービス開発を進めていきたいと思います。

現在WantedlyでReactを使ってサービスの開発したい方を募集してますので、 興味がある方はぜひ応募してみてください。 上で書いたように社内は現在React勉強中なので、 Reactに興味があって少し触ったことのあるレベルの方でも大歓迎です。

www.wantedly.com

HTML5の新機能紹介 ~WebStorage~

開発部のMです。

今回は、HTML5で導入された新機能の1つ、WebStorageについての紹介です。

WebStorageとは

WebStorageとは、HTML5で導入されたブラウザでデータの永続化を行う仕組みのことです。 特徴としては、 * 比較的大容量の文字列データを保存できる * Key-Value型のシンプルなインターフェイス * 保存/取得処理に通信を伴わない などがあります。 今までは、毎回サーバにアクセスし、保存/取得処理されていたブラウザ固有のデータをブラウザ内で完結させることができます。 また、最近使われている大多数のブラウザで使用できる(ChromeFireFoxSafariOpera、IE8~)ので、安心して使えます。

Cookieとの違い

WebStorageと似た技術で、今まではCookieがありました。違いについて、簡単にまとめてみました。 (localStorageとsessionStorageの違いは、後で説明しています)

WebStorage Cookie
Origin毎の保存容量 5MB (仕様上) 4KB
有効期限 なし (localStorage) あり
通信 jsで実装する必要がある 勝手に送信される
個数制限 なし 20個 (仕様上)
pathの設定 Originで共通 できる
標準API 比較的簡単 煩雑な文字列操作
ウィンドウ間でのデータの共有 できる (localStorage) できる
スコープ Origin単位 host/path単位

有効期限を設定したい場合や常にデータを送信したい場合、特定のpath以下のみのアクセスを許可したい場合など、 Cookieでしかできないこともありますが、データ保存に関しては、WebStorageに利点が多いです。

WebStorageの種類

WebStorageには、用途に応じて2種類のストレージが用意されています。違いについて、簡単にまとめてみました。

locakStorage sessionStorage
有効期限 なし(削除されるまで) ウィンドウ(タブ)を閉じるまで
ウィンドウ(タブ)間での
データの共有
できる できない

基本的な機能については、共通です。1点だけ異なっており、
localStorageは、Origin(scheme://hostname:port/)にスコープしており、
sessionStorageは、更にTop-level browsing context(ウィンドウ、タブなど)にスコープした Storageである点が差異です。(※sessionStorageは、Webアプリなどのログインセッションとは同期してないです)

用途としては、localStorageはデータの永続化、sessionStorageは一時データの保存になると思います。

WebStorageの使い方

コードを示しながら、説明します。 (localStorageもsessionStorageも同じインターフェイスを備えてます。ここでは、sessionStorageをサンプルとします。)

// sessionStorageが使えるかどうか
if (typeof sessionStorage === 'undefined')
    alert('sessionStorage is not found');

// 文字列データの操作は、hashを操作するように行えます。
sessionStorage['key'] = 'value';
console.log(sessionStorage['key']); // => 'value'
// 次の書き方もできます
//sessionStorage.setItem('key', 'value');
//console.log(sessionStorage.getItem('key'));
//sessionStorage.key = 'value';
//console.log(sessionStorage.key);

// Objectの保存には、JSON.stringifyなどで、シリアライズする必要があります。
sessionStorage['objKey'] = JSON.stringify({key: [1, 2, 3]});
// 取得時には、デシリアライズしてください。
console.log(JSON.parse(sessionStorage['objKey'])); // => {key: [1, 2, 3]}

// データを消したいとき、次のようにできます。
//sessionStorage.clear(); // 全件削除(Originに紐づく全件が削除されるので注意)
sessionStorage.removeItem('key'); // 'key'で登録されているデータが削除されます
// OriginでStorageが共有されているので、次のようにnamespaceを分けると削除しやすいです。
sessionStorage['prefix.key'] = 'value'; // 一意なprefixを付加
Object.keys(sessionStorage)  // -> ['objKey', 'prefix.key']
      .filter(function(k) { // prefixが一致するデータをfilter
          return k.split('.')[0] === 'prefix';
      }).each(function(k) { // filterされたデータを削除
          sessionStorage.removeItem(k);
      });

// その他のStorage interface
// n番目のkeyを戻します
sessionStorage.key(0); // -> 'objKey'
// Storageに保存されている件数(正確には、Storage自体のinterfaceではないですが)
sessionStorage.length; // -> 1
// 登録されているkeyの一覧
Object.keys(sessionStorage); // -> ['objKey']

// 他のタブからStorageの変更があった場合、eventが発火します
// (sessionStorageは仕様上、発火しないので、localStorageをサンプルにします)
localStorage['key'] = 'old';
// listenerを設定
window.addEventListener('storage', function(e) {
    console.log(e);
});
// 他のタブから
// localStorage['key'] = 'new';
// 登録、更新、削除など、Storageに変更があれば、eventが発火します
// => key: 'key', newValue: 'new', oldValue: 'old', ...

※Storageのデータは、Originで共有されるので、複数の機能で使用する場合、削除や上書きに気をつけてください。

使い分け

Cookie、localStorage、sessionStorageの違いを簡単に説明してきました。ここでは、それぞれの用途について考察してみたいと思います。

Cookie

容量が少なく、常にサーバとデータを共有しているCookieはログインセッションの管理が主な用途になると思います。

localStorage

ブラウザ毎にデータを永続的に保存できるので、設定の保存目的や、大容量なのを活かし、下書き保存などに使えると思います。 また、Storage変更時に、eventが発火するので、タブ間の同期などにも使えます。

sessionStorage

タブ毎にスコープが分かれているので、タブで行った作業結果の一時保存や、タブを閉じたあと必要がない閲覧情報などの保存に使えると思います。

まとめ

HTML5で導入されたWebStorageについて、Cookieとの比較を行い説明しました。 また、使い方について、サンプルコードを元に説明を行いました。 サーバに送らなくてもいいデータなどの保存に使用すると、画面遷移の高速化が期待できます。 サーバとの無駄な通信量が多い時などいかがでしょうか?

複数のバージョンのjQueryを読んでしまったときの共存のさせ方

新人のMです。今週もよろしくお願いします。

今回は、複数のバージョンのjQueryを読まないといけないときの対処方法について書きたいと思います。1.7系でしか動かないコードがあるけど、1.10系も使ってみたい場合やajaxで取得したページにjQueryを再取得してしまってる場合などにお試しください(※推奨できる方法ではないので、実装を見直すべきですが)

2個目のjQueryを読む前に処理したい場合

古いjQueryを別の変数に退避させて、新しいjQueryを読む方法です。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
$old = jQuery;
</script>

<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
console.log($old().jquery); // => 1.7.2
console.log($().jquery); // => 1.10.2
console.log(jQuery().jquery); // => 1.10.2
</script>

2個目のjQueryを読んだあとに処理したい場合

新しいjQueryを読んだあとに、noConflict([removeAll])で古いjQueryを復活させる方法です。removeAllのオプションにtrueを渡すと$オブジェクトだけではなく、jQueryのオブジェクトも元に戻されます。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>

<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
$new = jQuery.noConflict(true);
console.log($().jquery); // => 1.7.2
console.log(jQuery().jquery);
// removeAll is true => 1.7.2
// removeAll is false => 1.10.2
console.log($new().jquery); // => 1.10.2
</script>

まとめ

複数のバージョンのjQueryを読まないといけないときの対処方法について紹介しました。どうしても複数のバージョンのjQueryを共存させないといけないときなどにご活用ください。

javascriptで日付を扱うときに便利なmoment.jsの紹介

新人のMです。 このアドベントカレンダーもなんとか1周間続けることができました。残り3週間がんばっていきたいと思います。

今回は、javascriptで日時を扱うときに便利なライブラリの紹介を行いたいと思います。 javascriptにもDateオブジェクトはあるのですが、使いづらく簡単な処理であればStringで代用してしまったりします。そこで、試してみたいのが、今回紹介するmoment.jsです。

momentオブジェクト生成

日時情報を保持するオブジェクトです。任意のフォーマットパターンで日時文字列をparseすることができます。

moment();
// => 現在日時のオブジェクト

moment("2013/12/8", "YYYY/M/D");
moment("Dec 8, 2013", "MMM D, YYYY");
moment("8 12 2013", "D M YYYY");
// => 2013年12月8日のオブジェクト

フォーマット出力

任意のフォーマットパターンでStringを出力できます。

moment().format("MMM D YYYY ddd, hh:mm:ss a Z");
// => "Dec 8 2013 Sun, 09:05:04 pm +09:00"

日本語化

langs付きのmomentなら、lang("ja")で日本語に出力してくれます。また、langの設定を別に行うこともできます。

moment.lang("ja", {
    weekdaysShort: ["日","月","火","水","木","金","土"]
});
moment.format("ddd");
// => 日

まとめ

javascriptで日時を扱うときに便利なライブラリであるmoment.jsの簡単な紹介を行いました。 moment.jsには、他にも日付のマニピュレーションの機能が豊富にあったりするので、日付関係で困ったときは試してみてはいかがでしょう。

javascriptでもpythonのdecoratorを使いたい

新人のMです。 学生時代は、pythonをいじってたりしたので、今回はpythonの機能からjsで実装できそうなものを作ってみたいと思います。

pythonのdecorator

関数の処理の前後に任意の処理を飾り付けれる機能のことです。いわいるデコレータパターンだと思います。

def deco(opt):
    def wrapper(func):
        def impl(*args, **kwargs):
            print args, kwargs, opt
            print "before"
            r = func(*args, **kwargs)
            print "after"
            return r + opt
        return impl
    return wrapper

@deco(1)
def f(a):
    print a
    return a
f(2)
=> 3

javascriptでの実装

var deco = function() {
    var args = arguments;
    var wrapper = function(fn) {
        var impl = function() {
            console.log("decorator arg", args, "wraper arg", arguments);
            console.log("preprocess");
            var r = fn.apply(this, Array.prototype.slice.call(arguments));
            console.log("postprocess");
            return r + ":" + Array.prototype.join.call(args);
        }
        return impl;
    }
    return wrapper;
};

var f = deco(1)(function() {
        console.log(arguments);
        return Array.prototype.join.call(arguments);
f(2, 3);
=> "2,3:1"

まとめ

javascriptpythonのdecoratorを実装例を示してみました。 デコレータを使うことで、定型的な前処理・後処理をまめることができると思います。

CSSでくるくる回るアニメーション

新人のMです。 ネタ探しが大変です… 今日もCSSについて書こうと思います。 CSSアニメーションが簡単にアニメーションを表現できそうで興味があるので、試しに簡単なインジケータをCSSの@keyframesを使って作ってみたいと思います。

@keyframes

ある時点での状態を指定したキーフレームを複数用意することでアニメーションを表現します。

@keyframes 名前 {
    0% {}
    100% {
        transform: rotate(360deg);
    }
}

くるくる回るインジケータ

<html>
<head>
<style type="text/css">
@-webkit-keyframes anime {
    0% {}
    100% {
        -webkit-transform: rotate(360deg);
    }
}
.indicator {
    display: inline-block;
    position: relative;
    background: pink;
    margin-left: 50px;
    width: 20px;
    height: 100px;
    -webkit-border-radius: 5px;
    -webkit-animation: anime 3s infinite linear;
}
.indicator:before, .indicator:after{
    content: "";
    width: 20px;
    height: 100px;
    position: absolute;
    background: pink;
    opacity: 0.3;
    -webkit-border-radius: 5px;
    -webkit-transform: rotate(-60deg);
}
.indicator:after {
    opacity: 0.7;
    -webkit-transform: rotate(60deg);
}
</style>
</head>
<body>
    <div class="indicator"></div>
</body>
</html>

単調にオブジェクトが1回転するアニメーションを定義し、それを3秒で1回行うように設定しました。残像を表現したくて、バーの前後に薄いバーを追従させるようにしてみたのですが、同じスピードで回してるからか、残像ぽくないですね…(色をピンクにしたら、花が回ってるようでかわいいので、これはこれでありですが) ※Chrome以外で試すときは、ベンダープリフィックス(-webkit-)を各ブラウザのものに書き換えてください。

まとめ

CSS3の@keyframesを使うことで、CSSだけでアニメーションを実装しました。

:before擬似要素と:after擬似要素

新人のMです。 毎日ネタ考えるの大変ですね。

jsの話が続いてるので、今日はCSSの話にしてみたいと思います。

:before擬似要素と:after擬似要素

対象の要素の前後に擬似的な内容を追加してくれる擬似要素です

このような形で指定すると、「beforePafter]のように表示されます。

<html>
<head>
<style type="text/css">
p:before {
    content: "before";
}
p:after {
    content: "after";
}
</style>
</head>
<body>
    <p>P</p>
</body>
</html>

contentには、文字列の他に、URL(画像)、要素の属性値、カウンタが指定できます。 例えば、リンクの前にアイコンを表示させたり、リンクの後ろにURLを表示させたり、タイトルの前後に飾りをつけたりするのに使えます。

簡単Tooltip

:hover擬似クラスといっしょに使うと簡単にTooltipが実装できたりします。

<html>
<head>
<style type="text/css">
.content {
    display: inline;
    position: relative;
}
.content:hover:after {
    content: attr(data-content);
    background: yellow;
    position: absolute;
    top: 50%;
    left 50%;
}
</style>
</head>
<body>
   <p class="content" data-content="content">P</p>
</body>
</html>

要素にマウスをかざすと、説明が要素の上に表示されます。

まとめ

:before擬似要素と:after擬似要素の簡単な紹介を行いました。 簡単なTooltipの作り方の紹介を行いました。

event.curretTargetとevent.targetの違い

新人のMです。 今回も短めの記事で行きます。

イベントが発火した要素の取得の仕方

イベントが発火したときに、イベントリスナにイベントオブジェクト(最初の引数)が渡されます。 このオブジェクトにどの要素でイベントが発火したのか示すプロパティが2種類あります。 その2種類event.currentTargetとevent.targetの違いについて見て行きたいと思います。

エレメント.addEventListener(イベント, function(e) {}, false);
$(セレクタ).on(イベント, function(e) {});

event.currentTarget

イベントリスナをバインドした要素をイベントが通過した時の要素(イベントリスナがバインドされてる要素自身)を表します

event.target

イベントが発生した要素を表します。

以下の例で説明します。 青い部分をクリックすると、".outer"にバインドしたイベントリスナに「currentTarget=".outer"」、「target=".outer"」なイベントオブジェクトが渡されます。 他の色の部分をクリックすると、".inner"にバインドしたイベントリスナに「currentTarget=".inner"」、「target=".inner"」なイベントオブジェクト、".outer"にバインドしたイベントリスナに「currentTarget=".outer"」、「target=".inner"」なイベントオブジェクトが渡されます。

<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<style type="text/css">
.outer {
    width: 100px;
    height: 100px;
    background: blue;
}
.inner {
    width: 50px;
    height: 25px;
}
.inner:nth-child(1) {
    background: pink;
}
.inner:nth-child(2) {
    background: purple;
}
.inner:nth-child(3) {
    background: orange;
}
.inner:nth-child(4) {
    background: green;
}
</style>
<script type="text/javascript">
$(document).on("click", ".outer", function(e) {console.log(e.currentTarget, e.target);});
$(document).on("click", ".inner", function(e) {console.log(e.currentTarget, e.target);});
</script>
</head>

<body>
    <div class="outer">
        <div class="inner"></div>
        <div class="inner"></div>
        <div class="inner"></div>
        <div class="inner"></div>
    </div>
</body>
</html>

まとめ

event.currentTargetとevent.targetの違いについて見てみました。 currentTarget=バインドした要素、target=イベントが発生した要素と覚えておくと簡単かと思います。 currentTargetのほうがバインドした要素を表しているのでイベントリスナを書くときには、わかりやすいと思います。

underscore.jsで気になる関数(Functions、Objects、Utility、Chaining編)

前回の続きです。今日はUnderscore.jsのFunctions、Objectsを中心に見ていきます。

Functions

FPぽいことするのに便利な関数が揃ってます。

_.memoize(function, [hashFunction])

メモ化関数です。関数の計算結果を記憶しておいて、再計算のコストを低くしてくれます。フィボナッチ数列を計算するのに便利そうです。

var fibonacci = _.memoize(function(n) {
  return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});

_.once(function)

関数を一度しか計算しない。初期化処理とかに便利そうです。

var initialize = _.once(createApplication);
initialize();
initialize();
// Application is only created once.

_.after(count, function)

count回関数が呼び出されて初めて、関数が実行されます。非同期の処理実行後に処理を行いたいときに便利そうです。

var renderNotes = _.after(notes.length, render);
_.each(notes, function(note) {
  note.asyncSave({success: renderNotes});
});
// renderNotes is run once, after all notes have saved.

_.wrap(function, wrapper)

関数の前後に処理を行えます。pythonのdecoratorぽいことができそう?

var hello = function(name) { return "hello: " + name; };
hello = _.wrap(hello, function(func) {
  return "before, " + func("moe") + ", after";
});
hello();
=> 'before, hello: moe, after'

_.compose(*functions)

関数合成をしてくれる関数です。かっこたくさん書かなくていいのは、楽です。

var greet    = function(name){ return "hi: " + name; };
var exclaim  = function(statement){ return statement.toUpperCase() + "!"; };
var welcome = _.compose(greet, exclaim);
welcome('moe');
=> 'hi: MOE!'

Objects

_.omit(object, *keys)

keysに指定したプロパティを除外してくれます。chainで使うと便利です。

_.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid');
=> {name: 'moe', age: 50}

_.defaults(object, *defaults)

デフォルトのプロパティを設定してくれます。

var iceCream = {flavor: "chocolate"};
_.defaults(iceCream, {flavor: "vanilla", sprinkles: "lots"});
=> {flavor: "chocolate", sprinkles: "lots"}

_.tap(object, interceptor)

_chainといっしょに使うと便利です。計算途中の確認に使えます。

_.chain([1,2,3,200])
  .filter(function(num) { return num % 2 == 0; })
  .tap(alert)
  .map(function(num) { return num * num })
  .value();
=> // [2, 200] (alerted)
=> [4, 40000]

Utility

_.result(object, property)

objectのpropertyが関数なら結果を返して、値ならその値を返してくれます。

var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
_.result(object, 'cheese');
=> "crumpets"
_.result(object, 'stuff');
=> "nonsense"

Chaining

underscore関数がメソッドチェーンできるので便利です。

var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
var youngest = _.chain(stooges)
  .sortBy(function(stooge){ return stooge.age; })
  .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
  .first()
  .value();
=> "moe is 21"

まとめ

2回にわたって、javascriptのユーティリティライブラリであるunderscore.jsのおもしろそうな関数の紹介を行いました。 underscore.jsは、ファイルサイズが小さく(minify&gzipで4.9kb)、実績も豊富(bakcbone.jsの依存ライブラリなのでHulu、foursquareなど)、ドキュメントもわかりやすく、おすすめです。

underscore.jsで気になる関数(collections、arrays編)

2回目にして、もうネタ切れ気味になってきた新人のMです。

ネタ切れ気味なので、今日は軽めにUnderscore.jsで気に入ってる関数を幾つか紹介します。

Collections

一般的なmap・reduce・filter系ですが、jsのmap関数はArrayのメソッドだったりするので、Hashにも適用できるのは便利です。特に便利だと思うものをピックアップします。

_.pluck(list, propertyName)

プロパティ名に指定したものをmapしてくれます。

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.pluck(stooges, 'name');
=> ["moe", "larry", "curly"]

_.groupBy(list, iterator, [context])系

iteratorの返り値でグルーピングしてくれます。

_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
=> {1: [1.3], 2: [2.1, 2.4]}

_.groupBy(['one', 'two', 'three'], 'length');
=> {3: ["one", "two"], 5: ["three"]}

var stooges = [{name: 'moe', age: 40}, {name: 'larry', age: 50}, {name: 'curly', age: 60}];
_.indexBy(stooges, 'age');
=> {
  "40": {name: 'moe', age: 40},
  "50": {name: 'larry', age: 50},
  "60": {name: 'curly', age: 60}
}

_.countBy([1, 2, 3, 4, 5], function(num) {
  return num % 2 == 0 ? 'even': 'odd';
});
=> {odd: 3, even: 2}

Arrays

_.without(array, [*values])

arrayからvaluesに含まれるものを除外したArrayを返してくれます。chainで使うと便利です。

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
=> [2, 3, 4]

_.union(*arrays)

和を取ってくれます

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]

_.intersection(*arrays)

積を取ってくれます

_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]

_.difference(array, *others)

差を取ってくれます。処理の前後で追加・削除の検出に便利です。

_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]

_.uniq(array, [isSorted], [iterator])

重複を取ってくれます

_.uniq([1, 2, 1, 3, 1, 4]);
=> [1, 2, 3, 4]

_.range([start], stop, [step])

一般的なrange関数です

_.range(10);
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11);
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5);
=> [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1);
=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0);
=> []

一旦まとめ

Functions、Objects、Utilityにも便利な関数がたくさんあるのですが、長くなりそうなので、今日はこのへんで。

Collections、Arraysには最近の言語だと標準関数で備わってるものが多いですが、今のjsだと使いにくいものも多いので、こういったライブラリで補完すると大変楽です。

underscore.jsは、一般的に使われてる便利なutilityライブラリです。聞いたことあるけど、まだ使ってないって方はこの機会に導入を検討してみてはいかがでしょうか?

セレクトボックスのoptionを書き換えるjQueryプラグイン

こんにちは、こんばんは、新人のMです。 アドベントカレンダーを始めたはいいものの12/1が終わるまで時間がないので、簡単なネタで行きたいと思います。

セレクトボックスの内容を動的に書き換えたいことが、よくあるのですが、そんなときに使えるjQueryプラグインを書いてみました。 数十行なので読んでいただいたら、わかると思いますが、すこし説明します。

使い方

こんな感じに、hashの配列を渡してあげると、指定したセレクトボックスのoptionを書き換えてくれます。

var a = [
    { text: "a", value: "1"},
    { text: "b", value: "2", "data-b-c": "b"},
    { text: "c", value: "3", selected: true}
];
$("select").simpleOptions(a);

書き換えてくれる属性は、今のところ以下のものになります。

  • text
  • value
  • selected
  • disabled
  • data-*

他の属性も書き換えたいときは、適宜コードに追加してくだい。

セレクトボックスのvalueが変わったら、changeイベントを発火するようにしてあります。

コード

2番目のスクリプトタグ内のコードをコピペしてお試しください。

<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
(function($) {
    var simpleOptions = function(arr) {
        var $options = this.find("option");
        var selected = this.val();
        var diff = arr.length - $options.length;

        if (diff < 0) $options.slice(diff).remove();
        else if (diff > 0) {
            var fragment = document.createDocumentFragment();
            for (var i = diff; i; --i)
                fragment.appendChild(document.createElement("option"));
            this.append(fragment);
        }
        var some = arr.some(function(v) { return !!v.selected;});
        this.find("option").each(function(i, v) {
            v.value = arr[i].value;
            v.text = arr[i].text;
            v.selected = some ? !!arr[i].selected : ""+arr[i].value === selected;
            v.disabled = !!arr[i].disabled;
            for (var k in v.dataset)
                delete v.dataset[k];
            for (var k in arr[i])
                if (/^data-.+/.test(k))
                    v.setAttribute(k, arr[i][k]);
        });
        if (this.val() !== selected) this.change();
        return this;
    };

    $.fn.simpleOptions = simpleOptions;
})(jQuery);
</script>

<script type="text/javascript">
$(function() {
    $("select").on("change", function() {console.log(this);});
    var a = [
        { text: "a", value: "1"},
        { text: "b", value: "2", "data-b-c": "b"},
        { text: "c", value: "3", selected: true}
    ];
    $("select").simpleOptions(a);
});
</script>
</head>

<body>
    <select style="width: 100px">
        <option data-test="test"></option>
        <option data-test="test"></option>
        <option data-test="test"></option>
        <option data-test="test"></option>
    </select>
</body>
</html>

注意

DOMを使いまわしてるので、option自体に何かイベントを割り当てたときは、正しく動作しないので、ご注意ください。

まとめ

セレクトボックスのoptionを書き換えてくれるjQueryプラグインを作りました。 やっつけ感はありますが、大抵の場合はこれで事足りると思います。(アドバイスがあればお願いします)

GSOLエンジニアblog はじめました。

はじめまして、GSOLエンジニアblogの運用を任されたMです。

この度、遅ればせながら、グローバル・ソリューションズにおいてもエンジニアblogを開設することとなりました。このblogでは、弊社エンジニアが、開発時のTipsやノウハウ、興味ある技術、弊社の製品の紹介などを書いていく予定です。

このblogをきっかけに、弊社のことにご興味をもっていただけたら幸いです。
よろしくお願いします。


12月といえば技術系blogでは、アドベントカレンダーの季節ですね。弊社(むしろ私個人)としてもこの流れに乗っておきたいなと思い、1エントリ目の記事からアドベントカレンダーの記事としていと思います。
それでは、はじめます。