読者です 読者をやめる 読者になる 読者になる

やまろぐはてな

yamanokuの技術メモ。Qiitaは怖くて書けない。

cookieとかを使ってjsで云々

JavaScript jQuery cookie js-cookie localStorage

仕事とか実験で色々試してみたので雑まとめ。

js-cookie便利

github.com

jsでのCookie処理が楽なので是非導入してみよう。以下はそれを使った処理になります。

ページ固有のcookieを記録したい

http://xxxxx.xxx/xxxxx/xxxx/001/

みたいなアドレスがあったとき

// ページ番号
var Num = window.location.pathname.split('/')[3]
// 全体パス
var p = window.location.pathname.replace(new RegExp("(?:\\\/+[^\\\/]*){0,1}$"), "/");
Cookies.set(Num,Num,{ path: p });

ってやると「001」っていうcookieが残る。valueも同じ。

path設定はそのページ特有のものになるので、2度目の訪問の時は変えるみたいな処理に使える。(別に全ページ共通でもいいなら"/"でもいいです)

ページ遷移した時に高さを保持

たとえばページのどこかで何かしらのボタンを押して同ページ内で読み込みがある際に、押したボタンの位置でまた再開して欲しいみたいなことがあったとするときの対応。

$('#btn').click(function() {
  keepPosition();
});
var key = 'keep-position-'+location.pathname;
function keepPosition(){
  Cookies.set(key, $(window).scrollTop());
}
if(Cookies.get(key)){
  setTimeout(function(){
    $(window).scrollTop($.cookie(key));
    Cookies.remove(key);
  },0);
}

やってることは以下の通りです。

  1. 対象のボタンを押す
  2. その際に現在のパスと現在表示しているウィンドウの位置を保存したCookie作成
  3. 再度読み込まれる時にそのCookieが保存してたウィンドウ位置を読み込んで移動
  4. 終わったら削除する

パラメータごとでの判定

今回はパラメータの最後の部分(name)で判定するっていう場合のやつです。

http://xxx.xxx/xxx/?xxxx=xxxx&yyyy=yyyy&name=aaaa

// パラメータ取得
var params = [];
var param = location.search.substring(1).split('&');
for(var i = 0; i < param.length; i++) {
    params[i] = param[i].split('=');
}
var target = 'name';
var value;
for(var i = 0; i < params.length; i++) {
    if(params[i][0] == target) {
        value = params[i][1];
        break;
    }
}
switch (value) {
    case 'aaaa':
        Cookies.set('param1','aaaa');
    break;
    case 'bbbb':
        Cookies.set('param2','bbbb');
    break;
    case 'cccc':
        Cookies.set('param3','cccc');
    break;
}

判定箇所を絞ればわかりやすくcookieを保存してくれるはずです。

json(配列)使うのやりたい

js-cookieさんは使えるようにしている。有能。

var obj = {
    a : 'aaa',
    b : 'bbb',
    c : 'ccc'
}
Cookies.set('json',JSON.stringify(obj));
var read_obj = JSON.parse(Cookies.get('json'));
console.log(read_obj);

f:id:cardboarder:20160802214536p:plain

余談:LocalStorage

本題からそれるけどCookieでの処理だとブラウザ消しても残るので、ブラウザを消した時点で消去されるSessionStorageが使えるLocalStorageはすごいって話になった。有効期限も特になく保存量がすごいけど、使い過ぎるとまずまず重くなってくるので大したことないものならCookieで十分かと。

XSS対策のセキュアJSについて(基本編)

JavaScript jQuery XSS セキュリティ

社内ブログでまとめた内容をこっちでも書いてみる。ただ、フレームワーク使ったりしている中級者以上にはあんま参考にならないと思いますが基本編みたいなノリで御覧ください。

エスケープをする

すぐできる対策であり、割と効果的なものがエスケープ処理です。これは問題を起こしうる特殊文字文字参照に変換して、実行させないようにする処理です。対応する特殊文字「&」「<」「>」「”」「’」の5つです。

function escapeHTML(str) {
 str = str.replace(/&/g, '&amp;');
 str = str.replace(/</g, '&lt;');
 str = str.replace(/>/g, '&gt;');
 str = str.replace(/"/g, '&quot;');
 str = str.replace(/'/g, '&#39;');
 return str;
}

ちなみにES6であればテンプレートリテラル(=Template strings)を使用して下記処理もできます。

function escapeHTML() {
 var raw = String.raw.apply(null, arguments)
 var safe = raw.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''');
 return safe
}
var input = "<img src=# onerror=alert(1)>";
var html = escapeHTML`<div>${userinput}</div>`;

テンプレートリテラルの使い方は「`」(バッククオート)で囲むだけです。

URLはhttpおよびhttpsスキーム

URLを取り出し、それをデータとして扱う際に気をつけたいことは、javascriptスキームなど複数のスキームを介在させないために、リンク先がhttp://かhttps://なのかを判断して挿入するようにすることです。

var url = decodeURIComponent(location.href);
if( url.match( /^https?:\/\// ) ){
    var elm = document.getElementById("link");
    elm.setAttribute("href" url);
}

javascriptスキームはいわゆるブックマークに登録して便利な機能として使うというのが一般的ですが、それをXSSとして使用されるのを防ぐための策であります。

JSONPの取り扱い注意とJSON.parse

JSONPはクロスドメイン、つまり同一のドメインのデータでなくても引っ張ってこれるもので便利なものではありますが、同時に他者が仕組んだ悪意のあるJSONPデータも入り込む可能性があります。

JSONPをまったく使用するな、ということではないのですが使用する際は信頼のあるデータであることを証明した上で使用するのが吉です。

そしてJSONほか外部データを使用する際は必ず JSON.parse関数 を使用してください。これは文字列を JSON として解析するためのものなので、eval関数だとJSONの中に実行文が紛れていると実行されてしまう恐れがありますので意識して使いましょう。

レンダリングメソッド使用廃止

主に下記のソースになります。これは上述したエスケープ処理がない場合、確実にXSSの標的になり得ますし、この部分を使って悪用されるおそれがあるかもしれないからです。

element.innerHTML = “…”;
element.outerHTML = “…”;
document.write(…);
document.writeln(…);

jQueryに頼り過ぎるな

jQueryはjsライブラリの1つですが、煩雑なコードを容易に記述しやすくして、デザイナーさんにも扱える簡単なもので今も制作会社で広く使用されていると思われます。

実はjQueryでもXSS対策はできるものがあり、それは text() です。受け取る値をテキストデータにエスケープしてくれる代物なのでinputでの入力を即出力するものには適しています。

$('input').on('keyup', function(e){
 $('.hoge').text($(this).val());
});

しかしながら、jQuery自身の長所でもあり弱点としても見られる「DOMの直接操作」部分が割とネックとなってきています。つまりDOM操作によるXSSの介入が起こりうる可能性があるのです。

以前のver.1.6では $(location.hash) の脆弱性が指摘されており、要素の検索や作成などを引数の文字列で判断するため、$()内でスクリプトを記載すると#idで指定したものがそのまま要素として判断されることがありました(ver1.6.3にて修正済み)

http://my-web-app/#<img onerror="alert(1)" src="xxx">
$('#<img onerror="alert(1)" src="xxx">') //ハッシュ値で判断すると左の値で取得する
//<img>タグで処理されるようになってしまう。

jQuery自身もver3.0の更新(2016年5月)があったように、日々使いやすくかつ脆弱性を潰してきて、簡単な装飾程度であれば使用する面では問題無いかもですが、セキュリティ面を考えた上でwebサイト・アプリに使い続けるというのは難しい選択のようにも思えます。

なのでjQueryのみに頼り続けるのは危ないかも、というのを念頭に置いておくと良いかもしません。(※使用をやめろ!と固く禁じる訳ではないです)


こちらからは以上です。つまりReact.jsについてちゃんとやれということでした。

クオリティチェックで気をつけていること

作業効率 チェックシート 品質管理

クオリティチェックしてますか

f:id:cardboarder:20160629232846p:plain

納品前に一旦問題ないかをしっかりチェックし、品質は維持しているかを確認するクオリティチェック。皆さんの会社でも行っているかと思われます。やってないのだとしたら、自社のプログラマーがよほど立派なのか、客のことどうでもよく思っているでしょうかね。

クオリティチェック、ウチではチェックリストをデザイナー・プログラマー・ディレクターでそれぞれ設けてチェック項目を埋めていき、問題があったら都度リストにあげて作業者にパス、問題がなくなったら再度連絡してチェックしてもらう、という感じで品質維持・エラー数を減らしていってます。

ちなみに弊社ではGoogleDriveのスプレッドシートを使用して独自のクオリティチェックシートを用意しています。

チェック指摘について気をつけていること

で、表題に関してなんですが結論から言うと自分が修正するくらいのことを書くというのを気をつけています。

例えば、xhtml記述でオミットタグを忘れてバリデーションエラーが出てしまった箇所があるとしましょう。その時に

  • xxx行目 エラーあり
  • xxx行目 omitted tag エラーが発生しています

の2つがあったとしたらどちらが親切かといえば間違いなく下だと思います。そしてどういったエラーが起きているかというのも一見して分かるのでその修正箇所のエラーに対してもどう直せばいいかもわかります。

ちなみに程度問題ではありますが自分は以下まで書いてます。なるべく作業者のストレスは軽減できるように。

  • xxx行目 imgタグにオミットタグがないようです。<img src="" />修正の方お願いします。

見た目の調整も限りなく数値化する

今のはマークアップ側のエラー報告ですが、デザインの観点で言えば元のデザインと相違点があったら指摘が入ると思います。その時には

  • /xxx/xxx.html h2見出しのpaddingを上下あと10px広げてください
  • グローバルナビのホバー時のカラーを #d0d0d0 にしてください
  • ロゴの大きさをwidth : xxx px、height : yyy pxに修正していただけますか

とできるかぎり数値化・コード化してくれるとその通りに入れ込むことができるので安心です。ほかにもアニメーション挙動箇所についても何秒遅らすかとか、レスポンシブさせる時にカラム幅をいくつにするか等あるかもしれません。

チェックがただの指摘になっていないか

上述したのは主にマークアップに関するチェックなんですが、他にもインフラ側のチェックとかだと「どの条件下で発生したか」などのよりバグが発生した時の具体的な説明や期待値を述べるととてもやりやすいと思います。

結局何が言わんとするのかというとクオリティチェックをする際に他人事にしていないかということで、ただやって終わりにしないというのを徹底して欲しいなということです。

もちろん業務が分かれている以上、全員が詳細的な指摘はできないとは思いますが、いわゆる赤入れして期待値になってないときにキレる人というのはかなりの確率で他人事にしていると思います。それはひどい客がやるやつじゃんとお思いの方、案外敵は身内にいるものなのです。

何にせよやり過ぎはいけませんが、ちょっとした気遣いで全体の雰囲気は良くなります。人の振り見て我が振り直せ精神でクオリティチェックやっていきましょう。こちらからは以上です

以上精神論でしたけれど

クオリティチェックで漏れが出てしまった場合の対応策とかはまた別の機会にまとめていきます。lint的なやつとか。

関連

oyamaokuto.org

Media Queries でコンテンツ隠すのやめたい

CSS JavaScript RWD 設定

個人的に気にかかってること

よくMedia QueriesのブレークポイントでPC時とSP時でリンク先ほかコンテンツを、出したり出さなかったりする制御をしたりするんだけどあれって本当にいいのかという話。そんなことあり得るのかお前とお思いでしょうがまあ聞いてください。

以下例えばですけど、

@media screen and (min-width: 641px) {
  // PC〜TAB時のとき表示
  .pc_hoge {
    display: inline;
  }
  // SP時は非表示
  .sp_hoge {
    display: none;
  }
}
@media screen and (max-width: 640px) {
  // PC〜TAB時は非表示
  .pc_hoge {
    display: none;
  }
  // SP時のとき表示
  .sp_hoge {
    display: inline;
   }
}
<a href="http://xxxxxxxx" class="pc_hoge">PCのみ表示</a>
<a href="http://yyyyyyyy" class="sp_hoge">SPのみ表示</a>

こんな感じでaタグにクラス付けて表示・非表示するみたいな感じでやると思うけど、コレに関しての疑問。疑問というか個人的な感覚。

レスポンシブとして考えるとイカン気はする

レスポンシブ、基本1ソースなのでPCとSPのソースが混同してしまうってのは良くない気がする。理由としては

  • ブレークポイントで調整しても多様なデバイスに対応しきれない
  • TAB時の値が割と曖昧
  • PCでスマホ幅に縮めた時にSP時のためのリンクが表示されてしまう

こんな感じ。

正直別ソースで作れれば問題はないし、そもそも飛び先リンクが自動で切り替わるように調整しろよって話なんですけど、今回は別ソースにできずレスポンシブサイトを作る方面で且つリンク飛び先は何もしないという状況と仮定します。

こういう対応は、一時的な対応としてはアリだけど、上述の理由を考慮すると正しい方法ではないよなと感じます。というかRWDの対応じゃ限界を感じる。

ユーザーエージェント判定してみる

jsではユーザーエージェントを判定してそれぞれの処理を振り分けるなどのことが出来ます。なので例えば

// ユーザーエージェント判定の部分は省きます
var link = document.getElementById("ua");
if(ua.isPc){
  // PC時のリンク先
  link.href = "http://xxxxxxxx/";
} else if(ua.isTablet) {
  // TAB時のリンク先
  link.href = "http://yyyyyyyy/";
} else if(ua.isSp) {
  // SP時のリンク先
  link.href = "http://zzzzzzzz/";
}

みたいな感じでid指定してリンク先を動的に変更するやり方。組み込むソース上には影響ないけどこのためにidやらUA判定やらjsやら打つのかという問題もあります。仕方ないんですけど。

また、動的にhtml出力するのも同様の棲み分けが出来そうです。(wordpressのisMobileみたいなやつ)

結局どうしたいの

RWDの意味が無いからこういう対応するのやめたいし、やめてほしい。

あとこの辺なんとか出来そうな技術あったら教えて下さい何でもしますから。

マテリアルデザインについて学ぶ社内勉強会

Webデザイン マテリアルデザイン 資料

先週の水曜日に初主催の社内勉強会でマテリアルデザインについてやりました。

正直なところ曖昧な部分でしかしれてなかったので自分の勉強と改めて理解する・社内として共有知識にするみたいな感じでスライドつくりました。あくまで基本的な要点だけなので詳しく突っ込まれると、つらい。

speakerdeck.com

結局一番伝えたい部分はデザインのフレームワークはいっぱい出来てきたけど、流行りのために使うのではなく、自分たちの発信がどのようなものでそれに合うにはどういうフォーマットがいいか、ということを見失ってはいけないなということです。アーリーアダプターみたいな感じでもいいけど、ユーザーは皆そういう感じではないので。