geek-logo.jpg

メモをとるのは面倒くさいし、検索するのも面倒くさい。散らかるブックマークも好きじゃない・・・そんな理由も何かにつながる

久しぶりの「IEで見れないんだけど・・・」

久しぶりに聞いたフレーズ。

document.querySelectorAllなどで取得したNodeListのループ処理。
何も考えずにArray.forEachしてましたが・・・対応してないのね・・・(汗

調べてみると結構あるみたいね。
いろんなやり方があるみたいだけど、再利用も考えて配列に変換。

var list = Array.prototype.slice.call( nodeList, 0 );
list.forEach( function(e){
   console.log(e);
});

解決しました。

クロージャ

ここ最近、クロージャやら、即時関数やらを多様するようになってきた。
が、初歩的なミスを犯してしまったので、戒めとしてメモ。


例)Aタグのマウスオーバー時の色の変更(スタイルシートでいいじゃないか・・は言わないで)
下記のようなコードがあったとしよう。

var anchors = document.getElementsByTagName('a');
for( var i = 0, len = anchors.length; i < len; i++ ){
  var a = anchors[i];
  a.onmouseover = function()
  {
    a.style.color = '#ff0000';
  };
  a.onmouseout = function()
  {
    a.style.color = '#000';
  };
}

はい。これは問題なく動きます。
では、このコードを読み込み完了イベント内で書いてみると・・・

window.onload = function()
{
  var anchors = document.getElementsByTagName('a');
  for( var i = 0, len = anchors.length; i < len; i++ ){
    var a = anchors[i];
    a.onmouseover = function()
    {
      a.style.color = '#ff0000';
    };
    a.onmouseout = function()
    {
      a.style.color = '#000';
    };
  }
}

はい。失敗します。
これは、変数aはforループ内で都度初期化されているので、結果、最後に解釈されたAタグがonload内のローカル変数aの値となってしまいます。

結果は、ページ内どこのAタグをマウスオーバーしても、ページ内最後のAタグのみ色が変更されてしまうことになります。


そこでクロージャの登場です!!

window.onload = function()
{
  var anchors = document.getElementsByTagName('a');
  for( var i = 0, len = anchors.length; i < len; i++ ){
    var a = anchors[i];
    ( function(e)
    {
      e.onmouseover = function()
      {
        e.style.color = '#ff0000';
      };
      e.onmouseout = function()
      {
        e.style.color = '#000';
      };
    })(a);
  }
}


これで出来ました!!
何をしたかというと、forループ内に関数を作り、変数aをその関数内のローカル変数eへ渡してます。
このようにクロージャとは変数のスコープを切りたいときに利用したりできます。


JavaScriptを覚えるなら

よくわかるJavaScriptの教科書

新品価格
¥2,604から
(2013/12/1 15:56時点)



最寄りの駅を調べる

最寄りの駅を取得する方法を探していたら、こんな便利なWEBサービスと出会いました。

HeartRails Express | 路線/駅名/最寄駅データサービス

もちろん、きちんとAPIも提供されています。


使い道は至って簡単!!

最寄りの駅を調べたい対象となる緯度と軽度を渡すのみ!!

パラメータには

method には固定で getStations
x には最寄駅の情報を取得したい場所の経度
y には最寄駅の情報を取得したい場所の緯度

を渡します。

http://express.heartrails.com/api/json?method=getStations&x=135.191925&y=35.570042

すると、こんな感じで返ってきます。(サンプルはまたもや天橋立の最寄り駅をJSON形式で取得する)

{
  "response": {
    "station": [
      {
        "x": 135.195271,
        "next": "傘松",
        "prev": null,
        "distance": "1510m",
        "y": 35.583365,
        "line": "天橋立鋼索鉄道",
        "postal": "6292242",
        "name": "府中",
        "prefecture": "京都府"
      },
      {
        "x": 135.182874,
        "next": "岩滝口",
        "prev": "宮津",
        "distance": "1630m",
        "y": 35.557375,
        "line": "北近畿タンゴ鉄道宮津線",
        "postal": "6260001",
        "name": "天橋立",
        "prefecture": "京都府"
      },
      {
        "x": 135.195824,
        "next": null,
        "prev": "府中",
        "distance": "1830m",
        "y": 35.586202,
        "line": "天橋立鋼索鉄道",
        "postal": "6292242",
        "name": "傘松",
        "prefecture": "京都府"
      }
    ]
  }
}

返ってきた内容は

response 最寄駅の情報の一覧
station 最寄駅の情報(配列)

以下、各最寄り駅の情報

name 最寄駅名
prev 前の駅名(始発駅の場合は null)
next 次の駅名(終着駅の場合は null)
x 最寄駅の経度
y 最寄駅の緯度
distance 指定の場所から最寄駅までの距離(精度は10 m)
postal 最寄駅の郵便番号
prefecture 最寄駅の存在する都道府県名
line 最寄駅の存在する路線名


とっても簡単に最寄り駅を取得できました。
この情報とGoogleMap APIを併用すると色々とできそうでうね♪

JavaScriptを覚えるなら

よくわかるJavaScriptの教科書

新品価格
¥2,604から
(2013/12/1 15:56時点)


JavaScriptの並び替え

JavaScriptには配列を並び替えるための関数 sort が用意されてますが、あまり思うようにはいきません・・・

var list = [ 'Japan', 'England', 'America' ];
list.sort();
console.log(list); // [ "America", "England", "Japan" ]

と、なりますが、

var list = [ 80, 4000, 10, 600 ];
list.sort();
console.log(list); // [ 10, 4000, 600, 80 ]

と、なってしまいます。
sort 関数はアルファベットで並び替える仕様になっているので数値の大きさでは比較してくれません・・・

数値の大きさで比較したい場合は、下記のような関数を sort 関数の引数に渡してあげる事で解決します。

var list = [ 80, 4000, 10, 600 ];
list.sort( function( a, b )
{
  if( a < b ) return -1;
  if( a > b ) return 1;
  return 0;
});
console.log(list); // [ 10, 80, 600, 4000 ]

これで数値が小さい順に並びました。
比較により返す値を入れ替えれば、数値が大きい順で並びます。

さてさて、本題です。

先日、イベント情報を配信するサイトで悩んでしまったのでメモしときます。

内容は

・最新(降順)の5件を抽出
・抽出した5件は昇順で並べる

と、何を悩むのか・・・なんだけど、詳しく書くと

・公開日付が新しいもの(降順)から5件を抽出
・抽出した5件のイベント日をキーに昇順で並べる
・もちろん公開日付とイベント日付は異なります

です。

公開日付に関しては、HTMLを生成する際にシステム側でなんとでもなっちゃいます。

例えばこんな感じです。

<ul>
  <li>2013年12月01日<strong>イベント名</strong></li>
  <li>2013年11月25日<strong>イベント名</strong></li>
  <li>2013年11月23日<strong>イベント名</strong></li>
  <li>2013年11月20日<strong>イベント名</strong></li>
  <li>2013年11月24日<strong>イベント名</strong></li>
</ul>

これじゃぁ〜駄目ですよね・・・
ただし、イベントの日付は補足情報でしかなく、システムにそれをキーとして扱って〜とは言えません・・・
そこで<LI>タグに属性を追加してみます。

<ul>
  <li data-date="20131201">2013年12月01日<strong>イベント名</strong></li>
  <li data-date="20131125">2013年11月25日<strong>イベント名</strong></li>
  <li data-date="20131123">2013年11月23日<strong>イベント名</strong></li>
  <li data-date="20131120">2013年11月20日<strong>イベント名</strong></li>
  <li data-date="20131124">2013年11月24日<strong>イベント名</strong></li>
</ul>

これでページを読み込んだタイミングでDOM操作などを行ってなんとか出来そうだ!!

まずは、こんな感じでオブジェクト型の配列を作ってみます。

var li = $('ul li');
var list = [];
var i = 0;
while( i < li.length ){
  list.push({
    date: parseInt( $(li[i]).attr('data-date'), 10 ),
    element: li[i]
  });
  i++;
}

あとは、DOM操作などで<UL>タグを空っぽにして、お題の並び替えを行い、<LI>タグを戻していく。
そんな流れでいけそうです。


配列内のオブジェクトのキーに対する値を基準に配列を並び替える方法

list.sort( function( a, b )
{
  var adate = a['date'];
  var bdate = b['date'];
  if( adate < bdate ) return -1;
  if( adate > bdate ) return 1;
  return 0;
});

あらま、なんと単純!!

これでイベントの日付が古い順に並びました。
比較により返す値を入れ替えれば、降順で並びます。


JavaScriptを覚えるなら

よくわかるJavaScriptの教科書

新品価格
¥2,604から
(2013/12/1 15:56時点)

【メモ】jQueryのセレクタ

■基本

$('*')

すべての要素にマッチします。

$('*').css( 'color', 'red' );


$('element')

すべての element 要素にマッチします。下記の例ではすべての<P>要素にマッチします。

$('p').css( 'color', 'red' );


$('.class')

class="class-name" が指定されたすべての要素にマッチします。

$('.class-name').css( 'color', 'red' );


$('#id')

id="id-name" が指定された要素にマッチします。

$('#id-name').css( 'color', 'red' );


$('selector1,selector2,selector3')

selector1 または selector2 または selectorN にマッチする要素の集合です。

$('p,.class-name,#id-name').css( 'color', 'red' );


■階層

$('selector selector2')

selector1 の子孫要素として出現する selector2 にマッチします。

$('p strong').css( 'color', 'red' );


$('selector > selector2')

selector1 の子要素として出現する selector2 にマッチします。

$('p > strong').css( 'color', 'red' );


$('selector + selector2')

selector1 の直後に兄弟要素として出現する selector2 にマッチします。

$('p + strong').css( 'color', 'red' );


$('selector ~ selector2')

selector1 の後に兄弟要素として出現する selector2 にマッチします。

$('p ~ strong').css( 'color', 'red' );


■属性

$('[name]')

name 属性を持つ要素にマッチします。

$('[href]').css( 'color', 'red' );
$('a[href]').css( 'color', 'red' );


$('[name=value]')

name 属性の値が value に等しい要素にマッチします。

$('[href=http://uppeal.com/]').css( 'color', 'red' );


$('[name!=value]')

name 属性の値が value に等しくない要素にマッチします。

$('[href!=http://uppeal.com/]').css( 'color', 'red' );


$('[name~=value]')

name 属性の値がスペースで区切られたひとつ以上の値を持つ場合、その値のひとつが value と等しい要素にマッチします。

$('[class~=bold]').css( 'color', 'red' );


$('[name|=value]')

name 属性の値がプレフィクスとして value または value- を含む要素にマッチします。

$('[class|=lang]').css( 'color', 'red' );


$('[name^=value]')

name 属性の値が value を先頭に含む要素にマッチします。

$('[class^=lang-]').css( 'color', 'red' );


$('[name$=value]')

name 属性の値が value を末尾に含む要素にマッチします。

$('img[src$=.png]').css( 'margin', '10px' );


$('[name*=value]')

name 属性の値が value を含む要素にマッチします。

$('img[src*=uppeal.com]').css( 'margin', '10px' );


$('[condition1][condition2]')

condition1condition2 両方を満たす要素にマッチします。

$('img[class=button],img[src*=uppeal.com]').css( 'margin', '10px' );


■フィルター

:even
:odd

対象要素の中で偶数番目/奇数番目の要素にマッチします。

$('p:even').css( 'color', 'red' );
$('p:odd').css( 'color', 'blue' );


:first
:last

対象要素の中で最初/最後の要素にマッチします。

$('p:first').css( 'color', 'red' );
$('p:last').css( 'color', 'blue' );


:eq(index)
:eq(-index)

対象要素の中で0から数えて index 番目の要素にマッチします。負の値を指定した場合は後ろから数えます。

$('p:eq(10)').css( 'color', 'red' );
$('p:eq(-1)').css( 'color', 'blue' );


:gt
:lt

対象要素の中で0番目から数えて index 番目より大きい/小さい要素にマッチします。

$('p:gt(1)').css( 'color', 'red' );
$('p:lt(1)').css( 'color', 'blue' );


:not(selector)

対象要素の中で selector にマッチしない要素にマッチします。

$('p:not(excerpt)').css( 'color', 'red' );


:focus

対象要素の中でフォーカスが当たっている要素にマッチします。

$('input:focus').css( 'color', 'red' );


:header

対象要素の中でフォーカスが当たっている要素にマッチします。

$(':header').css( 'font-size', '20px' );


:lang(language)

対象要素の中で、lang="language" の要素にマッチします。

$(':lang(en)').css( 'font-family', 'Arial' );


:target(language)

対象要素の中で、URIのターゲット(#target) をidとして持つ要素にマッチします。例えば、http://www.example.com/sample.html#HTML にアクセスされた場合、id="HTML"属性を持つ要素にマッチします。

$(':target').css( 'color', 'red' );


:animated

アニメーション実行中の要素にマッチします。

$('p:animated').css( 'color', 'red' );


:contains(text)

text をテキストとして含む要素にマッチします。

$('p:contains(geek)').css( 'color', 'red' );


:empty

空の要素にマッチします。

$('p:empty').css( 'min-height', '20px' );


:has(selector)

対象要素の中で、selector にマッチする要素を子孫要素として持つ要素にマッチします。

$('p:has(strong)').css( 'color', 'red' );


:parent

対象要素の親要素にマッチします。

$('strong:parent').css( 'color', 'red' );


:hidden

非表示要素にマッチします。非表示要素には、head, title, meta, script, style などの非表示要素、CSS で display: none が設定された要素、width:0; height:0 が設定された要素、type="hidden" の input要素、祖先要素が非表示状態の要素が含まれます。

使い道がわかんない・・・


:visible

表示されている要素にマッチします。表示要素には html, body要素も含まれます。

使い道がわかんない・・・


:first-child
:last-child

対象要素の内、その要素が親要素から見て最初/最後の子要素であるものにマッチします。

$('p:first-child').css( 'color', 'red' );
$('p:last-child').css( 'color', 'blue' );


:first-type-of
:last-type-of

対象要素の内、その要素が親要素から見て同じ種別の最初/最後の子要素であるものにマッチします。

$('p:first-type-of').css( 'color', 'red' );
$('p:last-type-of').css( 'color', 'blue' );


:nth-child(index)
:nth-last-child(index)

対象要素の内、その要素の親要素から見て index 番目の子要素であるものにマッチします。最初の要素が1番目になります。:nth-last-child() は後ろから数えます。

$('li:nth-child(3)').css( 'color', 'red' );
$('li:nth-last-child(3)').css( 'color', 'blue' );

index は、2の倍数 (2n) や、2の倍数に1を加えたもの( 2n + 1 )などを指定することができます。

$('li:nth-child(2n)').css( 'color', 'red' );
$('li:nth-child(2n+1)').css( 'color', 'blue' );


:nth-of-type(index)
:nth-last-of-type(index)

:nth-child():nth-last-child() と同様ですが、同じ種別の要素のみを数えます。

$('li:nth-type-of(3)').css( 'color', 'red' );
$('li:nth-last-type-of(3)').css( 'color', 'blue' );


:only-child

その要素が、親要素から見て唯一の子要素である場合にマッチします。

$('li:only-child').css( 'color', 'red' );


:only-type-of

その要素が、親要素から見て唯一の子要素である場合にマッチします。

$('li:only-type-of').css( 'color', 'red' );


■フォーム

:input

input、textarea、select、button要素にマッチします。

$(':input').css( 'color', 'red' );


:text
:password
:file
:checkbox
:radio
:submit
:reset
:button
:image

type="text" , type="password" 等の input要素にマッチします。

$('input:text').css( 'color', 'red' );


:checked

checked な状態の要素にマッチします。


:selected

selected な状態の要素にマッチします。


:disabled

disabled な状態の要素にマッチします。

$('input:disabled').css( 'color', 'gray' );


:enabled

enabled な状態の要素にマッチします。

$('input:enabled').css( 'color', 'red' );


jQueryを覚えるなら

Web制作の現場で使うjQueryデザイン入門[改訂新版] (WEB PROFESSIONAL)

新品価格
¥3,129から
(2013/11/3 13:37時点)

Google Map API V3を使ってみる(3)

前回に引き続き、Google Map APIについて。

今回は、UI関係です。

デフォルトのコントロールセットを表示させない。

 1. <script>
 2. $(document).ready( function(){
 3.   var latlng = new google.maps.LatLng( 35.570075, 135.191917 );
 4.   var map = new google.maps.Map(
 5.     document.getElementById('map'),
 6.     {
 7.       zoom: 14,
 8.       center: latlng,
 9.       mapTypeId: google.maps.MapTypeId.ROADMAP,
10.       disableDefaultUI: true
11.     }
12.   );
13.   var marker = new google.maps.Marker({
14.     position: latlng,
15.     map: map,
16.     title: '天橋立'
17.   });
18. });
19. </script>

10行目
disableDefaultUIをtrueにするとデフォルトで表示されるコントロールセットを表示しない。


コントロールの表示を個別で指定することも出来ます。

 1. <script>
 2. $(document).ready( function(){
 3.   var latlng = new google.maps.LatLng( 35.570075, 135.191917 );
 4.   var map = new google.maps.Map(
 5.     document.getElementById('map'),
 6.     {
 7.       zoom: 14,
 8.       center: latlng,
 9.       mapTypeId: google.maps.MapTypeId.ROADMAP,
10.       panControl: true,
11.       zoomControl: true,
12.       mapTypeControl: true,
13.       mapTypeControlOptions: {
14.         style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
15.         position: google.maps.ControlPosition.TOP_RIGHT
16.       },
17.       scaleControl: true,
18.       streetViewControl: true,
19.       rotateControl: true,
20.       overviewMapControl: true
21.     }
22.   );
23.   var marker = new google.maps.Marker({
24.     position: latlng,
25.     map: map,
26.     title: '天橋立'
27.   });
28. });
29. </script>

10〜20行目
コントロールの表示/非表示を個別に設定するには、以下のプロパティで設定できます。
設定できる値はtrue(表示する)、false(表示しない)です。

panControl
 移動コントロールを有効または無効のいずれかを指定します。
zoomControl
 ズームコントロールを有効または無効のいずれかを指定します。
mapTypeControl
 マップタイプ(地図や航空写真など)を切り替えるマップタイプコントロールを有効または無効のいずれかを指定します。
scaleControl
 簡単な地図縮尺を表示するスケールコントロールを有効または無効のいずれかを指定します。
streetViewControl
 ストリートビューを有効または無効にするペグマンを、表示または非表示のいずれかを指定します。
rotateControl
 45度画像の向きをコントロールする回転コントロールの表示を有効または無効のいずれかを指定します。
 デフォルトではこのコントロールの表示は、現在表示されているズームと場所での指定されたマップタイプに45度画像があるかどうかで決まります。
overviewMapControl
 概観マップを有効または無効のいずれかを指定します。
 概観マップコントロールは、完全に表示(サムネイル概観マップを表示)するか、折りたたんで最小化した状態で表示することができます。

また、13〜16行目のようにコントローラーのスタイルや表示位置なども指定出来ます。


Google Map APIを覚えるなら

Google Maps APIプログラミング入門 改訂2版

新品価格
¥3,780から
(2013/10/25 14:40時点)

Google Map API V3を使ってみる(2)

前回に引き続き、Google Map APIについて。

今回は、マーカーを置いてみます。

 1. <script>
 2. $(document).ready( function(){
 3.   var latlng = new google.maps.LatLng( 35.570075, 135.191917 );
 4.   var map = new google.maps.Map(
 5.     document.getElementById('map'),
 6.     {
 7.       zoom: 14,
 8.       center: latlng,
 9.       mapTypeId: google.maps.MapTypeId.ROADMAP
10.     }
11.   );
12.   var marker = new google.maps.Marker({
13.     position: latlng,
14.     map: map,
15.     title: '天橋立'
16.   });
17. });
18. </script>

12〜16行目
markerという変数に以下のオプションを設定したマーカーを生成します。

positionは、マーカーを表示させる位置を座標で指定します。この指定は必須です。
mapは、どの地図にマーカーを表示させるか指定します。この指定も必須です。
titleは、マーカーにロールオーバーした時に出るツールチップ用テキストを指定します。


その他のマーカーのオプション

animation
 マーカーにアニメーションを指定します。
 アニメーションには、上から落ちてくる「DROP」、ピョンピョン弾む「BOUNCE」があります。

 BOUNCE

draggable
 マーカーをドラッグできる(true)かできない(false)かを指定します。

 ドラッグできない(良く意味がわかんない・・・)


Google Map APIを覚えるなら

Google Maps APIプログラミング入門 改訂2版

新品価格
¥3,780から
(2013/10/25 14:40時点)

Google Map API V3を使ってみる(1)

GoogleMapの埋め込みタグでは物足りなくなってきまして・・・
GoogleMap API V3を使ってみました。


まずはAPIを読み込みます。

1. <script src="http://maps.google.com/maps/api/js?sensor=false"></script>

たったこれだけ・・・もうAPIキーを発行して・・・そして・・・みたいな面倒は要りません!

sensor=の所はGPSなどの位置情報取得センサーをtrue(使用する)かfalse(使用しない)のどちらかを指定します。


表示したいGoogleマップの詳細設定。

 1. <script>
 2. $(document).ready( function(){
 3.   var latlng = new google.maps.LatLng( 35.570075, 135.191917 );
 4.   var map = new google.maps.Map(
 5.     document.getElementById('map'),
 6.     {
 7.       zoom: 14,
 8.       center: latlng,
 9.       mapTypeId: google.maps.MapTypeId.ROADMAP
10.     }
11.   );
12. });
13. </script>

2行目:
DOM構築完了のタイミングで処理を行う用意をします。

3行目:
latlngという変数に表示したい座標の値を代入します。
( 35.570075, 135.191917 ) は(緯度, 経度)を表します。
※Latlngは、Lat=latitude(緯度)、Lng=longitude(経度)のこと。
※指定した座標は京都府の天橋立の座標です。

4〜11行目
mapという変数に以下のオプションを設定した地図を生成し、5行目で指定したタグのIDに表示します。

zoomは、デフォルトのズームレベル(表示倍率)の指定。
 ズームレベルは数値が大きくなるほど拡大、小さくなるほど縮小。
centerは、表示枠内の中心点をどの座標にするかの指定。
 今回の例では、latlngに代入しておいた座標を指定しています。
mapTypeIdは、初期の表示タイプの指定。

 ROADMAP(市街地図)

 SATELLITE(衛星写真や航空写真)

 HYBRID(衛星写真/航空写真と道路地図のハイブリッド)

 TERRAIN(地形や樹木などの地形的特徴を持つ地図)


と、簡単なGoogle Mapはこんな感じで表示できます。


Google Map APIを覚えるなら

Google Maps APIプログラミング入門 改訂2版

新品価格
¥3,780から
(2013/10/25 14:40時点)

相対的な経過時間

先日書いたPHP版相対的な経過時間を今回はJavaScriptに置き換えてみました。

 1. function relativeDate( d ){
 2.   var ts = d.getTime() / 1000;
 3.   var now_ts = new Date().getTime() / 1000;
 4.   var delta = now_ts - ts;
 5.   if( delta <= 60 ){
 6.     return '1分以内';
 7.   }else if( delta <= 86400 ){
 8.     var hours = parseInt(( delta / 3600 ), 10 );
 9.     var min = parseInt((( delta % 3600 ) / 60 ), 10 );
10.     if( hours && min ){
11.       return hours +'時間'+ min +'分前';
12.     }else if(hours){
13.       return hours +'時間前';
14.     }else if(min){
15.       return min +'分前';
16.     }
17.   }else if( delta <= 604800 ){
18.     var days = parseInt(( delta / 86400), 10 );
19.     var hours = parseInt((( delta % 86400 ) / 3600 ), 10 );
20.     if( days && hours ){
21.       return days +'日'+ hours +'時間前';
22.     }else if(days){
23.       return days +'日前';
24.     }else if(hours){
25.       return hours +'時間前';
26.     }
27.   }else{
28.     return d.getFullYear() +'年' +( d.getMonth() + 1 ) +'月' + d.getDate() + '日 '
               + d.getHours() +'時'+ d.getMinutes() +'分';
29.   }
30. }

1行目:
相対的な経過時間を求めたいDate型を受け取る関数を用意します。

2行目:
受け取ったDate型からタイムスタンプを取得します。PHPと違いgetTime関数は1970年1月1日午前0時からのミリ秒(1000分の1秒)を返すため、値を1000で割る必要があります。

3行目:
現在の日時が設定されたDate型からタイムスタンプを取得します。


4行目:
現在のタイムスタンプと経過時刻を求めたい日時のタイムスタンプの差分を求めます。

5〜6行:
3行目で求めた差分(以下、差分)の値が60以下の場合、60秒以下ということになるので、「1分以内」を返します。

7〜16行:
差分が86400(=60秒×60分×24時間)以下の場合、その差分は1日以内になるので、
さらに差分を3600(=60秒×60分)で割り整数にすることでN時間を求めます。
さらに差分を3600(=60秒×60分)で割った余りを60で割整数にすることでN分を求めます。

10〜11行:
N時間、N分共に0ではない場合、「N時間N分前」を返します。

12〜13行:
N分が0の場合、「N時間前」を返します。

14〜15行:
N時間が0の場合、「N分前」を返します。

17〜26行:
差分が604800(=86400(=60秒×60分×24時間)×7日)以下の場合、その差分は1週間以内になるので、
さらに差分を86400(=60秒×60分×24時間)で割り整数にすることでN日を求めます。
さらに差分を86400(=60秒×60分×24時間)で割った余りを3600で割整数にすることでN時間を求めます。

20〜21行:
N日、N時間共に0ではない場合、「N日N時間前」を返します。

22〜23行:
N時間が0の場合、「N日前」を返します。

24〜25行:
N日が0の場合、「N時間前」を返します。

27〜28行:
上記にも当てはまらなかった場合、「N年N月N日 N時N分」を返します。


JavaScriptを覚えるなら

JavaScript 第6版

新品価格
¥4,410から
(2013/5/7 15:34時点)

JavaScriptの配列を拡張してみる(1)

痒いところに手が届かないJavaScriptの配列・・・

まずは個人的に良く使うシャッフル関数を拡張します。

 1. Array.prototype.shuffle = function(){
 2.   var i = this.length;
 3.   while(i){
 4.     var j = Math.floor( Math.random() * i );
 5.     var t = this[--i];
 6.     this[i] = this[j];
 7.     this[j] = t;
 8.   }
 9.   return this;
10. }

1行目:
Arrayオブジェクトのプロトタイプにshuffle関数を実装します。

2〜8行:
配列の長さを取得し、その長さ分デクリメントしながらループさせます。

4行目:
配列の長さを上限にした乱数を取得し、それを整数に繰り下げ(※配列は0から数えられるため)、変数jに代入しておく。

5行目:
ループカウンタをデクリメントした位置の値を変数tに代入しておく。

6行目:
ループカウンタの位置の値を、乱数で取得した変数jの位置の値で置き換える。

7行目:
乱数で取得した変数jの位置の値を、変数tで置き換える。

9行目:
配列を返す。


使い方は簡単です。

 1. // 配列listを生成
 2. var list = [1,2,3,4,5];
 3. // 配列listをシャッフルする
 4. list.shuffle();
 5. console.log(list); // [2,5,3,1,4]

JavaScriptを覚えるなら

JavaScript 第6版

新品価格
¥4,410から
(2013/5/7 15:34時点)