ウェブインコ

インコの技術メモ

JavaScript, jQuery

連想配列 ←→ JSON

var obj = JSON.parse(jsontext);
var jsontext = JSON.stringify(obj);


マッチと置き換え

var myid = $(this).attr('id');
if (myid.match(/svg\-/)) {
  myid = myid.replace('svg\-', 'svg-box-');
  myid = myid.replace(/(\w+)\s(\w+)/, '$2 $1'); // 正規表現
}


ゼロ埋め

now= new Date();
var keydate = ('000' + now.getFullYear()).slice(-4)
  + ('0' + (now.getMonth() + 1)).slice(-2)
  + ('0' + now.getDate()).slice(-2)


文字操作

var yyyy = keydate.substr(0, 4)
var mm = keydate.substr(4, 2)
var dd = keydate.substr(6, 2)


ランダム

   // サイコロ(1- 6)(その場限りで良いとき)
  var num = Math.floor( Math.random() * 6 ) + 1;
  console.log(num);
   // ランダムに並び替える(一定間隔で重複を避けたいとき)
  var arr = [1,2,3,4,5,6,7,8];
  arr.sort(function() {
    return Math.random() - Math.random();
  });
  console.log(arr);


each で飛ばす、抜ける

$('input').each(function(i, e) {
  // continue
  if ($(e).attr('type') != 'radio') { return true; }
  // break
  if (i > 10) { return false; }
});


ゆっくりループ

var count = 0; // ループ抜ける素
function loop(){
  count++;
  console.log(count); // 処理
  var countLimit = setTimeout(loop, 1000); // 再帰的に呼び出し
  if (count > 4) { clearTimeout(countLimit); } // ループ抜ける
}
loop(); // スタート


配列のソート

// 昇順
var a = [2,1,3]
a.sort(function(a,b){
  if( a < b ) return -1;
  if( a > b ) return 1;
  return 0;
});
結果: 1, 2, 3

// 降順
a.sort(function(a,b){
  if( a > b ) return -1;
  if( a < b ) return 1;
  return 0;
});
結果: 3, 2, 1


ハッシュをキーでソート(ハッシュの配列ではない)

[{"hoge":"warosu"},{"hage":"warota"},{"fuga":"warorisshu"}] ← x
var hogeHash  = {"hoge":"warosu","hage":"warota","fuga":"warorisshu"} // ← こっち
function sortHash(hash){
  var keys=[]; for(var k in hash){keys.push(k);}
  keys.sort();
  var res={}; for(var k in keys){res[keys[k]] = hash[keys[k]];}
  return res;
}
hogeHash = sortHash(hogeHash);
結果: 3, 2, 1


ハッシュを値でソート

var hogeHash  = {"hoge":20,"hage":30,"fuga":10}
var hogeHashA = Object.keys(hogeHash).map((k)=>({ key: k, value: hogeHash[k] }));
hogeHashA.sort((a, b) => a.value - b.value);
hogeHash = Object.assign({}, ...hogeHashA.map((item) => ({
    [item.key]: item.value,
})));
console.log(hogeHash);
結果: {fuga: 10, hoge: 20, hage: 30}


ハッシュを値(文字列)でソート

var hogeHash  = {"hoge":"2024/03/25","hage":"2024/03/24","fuga":"2024/03/26"}
var hogeHashA = Object.keys(hogeHash).map((k)=>({ key: k, value: hogeHash[k] }));
hogeHashA.sort((a,b)=>{  
  if(a.value < b.value){
    return -1;
  }else if(a.value > b.value){
    return 1;
  }
  return 0;
})
hogeHash = Object.assign({}, ...hogeHashA.map((item) => ({
  [item.key]: item.value,
})));
console.log(hogeHash);
結果: {hage: '2024/03/24', hoge: '2024/03/25', fuga: '2024/03/26'}


new Date() を localStorage に保存読込

// 保存
endtime = new Date();
window.localStorage.setItem('spot_endtime', endtime);
// 読込
spot_endtime = new Date(localStorage.endtime); // new する


ディープコピー

var myHash = JSON.parse(JSON.stringify(hisHash));
var myHash = $.extend(hisHash); // jQuery
var myHash = $.extend(hisHash, herHash); // マージ


jQuery を使わないで class の追加削除

<script>
window.onload = function () {
    var div = document.querySelector('.footer-widget-wrap .widget-box');
    div.classList.remove('col-md-3');
    div.classList.add('col-md-6');
}
</script>


【Node.js】API を叩いた結果をブラウザに表示
例)
vi server.js

var express = require('express');
var app = express();
app.listen(8888, function() {
    console.log('Express Listen port 8888');
})
var request = require('request');
app.get('/', function(req, res) {
    request.get('http://ほにゃらら/api', function(err, hit, body) {
#        body = JSON.parse(body);
        res.send(body);
    });
});
node server.js
http://localhost:8888/

POST の例。Elasticsearchで。
var express = require('express');
var app = express();
app.listen(8888, function() {
    console.log('Express Listen port 8888');
})
var request = require('request');
app.get('/search', function(req, res) {
  let options = {
    uri: "http://elasticsearchほにゃらら:9201/index/type/_search",
    headers: {
      "Content-type": "application/json",
    },
    json : {
      "size": "5",
      "from": "0",
      "query": {
        "query": "検索文字列",
        "fields": ["title", "body"],
        "default_operator": "and"
      },
      "sort": [{"search_date": {"order": "desc"}}]
    }
  };
  request.post(options, function(err, hit, body) {
    res.send(body);
  });
});


連想配列が空か

hoge = new Object();
if (hoge) {~ // x 間違い。全部反応します。
if (Object.keys(hoge).length) {~ // o 正解。値があるときだけ反応します。

一定時間ごとに処理
setInterval:時間通りに処理したいとき
setTimeout :処理をちゃんと完了させてから処理したい

setTimeout はごくわずかながら遅延しますが、setInterval 処理結果如何に関わらず続行します。

setInterval は外に書きます。
function loop(){
// 処理
}
setInterval(loop,1000);

setTimeout は中に書きます。
function loop(){
// 処理
setTimeout(loop,1000);
}

オブジェクト(連想配列も)の参照が不安定な時
オブジェクトは参照渡し、文字等は値渡し、という特徴から、いったん JSON にす。
function hoge(){
    ~何かしらの処理~
    return JSON.stringify(obj);
}
var funa = JSON.parse(hoge());

数字に
parseInt(hoge, 10);
hoge - 0
(下は続けて計算するときにしくるときがあるような)

配列←→csv
hoge_array = hoge.split(',');
hoge = hoge_array.join(',')

ループ
for(var i = 0 ; i < hoge_array.length ; i++ ){hoge_array[i]}
for(var i in hoge_array){hoge_array[i]}
for(var key in hoge_hash){hoge_hash[key]}

配列に値が含まれているか
あれば、添え字(0 ~)が返ってきます。
無い場合は false ではなく -1 が返ってくるので注意。
var isNew = ['Brand New', 'New', 'New with box', 'New with tags'];
var condition = 'New';
if(isNew.indexOf(condition) >= 0){
    console.log("---- あり ----"); // この場合こちら (= 1)
}else{
    console.log("---- なし ----");
}

連想配列のキーの階層を動的に増やしたい
代入したい左辺の場合は文字列作って eval() で評価です。
  var obj_001 = {"skills":[99,"149"]};
  var keys = ['skills', 1];
  var str2 = '';
  for(k in keys){
    str2 += "['" + keys[k] + "']";
  }
  str2 = 'obj_001' + str2;
  eval(str2 + "='ヘ(-。-)ノ'");

取得する場合は自分自身に代入するだけ。
  var obj_002 = obj_001;
  for(k in keys){
    obj_002 = obj_002[keys[k]];
  }
  console.log(obj_002);

動的なものを中央に表示する一例。
画面内の要素を計ってからセットし直すという発想。
  $(document).ready(function(){
    $('#hena').css('width', ($('#funa').width() + 1)); // +1 線幅や隙間があればその分をプラス
  })
  </head><body>
    <div id="hena" style="margin: 0 auto;">
      <span id="funa">ヘ(-。-)ノ</span>
    </div>

ハッシュの要素数
Object.keys(hoge_hash).length

配列を統合して重複があるか
var screen_ids=data.no_allauth.concat();
_.forEach(data.html, function(row){screen_ids.push(row.id);});
var overlap = screen_ids.filter(function(x, i, self){return self.indexOf(x) !== self.lastIndexOf(x);});
if(overlap.length){?}

カンマを付ける
var ssss= 1234;
var cccc = String(ssss).replace(/(\d)(?=(\d\d\d)+(?!\d))/g,'$1,');

カンマを取る
var ccc = '1,234';
var sss= ccc.split(",").join("");
無駄なスペースも取って数字に
var sss= parseInt(ccc.split(',').join('').trim(),10);
var sss= strPcccrice.split(',').join('').trim()-0;

セレクタ
タグで指定
$('div')

idで指定。1番メジャー。
$('#idname')

classで指定。2番目にメジャー。
$('.classname')

input タグの name で指定。
$('input[name="data[User][id]"]')

絞り込み。だいたいCSSと同じ。
$('#idname .classname')

イベントトリガー
クリック
$('#hoge').click(function(){
});
値が変わった
$('#hoge').bind("change",function(){
});

後から追加したものにも反応させたい

$(document).on('click', '.btn', function(){
  alert($(this).text());
});
document のところは親セレクタでも良いです。
親セレクタの中の子供は後から追加されても反応することができます。
親セレクタを document にしていれば全部なめます。
要素が多くなければ document で良いです。
解除は以下です。使うことはあまりないです。
$(document).off('click', '#blocA');


普通の on

$('.btn').on("click", function(event){
  alert($(this).text());
});


イベント時に引数を渡すことができます。
$(document).on('click', '#blocA', [{wwww1:'wwww1', wwww2:'wwww2'},{eeee1:'eeee1'}],function(event){
console.log(event.data[0].wwww2);
});
◆分けて書くときの方が使い道が多そうですね
function myHandler(event) {
console.log(event.data[0].wwww2);
}
$(document).on('click', '#blocA', [{wwww1:'wwww1', wwww2:'wwww2'},{eeee1:'eeee1'}],myHandler);
子共を指定していなくて引数の数が足りなくてもよしなに判断してくれます。(下の場合はどこをクリックしても反応します)
$(document).on('click', [{wwww1:'wwww1', wwww2:'wwww2'},{eeee1:'eeee1'}],function(event){
console.log(event.data[0].wwww2);
});


選択されている値。
ラジオ、チェックボックスの単体、セレクトボックス。
セレクトボックス複数の場合は配列。
var www = $('[name="UserId"]').val();

チェックボックス複数はセレクトボックスみたいに配列で返すことは無いから以下。配列。
var www = $('[name="UserId"]:checked').map(function(index, checkbox) {
return $(this).val();
});

選択させる。ex.1を選択させる。
ラジオ、チェックボックス、セレクトボックス複数。配列。
$('[name="UserId"]').val(['1']);
セレクトボックス単体。
$('[name="UserId"]').val('1');

クリックしたときのイベント
<input type="button" value="戻る" onclick="history.back()">

リンクを無効
<a href="javascript:void(0)">LINK</a>

宣言
HTML5
<script>
$(function(){
});
</script>
それ以前
<script type="text/javascript">//<![CDATA[
$(function(){
});
//]]></script>

CakePHPのフォーム内容をjqueryのajax用に加工する例
var formdata = {};
$('input').each(function(){
  var thisName = $(this).attr('name');
  if((thisName)&&(thisName.match(/data/))){
    if($(this).attr('type')=='radio'){
      formdata[thisName] = $("[name='"+thisName+"']:checked").val();
    }else{
      formdata[thisName] = $(this).val();
    }
  }
});
$.ajax({
  type: "POST",
  url: "/hoge/",
  data: formdata,
?

配列→文字列
function a2s(a){
  var result = "(";
  if (a instanceof Array){
    for (var k=0; k<a.length; k++){
      if( typeof a[k] == 'object' ){
        result = result + a2s(a[k])+" ";
      }else{
        result = result + "\""+a[k]+"\" ";
      }
    }
  }else{
    for (var k in a){
      if( typeof a[k] == 'object' ){
        result = result + ":"+k+" "+a2s(a[k])+" ";
      }else{
        result = result + ":"+k+" \""+a[k]+"\" ";
      }
    }
  }
  result = result + ")";
  return result;
}
ちぢめるとこんな感じ。
function a2s(a){var result="(";if(a instanceof Array){for(var k=0; k<a.length; k++){if(typeof a[k]=='object'){result=result+a2s(a[k])+" ";}else{result=result+"\""+a[k]+"\" ";}}}else{for(var k in a){if(typeof a[k]=='object'){result=result+":"+k+" "+a2s(a[k])+" ";}else{result=result+":"+k+" \""+a[k]+"\" ";}}}result=result+")";return result;}
使い方
alert(a2s(arrayhoge));

チェックされたチェックボックスの値を取る
var checks=[];
$("[name='data[fav]']:checked").each(function(){
  checks.push(this.value);
});

チェックボックス全部オフオンで2回目以降動かなくなる
例)
attr ではなく prop を使う。
.js
  // オーダーのチェックボックス
  $("#fav_toggle").click(function() {
    if(this.checked){
      $('.fav').prop('checked', true);
    } else {
      $('.fav').prop('checked', false);
    }
  });
.hmtl
<div class="input checkbox"><input name="data[fav]" id="fav_000143_" value="0" type="hidden"><input name="data[fav]" value="000143" id="fav_000143" class="fav" type="checkbox"></div>
<div class="input checkbox"><input name="data[fav]" id="fav_000142_" value="0" type="hidden"><input name="data[fav]" value="000142" id="fav_000142" class="fav" type="checkbox"></div>
<input id="fav_toggle" type="checkbox"><label for="fav_toggle" style="font-size: 12px;">すべてチェック</label>

メニューをロールアウトさせない例
.js
$(function(){
  var nav = $('.globalMenu');
  //navの位置  
  var navTop = nav.offset().top;
  //スクロールするたびに実行
  $(window).scroll(function () {
    var winTop = $(this).scrollTop();
    //スクロール位置がnavの位置より下だったらクラスfixedを追加
    if (winTop >= navTop) {
      nav.addClass('fixed')
    } else if (winTop <= navTop) {
      nav.removeClass('fixed')
    }
  });
});
.css
.fixed {
    position: fixed;
    top: 0;
    left: 20px;
    width: 100%;
}

ハッシュが空かどうか
if(Object.keys(hashArray).length > 0){ほにゃらら}

配列が空かどうか
if(Array.length > 0){ほにゃらら}

IEでajaxをキャッシュしてしまう
以下を $.ajax({ の前に書き足してください。
$.ajaxSetup({ cache: false });

aタグ href をpostで送信したいとき
<script type='text/javascript'>
$(document).ready(function(){
  $('#hoge a').click(function(){
    var form = $('<form></form>',{action:$(this).attr('href'),method:'POST'}).hide();
    var body = $('body');
    body.append(form);
    form.append($('<input>',{type:'hidden',name:'hogeid',value:'1'}));
    form.submit();
    return false;
  });
});
別ウインドウにしたいときにはこれ。
var form = $('<form></form>',{action:$(this).attr('href'),target:'receiver',method:'POST'}).hide();

formがネストしてしまいたいときなどにも
1つ上のソースと同じです。idをaタグに書くかsubmit他に書くかぐらい。
<script type='text/javascript'>
$(document).ready(function(){
  $('#hoge').click(function(){
    var form = $('<form></form>',{action:'/url/hoge.php',method:'POST'}).hide();
    var body = $('body');
    body.append(form);
    form.append($('<input>',{type:'hidden',name:'hogeid',value:'1'}));
    form.submit();
    return false;
  });
});

PHPで動的に画像を出力するタグをJavaScriptで動的に出力
ツボにハマッた。
imsに埋め込んだPHPに入力内容を引数にして渡してQRコードを返してもらうというもの。
何故だかIE6で画像が表示されないというのでツボにハマりました。
現象
 ・imgタグをJavaScriptで書き換えたがIE6で表示されない。
 ・右クリックして「画像を表示」とすると表示される。
解決方法
 ・ボタンをaタグからinputのimageに変える。
マウスオーバー等を他のところと共通で使いたかったので、aタグをトリガーにしていたのだけれど、それがダメだった見たい。imputタグのボタンや画像にしたら表示されました。原因は不明。

jQuery
とても便利だと思うんだ。
jQuery日本語リファレンス
http://semooh.jp/jquery/
jQueryの魔法
http://allabout.co.jp/internet/javascript/closeup/CU20071020A/

画面中央の座標
var cgw=300; //表示したいCG等の横幅
var cgh=400; //表示したいCG等の高さ
s_width = document.body.clientWidth || document.documentElement.clientWidth; // 横幅
s_nowHeight = document.documentElement.clientHeight; // 現在表示している画面の高さ
s_height = document.body.clientHeight || document.body.scrollHeight; // 画面の高さ
s_x = document.body.scrollLeft || document.documentElement.scrollLeft; // 横の移動量
s_y = document.body.scrollTop || document.documentElement.scrollTop; // 縦の移動量
var gostLeft = (s_width/2) - cgw/2; // 画面中央のx軸
var gostHeight = (s_nowHeight/2 + s_y) - cgh/2; // 画面中央のy軸
if (gostLeft < 0){gostLeft =0;}
if (gostHeight < 0){gostHeight=0;}

JavaScriptを使ってaタグからformの送信
CSSで組んだaタグの効果を生かしたいときなどに。
<form action="account.cgi" method="post" name="inputform">
?
<input type="submit" value="確  認">

<a href="#" onclick="document.inputform.submit()">確  認</a>
</form>
document.と.submit()の間にformのnameを入れる。

 実行されるタイミング。
◆ HTML が読み込まれる前に実行してしまい幅が取得できない。
<script>
    console.log($('div').width());
</script>
</head>
<body>
  <span>ヘ(-。-)ノ</span>
</body>
</html>

null

◆ HTML が読み終わってから実行するよう明示されているので幅が取得できる。
<script>
$(document).ready(function(){
    console.log($('div').width());
});
</script>
</head>
<body>
  <span>ヘ(-。-)ノ</span>
</body>
</html>

47

◆ 取得対象の HTML の後に書かれているので取得できる。
<body>
  <span>ヘ(-。-)ノ</span>
  <script>
      console.log($('div').width());
  </script>
</body>
</html>

47

というわけで、jQuery のトリガーは $(document).ready(function(){ ほにゃらら }); の中に書くこと。

画像まで全部読み終わってから実行したいときには $(window).load(function(){ ほにゃらら }); です。

jQuery が無ければ以下。
window.onload = function () {
  console.log("やること");
};

JavaScriptは少数の計算ができない

console.log(0.1 + 0.2);
0.30000000000000004
いったん 10n 倍して整数にしてから行うこと。
知らんと壺った。
(内部的に少数を10←→2進数するとき、2進数のほうで循環小数になってしまうのをよしなにしようとしてトチるらしいです)