かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

JS 呼び出し元の this を担保するメモ。

例 オブジェクト内の関数でsetTimeoutを使ってその中で、オブジェクト自身をthisとして使いたいような場合

var obj = {
  name: 'obj',
  func: function() {
    console.log(this); // => Object
    setTimeout(function() {
      console.log(this, this.name); // => Window, "result"
    }, 100);
  }
};
obj.func();

そのまま書くと、setTimeoutで呼び出された関数のthisWindowになる
Functionが参照型だから、thisがwindowになってる? undifinedではなくwindowになる理由の理解がまだ不明瞭。

伝統的な方法

var obj = {
  name: 'obj',
  func: function() {
    var self = this;
    setTimeout(function() {
      console.log(self, self.name); // => Object, "obj"
    }, 100);
  }
};
obj.func();

thisをスコープ内にself_thisといった別の変数に割り当てて関数内で変数が定義されていなければ上のスコープから変数を探すjavascriptの仕様を利用する方法。
(self = thisobjへの参照を変数に格納してるって理解で合ってる?)

jQuery $.proxy() を使う方法

var obj = {
  name: 'obj',
  func: function() {
    setTimeout($.proxy(function() {
      console.log(self, self.name); // => Object, "obj"
    }, this), 100);
  }
};
obj.func();

jQuery.proxy( function, context )
context
Type: PlainObject
The object to which the context (this) of the function should be set.
jQuery.proxy() | jQuery API Documentation

$.proxy()は第二引数に第一引数のFunction内で this として扱うものを指定できる。

ES5 Function.prototype.bind を使う方法

'use strict';
var obj = {
  name: 'obj',
  func: function() {
    setTimeout(function() {
      console.log(this, this.name); // => Object, "obj"
    }.bind(this), 100);
  }
};
obj.func();

Function.prototype.bind()
bind() メソッドは、呼び出された時に新しい関数を生成します。最初の引数 thisArg は新しい関数の this キーワードにセットされます。2 個目以降の引数は、新しい関数より前に、ターゲット関数の引数として与えられます。

fun.bind(thisArg[, arg1[, arg2[, …]]])
thisArg
束縛された関数が呼ばれる時、this 値としてターゲット関数に渡される値を指定します。束縛された関数が new 演算子によって構築された場合、この引数は無視されます。
Function.prototype.bind() - JavaScript | MDN

function(){}.bind(<関数内でthisとして使いたいもの>) の様な感じでFunctionのthisを拘束する。
下記のような使い方もできる。

'use strict';
var obj = {
  name: 'obj',
  say: function() { console.log( this, this.name ); }
};

setTimeout( obj.say.bind(obj), 100 ); // => Object, `obj`

[参考] es5のサポート状況

ES6 アロー関数() => を使う

まだIE11とかまだサポートされていないブラウザもありますが、ES6のアロー関数を使えば関数内のthisは呼出し元のthisが保証されるという事のようなので、次のように書く事ができます。

'use strict';
var obj = {
  name: 'obj',
  func: function() {
    setTimeout( () => {
      console.log(this, this,name); // => Object, "obj"
    }, 100);
  }
};
obj.func();

[参考] es6のサポート状況

アロー関数 - JavaScript | MDN
this を束縛しない
//(中略)
アロー関数がスコープ内の this の値を捕捉するため、
//(略)

これを読む限りアロー関数関数が定義されているスコープを関数内のthisとして使用する という事、つまり「thisが何を指すかは関数定義時に決まる」のではないかと思います。(間違ってたら指摘ください
 

ES5 から ES6 へ書き換える際の アロー関数 の落とし穴

アロー関数は関数を定義した際にそのスコープをthisとして束縛するようなので、いままで function() で書いていたものをそのまま () => に書き換えると思わぬ落とし穴にハマってしまうことがあります。

例えば下記のようなコード

// ES5
'use strict';
var obj = {
  name: 'obj',
  callback: function() {
    console.log(this, this.name);
  },
  func: function() {
    setTimeout( this.callback.bind(this), 100 );
  },
};
obj.func(); // => Object "obj"

これを単純にアロー関数に書き換えると… 👇

// ES6
'use strict';
var obj = {
  name: 'obj',
  callback: () => {
    console.log(this, this.name);
  },
  func: () => {
    setTimeout( this.callback, 100 );
  },
};
obj.func(); // => consoleには何も表示されない

これは下記と書き方と同等かと思います。({}はスコープを作成しない…はず)

var obj = {}; // new Object(); でも同じ?
obj.name = 'obj';
obj.callback = () => console.log(this, this.name);
obj.func = () => setTimeout( this.callback, 100 );

なので、アロー関数で定義されたobj.callbackobj.func 内の thisobjではなく、Window(グローバルオブジェクト)に拘束されてしまっているので上手く動作しなかったのだと考えられます。

この場合は、
アロー関数を使わずに、ES5のFunction.prototype.bind()を使って obj.callback 関数を呼び出す

'use strict';
var obj = {
  name: 'obj',
  callback: function() {
    console.log(this, this.name);
  },
  func: function() {
    setTimeout( this.callback.bind(this), 100 );
  },
};
obj.func(); // => Object "obj"

又は
thisobjに拘束してあるアロー関数内から obj.callback 関数を呼び出す

var obj = {
  name: 'obj',
  callback: function() {
    console.log(this, this.name);
  },
  func: function() {
    setTimeout( () => this.callback(), 100 );
  }
};
obj.func(); // => Object "obj"

の様な書き方にすれば上手く動作します。

クラスのようなprototypeにメソッドを付けている様な場合も同様のようです。

だめな例
'use strict';
var MyObject = function() {
  this.name = 'obj';
  return this;
};
MyObject.prototype.callback = () => {
  console.log(this, this.name); // this が Windowになってしまう
}
MyObject.prototype.func = () => {
  setTimeout( this.callback, 100); // this が Windowになってしまう
};
var obj = new MyObject();
obj.func(); // =>

callbackfunc 内の this が Window(グローバルオブジェクト)になるのでうまく動作しない。

動作する例

'use strict';
var MyObject = function() {
  this.name = 'obj';
  return this;
};
MyObject.prototype.callback = () {
  console.log(this, this.name);
}
MyObject.prototype.func = function() {
  setTimeout( this.callback.bind(this), 100);
  // 又は
  // setTimeout( ()=>this.callback(), 100);
};
var obj = new MyObject();
obj.func(); // => MyObject, "obj"

関数の定義をコンストラクタ内などに記述すればアロー関数で定義することもできました。

'use strict';
var MyObject = function() {
  this.name = 'obj';
  this.callback = () => {
    console.log(this, this.name);
  };
  this.func = () => {
    setTimeout(this.callback, 100);
  }
  return this;
};
var obj = new MyObject();
obj.func(); // => MyObject, "obj"

※ 但し継承させたオブジェクトなどで試していないので、この書き方はもしかすると継承させたオブジェクトからだとアロー関数内のthisが継承させたオブジェクトにならないなど不具合が出る可能性がありそうな気がしています。
 

まとめ

ES5もES6もちゃんと学習をしていなくて、ES6にしたら関数はすべてアロー関数() =>にするのかな?のような曖昧な理解だったので、ES6はfunction()()=>を挙動の違いを理解して適材適所に共存させて使うんだ!と今回調べてみて少し理解が深まったように思います。

溜まっていたを技術書少しづづ読んでいます。
今読んでいる「オブジェクト指向JavaScriptの原則」という本は薄めの本ですが、あやふやなまま使っていたECMAScript5で導入されたことをベースに書かれているようなのでES6の前にしっかり読んで理解しておきたいと思ってます。


[参考]

オブジェクト指向JavaScriptの原則

オブジェクト指向JavaScriptの原則

jQuery .triggerと.onとで実行される関数へのデータの渡し方の違いメモ。

オブジェクトのイベントを呼出して、オブジェクト自身をイベント内で使いたい時とかのメモ

.trigger

.trigger( eventType [, extraParameters ] )

extraParameters
Type: Array or PlainObject
Additional parameters to pass along to the event handler.
.trigger() | jQuery API Documentation

呼び出されるイベントの第二引数以降でデータを受取ることができる。

ex

配列で渡す場合

var $d = $(document);

$d.on('trigger_event', function(evt, param1, param2) {
  console.log( param1, param2 ); // => 'foo', 'bar'
});

// 発火
$d.trigger('trigger_event', ['foo', 'bar']);

オブジェクトで渡す場合

var $d = $(document);

$d.on('trigger_event', function(evt, data) {
  console.log( data.flg ); // => true
});

// 発火
$d.trigger('trigger_event', {flg: true});

.on

.on( events [, selector ] [, data ], handler )

data
Type: Anything
Data to be passed to the handler in event.data when an event is triggered.
.on() | jQuery API Documentation

呼び出されるイベントでは event.data で受取ることができる。

ex

var myObj = {
  dispatchEventListener: function(evt) {
     console.log( evt.data.self); // => myObj
  }
};

var $d = $(document);
$d.on('dispatch_event', {self: myObj}, myObj.dispatchEventListener);

// 発火
$d.trigger('dispatch_event');

.trigger と .on 両方からデータを渡す

データの渡し方が異なるので両方からデータを渡せば、オブジェクトの外からオブジェクトの中の関数に値を渡せたりします。

var MyObj = function() {
  var self = this;
  $(document).on('dispatch_event', {self: self}, self.dispatchEventListener);
  return this;
}

MyObj.prototype.dispatchEventListener = function(evt, data) {
  console.log( evt.data.self); // => [MyObj]
  console.log( data.flg ); // => true
};

var myObj = new MyObj();

// 発火
$(document).trigger( 'dispatch_event', {flg: true} );

わーい!

初めてプログラミングを書きはじめたのがAS(ActionScript)だったので、そこでなんとなく覚えた EventDispatcher 的な書き方に影響されている気がします。EventDispatcher と EventListener の定義の違いの理解があやふやですが…

久しぶりにコーディングのお仕事でjQuery触ったら、やっぱりすごく忘れてて予想外に時間がかかってしまった。。。orz
どうせまた忘れるだろうからメモをしました。やはり日々の触れてるって継続が大切でなのすね…


[参考]

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

初めてのJavaScript 第3版 ―ES2015以降の最新ウェブ開発

CSSで文字にボーダー(縁取り)をつけたい。

f:id:kikiki-kiki:20170327123027p:plain

Illustratorの線やPhothopのレイヤースタイルの境界線みたいに文字にボーダー(縁取り)をつける方法のメモ。

1. text-stroke を使う方法

f:id:kikiki-kiki:20170327123709p:plain
text-stroke サポート状況

IE以外はそこそこサポートされてきてるっぽい。
プロパティには-webkit-のブレフィックスが現状では必要。(なぜかFirefoxも。-webkit-text-stroke ってプロパティ名?)

書き方

f:id:kikiki-kiki:20170327130903p:plain

/* width | color */
-webkit-text-stroke: 2px #000;

又は

-webkit-text-stroke-width: 2px;
-webkit-text-stroke-color: #000;

ボーダー(縁取り)は文字の内側に付く

2. text-shadow を使う方法

text-shadowの構文は下記の様な感じです。

/* offset-x | offset-y | blur-radius | color */
text-shadow: 1px 1px 0 #000
/* color | offset-x | offset-y | blur-radius */
text-shadow: #000 1px 1px 0

このoffset-x | offset-y | blur-radius | colorのセットを「,」区切りで複数指定することが出来るので、上下左右にソリッドなtext-shadowを付けることで文字にボーダー(縁取り)を付けることができます。

書き方

f:id:kikiki-kiki:20170327141539p:plain

// 上
text-shadow: 2px 2px 0 #000,
             -2px 2px 0 #000,
             2px -2px 0 #000,
             -2px -2px 0 #000;
// 下
text-shadow: 2px 2px 1px #000,
             -2px 2px 1px #000,
             2px -2px 1px #000,
             -2px -2px 1px #000;

ボーダー(縁取り)は文字の外側に付く
text-shadowはIE10+で効くようなので、こちらを使えばほぼ全てのブラウザで表示ができそうです。text-shadow サポート状況
※ 文字の大きさに対してoffsetの値が大きすぎるとフォントの周りがギザギザになってしまうので注意が必要です。
 

まとめ

  • text-stroke は 内側にラインが入る
  • text-shadow は外側にラインが入る

と覚えておけば良さそうです。
IEも10以上なら表示されるし、Illustratorの線やPhothopのレイヤースタイルの境界線に近いのはtext-shadowの方かなと思いました。
また、IEではtext-strokeが表示されないので少し表示が変わってしまいますが、text-stroketext-shadowと合わせて指定するとこもできます。
f:id:kikiki-kiki:20170327141750p:plain
両方サポートしているブラウザなら細かな表現ができそうです。

サンプル

See the Pen OUTLINE TEXT Test by KIKIKI (@chaika-design) on CodePen.


[参考]

はじめてのCSS設計 フロントエンドエンジニアが教えるメンテナブルなCSS設計手法 (WEB Engineer’s Books)

はじめてのCSS設計 フロントエンドエンジニアが教えるメンテナブルなCSS設計手法 (WEB Engineer’s Books)

CSS 100%幅の子要素にネガティブマージンを使うと右側だけはみ出して横スクロールが表示されてしまう

所謂Bootstrapの.row.col-で使われているような親要素が左右のネガティブマージンを持ち子要素がfloatを使ったカラムレイアウトを100%の画面に入れた時に右側だけが100%のブラウザサイズからはみ出して横スクロールが表示される現象に遭遇しました。

横スクロールが発生する例

HTML

<div class="container">
  <div class="row">
    <div class="col col-half">
      <div class="content">content</div>
    </div>
    <div class="col col-half">
      <div class="content">content</div>
    </div>
  </div>
</div>

CSS (stylus表記)

*
  box-sizing: border-box
.container
  width: 100%
.row
  margin-left: -15px
  margin-right: -15px
  .col
    float: left
    padding-left: 15px
    padding-right: 15px
  .col-half
    width: 50%

f:id:kikiki-kiki:20170325212944p:plain
こんな風に横スクロールが発生してしまいます。

解決方法1 ネガディブマージンを持つ要素の親にパディングを持たせる

Bootstrapをよくよく観察していると、ネガティブマージンを持つ.rowの親要素には必ずネガティブマージン分のパディングを持つ要素がある事に気が付きました。親要素にパティングを持たせておくことでウィンドウサイズからはみ出さないようにしているようです。

HTML

<div class="container">
  <div class="wrap">
    <div class="row">
      <div class="col col-half">
        <div class="content">content</div>
      </div>
      <div class="col col-half">
        <div class="content">content</div>
      </div>
    </div>
  </div>
</div>

CSS

.wrap
  padding-left: 15px
  padding-right: 15px

ネガティブマージンを持つ要素を囲み、囲った要素にネガティブマージン分のパディングをもたせればOKです。
f:id:kikiki-kiki:20170325223024p:plain
横スクロールは発生しませんが、.content.colの持つパディング分左右が小さくなります。
border-boxを使っているこの状態なら下記のような.rowに初めからネガティブマージンを持たせないものと同じ結果です。

*
  box-sizing: border-box
.container
  width: 100%
.row
  .col
    float: left
    padding-left: 15px
    padding-right: 15px
  .col-half
    width: 50%

解決方法2 ネガティブマージンを持つ要素の親にoverflow: hiddenを設定する

.colの持つパディング分を画面外に出し、.contentを画面の端一杯にしたいときは、ネガティブマージンをもつ.rowの親に幅指定と共にoverflow: hiddenを設定すればOKです。
HTML

<div class="container">
  <div class="row">
    <div class="col col-half">
      <div class="content">content</div>
    </div>
    <div class="col col-half">
      <div class="content">content</div>
    </div>
  </div>
</div>

CSS

*
  box-sizing: border-box
.container
  width: 100%
    overflow: hidden // <- 追加
.row
  margin-left: -15px
  margin-right: -15px
  .col
    float: left
    padding-left: 15px
    padding-right: 15px
  .col-half
    width: 50%

f:id:kikiki-kiki:20170325223042p:plain
図のように画面端から.contentのエリアになります。
overflow: hiddenを使用するのであまり上のレイヤーの要素にこの設定をしてしまうと他のデザインで苦労する自体が発生しかねないので注意が必要です。
 
しばらくCSSとか書いてなかったので予期しないレベルダウンを感じています…
今までこんな所に躓いたこと無かった気が…

ITがメインではない仕事に就いている(正確には仕事がない)とドンドンレベルダウンしていっているのを身にしみて感じていて、今迄できていたような事がカンタンに出来なくなるってのが凄まじいストレスと自己嫌悪になるので、都会に引越ししてエンジニア的なお仕事に再就職したい今日この頃なのでした…


[参考]

はじめてのCSS設計 フロントエンドエンジニアが教えるメンテナブルなCSS設計手法 (WEB Engineer’s Books)

はじめてのCSS設計 フロントエンドエンジニアが教えるメンテナブルなCSS設計手法 (WEB Engineer’s Books)

Google スプレッドシート nヵ月前の日付をチェックしたい

例えば、下記のような期限日が入力されているシートで期限まで3ヵ月切っているセルをハイライトしたいような時のメモ。

A B
1 案内日 期限(6ヵ月後月末)
2 2016/07/07 2017/01/31
3 2016/08/07 2017/02/28
4 2016/09/10 2017/03/31
5 2016/10/06 2017/04/30
6 2016/11/04 2017/05/31
7 2016/12/05 2017/06/30
8 2017/01/05 2017/07/31
9 2017/02/03 2017/08/31
10 2017/03/07 2017/09/30

判定条件

条件としては「3ヶ月前の月末 < 本日」で判定すれば良さそうです。
3ヶ月前の月末はEOMONTHを使うと取得することができます。

EOMONTH(開始日, 月数)
起算日から指定した月数だけ前または後ろの月の最終日の日付を返します。
EOMONTH - Docs editors Help

EX

B5セルの「2017/04/30」の3ヵ月前の月末(2017/01/31)は次の式で求めることができます。

=EOMONTH(B5, -3)

この式を利用した条件式付き書式をせっていすれば良さそうです。

シートに条件式付き書式を設定する

  1. B部分をクリックしてB列全体を選択
  2. メニューの「表示形式」から「条件付き書式…」を選択。
  3. 条件式付き書式設定ルール のメニューが表示されるので
    セルの書式設定の条件を「カスタム数式」を選択。
  4. 値または数式入力欄に下記の数式を入力
    =EOMONTH($B:$B,-3)<TODAY()
  5. いい感じに書式設定のスタイルを指定して、完了ボタンをクリック

期限日が3ヶ月切っているセルが設定した書式の通りに表示されていればOKです。
f:id:kikiki-kiki:20170324165053p:plain

月数を変えたいときはEOMONTHの第二引数の値を変えればOK。
他にもEDATE関数などを使用すれば条件の日付を自由に計算することができます。
公式のドキュメントにいろんな関数が載っているので興味があればそちらを参照ください。


[参考]

ポケット百科 Googleサービス 知りたいことがズバッとわかる本

ポケット百科 Googleサービス 知りたいことがズバッとわかる本

CSS3 マークアップ別Flexboxで要素を左端・センター・右端揃えのレイアウトを作る

IE8以下のサポートも終わり自動アップデートになってきていますし、CSS3のFlexboxもそろそろ実制作で活用できる用になってきていると思っています。
f:id:kikiki-kiki:20170323200844p:plain
flex サポート状況

なので、下記画像のようなWEBサイトのグローバルナビゲーションとかでよくある例えばロゴ・ナビゲーション+ボタンの様な構成で、ロゴを左端、ナビゲーションをセンターにしてボタンを右端に置くデザインをFlexboxで作ってみようと思います。
f:id:kikiki-kiki:20170323201153p:plain ※いつもの事ながらIEではチェックしていません。

並べたい各要素が同じ階層のマークアップの場合

HTML

<header class="header">
  <div class="nav-wrapper">
    <p class="logo">LOGO</p>
    <nav class="navigation">
      <ul class="nav-list">
        <li class="nav-link"><a href="">LINK</a></li>
        ...
      </ul>
    </nav>
    <div class="nav-btn">
      <a class="btn">BUTTON</a>
    </div>
  </div>
</header>

Flexboxの揃え方 justify-content: space-between を使う方法

CSS

/* ▼ 共通部分 ▼ */
.header,
.logo,
.navigation
.nav-list,
.nav-btn
  box-sizing: border-box
.header
  width: 100%
.nav-list
  padding: 0 1em // 最小の左右のマージンを持たせておく
/* ▲ 共通部分 ▲ */
// Flex
.nav-wrapper
  display: flex
  flex-flow: row nowrap
  justify-content: space-between
  align-items: baseline

flexboxにjustify-content: space-between と指定すれば、ロゴ・ナビゲーション・ボタンの間隔が均等になるのでデザインが実現できます。

margin auto を利用する方法

CSS

/* 共通部分省略 */
// Flex
.nav-wrapper
  display: flex
  flex-flow: row nowrap
  // justify-content: space-start <- default値
  align-items: baseline
.navigation
  margin: 0 auto

親要素がflexの子要素でmargin autoを使用すると親要素の幅内でいい感じに配置してくれる様です。
ですので、センター揃えにしたいナビゲーションにmargin: 0 autoを与えると右マージンに押されてボタンが右端に配置されデザインを実現することができます。
このautoで付けたマージンもjustify-content: space-betweenの間隔と同じように可変なのでレスポンシブやリキッドレイアウトにも対応可能かと思います。

おまけ margin autoを利用するとロゴだけ左揃えにもできる

ナビゲーションとボタンがflexを親に持つ同じ子要素なので、ロゴを左揃え・ナビゲーション・ボタンを右揃えにしたい時にはjustify-content: space-betweenは使えませんので、margin: autoがいい感じに幅を取ってくれることを利用すると実現が可能となります。

/* 共通部分省略 */
// Flex
.nav-wrapper
  display: flex
  flex-flow: row nowrap
  justify-content: space-end // 右を基点にする (全体右寄せ)
  align-items: baseline
.logo
  margin-right: auto

ロゴにmargin-right: autoを与えるとロゴの右側に取れるだけのマージンが付くので、ロゴのみ左揃えになります。
f:id:kikiki-kiki:20170323203950p:plain
 

ナビゲーションと内にボタンがあるマークアップの場合

レスポンシブデザインでナビゲーションとボタンを同時に変化させたい時とかこの様なマークアップもありそうです。
HTML

<header class="header">
  <div class="nav-wrapper">
    <p class="logo">LOGO</p>
    <nav class="navigation">
      <ul class="nav-list">
        <li class="nav-link"><a href="">LINK</a></li>
        ...
      </ul>
      <div class="nav-btn">
        <a class="btn">BUTTON</a>
      </div>
    </nav>
  </div>
</header>

2段重ねのFlexboxで実現する

‘.navigation'内の子要素も横並びにするので、ここもdisplay: flexにし、センター揃えにしたいナビゲーション(.nav-list)で調整する事で、キレイに左端揃え・センター揃え・右端揃えのレイアウトを実現することができます。

/* 共通部分省略 */
// Flex1 .logo と .navigation の並び
.nav-wrapper
  display: flex
  flex-flow: row nowrap
  // justify-content: space-start <- default値
  align-items: baseline
// Flex2 .nav-list と .nav-btn の並び
.navigation
  display: flex
  flex-flow: row nowrap
  justify-content: center // 全体中揃え
  width: 100% // 残りの幅全体にする
  box-sizing: border-box // 必須
.nav4 .nav-list
  margin: 0 auto
  1. .logo.navigationflexにする
    f:id:kikiki-kiki:20170323210413p:plain
  2. widtth: 100%.navigationを残りの部分一杯の領域にする
    f:id:kikiki-kiki:20170323210420p:plain
  3. ナビゲーション(.nav-list)の左右のマージンをautoにして全体のセンターにする
    f:id:kikiki-kiki:20170323210430p:plain

 

ボタンがナビゲーションのリスト内にある場合

<header class="header">
  <div class="nav-wrapper">
    <p class="logo">LOGO</p>
    <nav class="navigation">
      <ul class="nav-list">
        <li class="nav-link"><a href="">LINK</a></li>
        ...
        <li class="nav-btn">
          <a class="btn">BUTTON</a>
        </li>
      </ul>
    </nav>
  </div>
</header>

このマークアップだと完璧にナビゲーションのリンク部分だけをheaderのセンターに揃える方法を見つけることができませんでした。

ボタンにマージンを%で設定して調整するパターン

/* 共通部分省略 */
.nav-wrapper
  display: flex
  flex-flow: row nowrap
  justify-content: space-betwee
  align-items: baseline
.navigation
  width: 100%
  box-sizing: border-box // 必須
.nav-list
  display: flex
  flex-flow: row wrap
  justify-content: flex-end // 右端を基点にする
  padding-right: 0
.nav-btn
  margin-left: 25% // 適当な値に設定

.logo.navigationjustify-content: space-between で等間隔にし、.nav-listflexにして子要素を並べ、リストの最後になるボタン(.nav-btn)の左マージンを適当な%で指定してそれっぽくすることができました。ボタンのマージンは親要素のn%なので、ブラウザの幅が狭いとロゴとの間隔が狭くなり、逆にブラウザの幅が広いとボタンとの間隔に対してロゴとの間隔が広くなります。
f:id:kikiki-kiki:20170323215701p:plain

ボタンをposition: absoluteで右端に固定するパターン

/* 共通部分省略 */
.nav-wrapper
  display: flex
  flex-flow: row nowrap
  justify-content: space-betwee
  align-items: baseline
  position: relative
.navigation
  display: flex
  flex-flow: row nowrap
  justify-content: space-around  // .logoとの間隔を作る
  width: 100%
  box-sizing: border-box // 必須
.nav-list
  display: flex
  flex-flow: row wrap
  // justify-content: space-start <- default値
  padding-right: 0
.nav-btn
  position: absolute
  right: 0

ナビゲーション内のリスト左揃えで始めボタンだけposition: absoluteで右端に固定しflex配置から外します。そして.navigationをFlexboxにしてjustify-content: space-aroundを指定するとロゴとの間隔もいい感じになります。しかし、absolute配置しているボタンの幅は無いものして計算されるのでブラウザの幅が狭くなるとナビゲーションのリストとボタンが重なってしまいますので、メディアクエリなどで小さくなった時のCSSを別途作成する必要がありそうです。
f:id:kikiki-kiki:20170323221203p:plain
 

サンプル

See the Pen Flex nav sample by KIKIKI (@chaika-design) on CodePen.

 

今までどうしてもIE対応があったりで、Bootstrapで流行ったfloatdisplay: tableを使ったCSSを書くことが多くFlexboxをちゃんと使いこなせていなかったので今回この記事をかいて少しFlexboxにも慣れてきた感じがしてきました。
コーディングしない期間が続くと書き方を忘れていたり、新しいやり方のキャッチアップが疎かになってしまうので気をつけなきゃな―っとしみじみ感じています。


[参考]

Adobe illustrator パターンをオブジェクトにしたい

パターンで付けた柄をオブジェクト化(アウトライン化?)する方法。
オブジェクトを選択して、メニュバーからオブジェクト > 分割・拡張...を選択すればOK
f:id:kikiki-kiki:20170311224902p:plain
ダイアログが出るのでそのままOKを押せばパターンがオブジェクトに変換されます👇
f:id:kikiki-kiki:20170311224935p:plain

イラレで印刷に出すのバージョンとかの問題でパターンとかブレンドとかそのまま出すの不安なので、全部オブジェクトに変換しているのだけれど正しいのかな?(イラレ嫌いでPhotoshopで印刷データ作るタイプ)


神速Illustrator [グラフィックデザイン編] CC対応

神速Illustrator [グラフィックデザイン編] CC対応

WordPress 4.7, 4.7.1 はAPIに致命的なバグがあって認証無しで誰でも記事を改ざんできちゃうっぽい!

WordPress 4.7, 4.7.1 のサイトは直ぐに4.7.2にアップデートするのです!

Twitterで大学や国会議員や公的機関のサイトが大量に改ざんされてるという情報を朝から目にした日でした。

どうやら改ざんされていたのはWordPressのサイトの様で、事の顛末は、
WordPressはアップデートの際には何を修正したかを公開していたのですが、今回はWordPress 4.7.2で修正をしたバグが致命的なものだったために直ぐにセキュリティに関わるアップデートの内容を公開せずに1週間後に情報を公開したようです。( WordPress 4.7.2のリリースが1月26日、バグの情報が公開されたのが2月1日 )
そして、それ以降もWordPressをアップデートせずに、4.7、4.7.1のバージョンのままだったサイトが軒並みこのバグを利用されて記事を改ざんされていったと言うのが今回の件のようです。

今回の話題になってるバグとは?

特定のAPIのURLにPOSTでデータを送るだけで、WordPressのログインも認証もなしに投稿内容を更新することができてしまうというバグ…そしてバグの内容が公開されていて、少しググれば簡単に攻撃スクリプトが解ってしまうというくらい簡単なもの。
これはWordPress 4.7 で導入された投稿の取得や新規追加、更新を行うことができるREST APIに含まれていたバグ。なので、4.7より古いバージョンのサイトはこの攻撃で改ざんされないっぽい。古いのはあまり良くないけど、結果的に今回は良かったみたいな…

ローカル環境で試してみました。

WordPressのバージョンは管理画面 >ダッシュボードで確認ができます。 f:id:kikiki-kiki:20170206143252p:plain
※ ここが、4.74.7.1 の人はすぐにアップデートしましょう!

バグの具体的な内容はWordPress公式のリリースノートの記事や、そこにある報告者のリンク先の記事内に書かれています。
攻撃したいWordPressのサイトのAPIのURLに、改ざんしたい記事の投稿IDを紐付けて、データにタイトルと本文を持たせてPOSTするだけ。

なので、こんなサイトに…
f:id:kikiki-kiki:20170206150323p:plain
次のような公式の記事とかを参考に作った攻撃コード ( 調べればすぐ解りますがキーとか隠しておきます )
f:id:kikiki-kiki:20170206150202p:plain
これをリクエストすると…

f:id:kikiki-kiki:20170206150331p:plain
はい。認証も何もなしに記事を書き換えることができました。
このAPIを利用して記事を改ざんするとWordPress管理画面から見れる投稿のリビジョンでは、ユーザー名が表示されないようです。
f:id:kikiki-kiki:20170206151734p:plain

ね?簡単でしょ!?

_人人人人人人人人人人人人人人人_  
> 簡単でしょ!?じゃねーよ!!!! <  
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄  

試してみた所、HTMLタグも入れ放題なんですよ。
そして、攻撃に必要になる「WordPressの投稿ID」なのですが、デフォルトとか多くのテーマだとHTMLタグにid名やclass名で投稿IDが出力されています。
HTMLに出力されていなくてもRSSを利用している場合RSSに出力されているURLはパーマネントリンク設定で変更されたURLではなく?p=1の形式になっており投稿IDが丸わかりなのです…

このバグ
f:id:kikiki-kiki:20170206142825p:plain

はてなブックマーク - WordPress 4.7.1 の権限昇格脆弱性について検証した | 徳丸浩の日記
👆 コトの重大性に溢れたコメントが並んでいます。マジやばくね?

解決方法

こちらの記事にあるように、下記の方法を取ればこの致命的なバグには対応することができそうです。

  1. WordPressを最新の4.7.2にアップデートする
  2. ただちに最新版へアップデートすることが困難な場合、REST APIを無効化するプラグインを使用する

そして、可能な限りWordPressの自動更新をONにしておくのが良いのではないかと思いました。
しかし私の持っていたサイトの中には更新の通知が来ても実際には更新されなかったサイトもあったので自動更新機能を過信しすぎてもダメかもしれません。

改ざんされたサイトの対応

改ざんされた記事そのものはリビジョンから直ぐにもとに戻すことが可能です。
今回のAPIを利用した攻撃の場合、できても記事のタイトルと本文の更新のようなので記事内にスクリプトやiframe埋め込むことはできると思うのですが、サイトのテーマ自体にコードを追加したり、DBからデータを抜き取ったり、ログイン情報を取得したりとかは難しいのかな〜?と思っているのですが、これは私もハッキリとした事が言えないので、むしろ教えてほしい部分です!!

WordPressのような既に多くの人がコミットしているプロジェクトでもこんな重大な脆弱性が発生したりするんだなぁ〜って驚きました。
それより、WrodPressのサイトを持っている方は直ぐにチェックしてみることをオススメします。  
 
追記
REST APIのバグを利用しての改竄は観測している中ではISISを中傷する改竄が多かったのですが、中には「私はホワイトハッカーだ。君のサイトのWordPressアップデートした方が良いぞ。」と注意喚起のような記事を改ざんするハッカーも観られるようになってきました。
f:id:kikiki-kiki:20170206200127p:plain
まぁ いずれにせよ、改ざんされちゃってるわけですけどね。。。


[参考]

👇 徳丸 先生のありがた〜い本 👇

確定申告!

確定申告の季節です。
毎年、ナゼ毎月領収書を整理しておかなかったのだ!! と成長のない自分を責める季節でもあります。

私はフリーランスを初めてナンダカンダで10年くらいになっていました。
WEB・グラフィック制作やイベントの進行管理といった仕事の他に同人活動もしているの事もあり、業務内容が雑多で多岐にわたるので経費も雑多なものになるのですが、昔読んだ「フリーランスを代表して 申告と節税について教わってきました。」という本に書かれていた内容が青色申告になった今も役に立っています👇

2010年に読んで書いたレビューを貼っておきます。

会話形式の文章とイラストでとても読みやすく理解しやすかった。
腹黒本音モードのときは顔に影が入ったりするのが面白い。各章も短く簡潔で、最後にまとめの4コマ漫画が入るので読み疲れることなく最後まで読めた。
税が身近に感じられた一冊。
フリーランスを代表して 申告と節税について教わってきました。 感想 きたみ りゅうじ - 読書メーター

この本の著者はイラストレーターなので同人をしていて確定申告が必要な方はもちろん参考になる部分が多いと思います。その様な職種の方だけでなく、フリーのデザイナーやエンジニアも読んでおいて損は無いのではないかと思います。
どちらも資料がいっぱい必要なお仕事ですからね!! と、本をオススメするだけの記事でした。

Ruby Slim タグなどを含んだ変数をエスケープせずに出力したい。

Slim テンプレートでの変数の出力の方法は、こんな感じに=で出力することができます。

div
  p= @value

文章中や、属性中に変数展開させる場合は#{変数名}で出力します。

p
  a.btn src="edit/#{@id}" 編集

しかし、上記の方法ではHTMLタグや"などを含んだ文字列を出力しようとするとエスケープされたものが出力されてしまいます。自動的にエスケープしてくれるので便利なのですが、改行がある文章をそのまま出力したいなどといった場合には不都合があります。

EX:

@value = '<b>"タグ"を含んだテキスト。</b>'
p= @value
p 文章中に変数展開「#{@value}

↓ 出力されるHTML

<p>&lt;b&gt;&quot;タグ&quot;を含んだテキスト。&lt;/b&gt;</p>
<p>文章中に変数展開「&lt;b&gt;&quot;タグ&quot;を含んだテキスト。&lt;/b&gt;</p>

エスケープせずに出力する方法

エスケープせずに変数を出力する場合は == で、
エスケープせずに文章中に変数展開をする場合は #{{変数名}} と二重にすれば記述すればOK。

EX:

@value = '<b>"タグ"を含んだテキスト。</b>'
p== @value
p 文章中に変数展開「#{{@value}}

↓ 出力されるHTML

<p><b>"タグ"を含んだテキスト。</b></p>
<p>文章中に変数展開「<b>"タグ"を含んだテキスト。</b></p>

まとめ

エスケープあり エスケープなし
変数出力 = ==
変数展開 #{変数名} #{{変数名}}

 
好んで使ってたSlimと記述方法が似てるpug (旧jade)ではエスケープしない場合は!=!{変数名}だったので、同じだろうと思ってハマってしまいました。
Rubyの学習が全然進んでないので、もくもく会とかに参加しよう…

後、記事と全然関係ないのだけどSublimeTextでRuby書いてると、シンタックスハイライトの処理なのかめちゃくちゃ入力と表示にラグ発生するのだけれど解決方法とかあるのだろうか…?


プログラミング言語 Ruby

プログラミング言語 Ruby