Motomichi Works Blog

モトミチワークスブログです。その日学習したことについて書いている日記みたいなものです。

JavaScript学習日記 その0005 ブラウザバック時の挙動と対策について考えてみる

参考にさせて頂いたページ

まずa.htmlとb.htmlを作成する

a.html

a.htmlはbody内に以下のように記述しました。 フィールドのvalueにdefaultを入れています。 submitするとgetでb.htmlへ遷移します。

フィールドを編集してからsubmitして、b.htmlからブラウザバックしたときのイベント発火とフィールドのvalueについて検証してみます。

<h1>Page a</h1>

<form action="b.html">
  <input type="text" name="example" value="default">
  <input type="submit" value="送信">
</form>

<script>

alert('hoge');

window.onload = function(){
  alert('window.onload');
};

window.onpageshow = function(){
  alert('window.onpageshow');
};
</script>

b.html

b.htmlはbody内に以下のように記述しました。 ただh1タグがあるだけです。

<h1>Page b</h1>

今日の検証環境

Windows10の2017年4月15日現在の以下のブラウザで試しています。

a.htmlでフィールドをeditedに変更してsubmitしたあとブラウザバックしてみる

alertが実行される場合は〇、ブラウザバックしたときにフィールドのvalueは編集を保持しているかは以下の通りでした。

ブラウザ hoge window.onload window.onpageshow value
Chrome edited
Firefox × × edited
IE edited
Edge edited

a.htmlでフィールドをeditedに変更してページを更新してみる

submitせずに更新してみるパターンです。 ページ更新なのでalertは全て実行されますが、FirefoxIE、Edgeはページを一度更新してもvalueにeditedが残りました。 そのままもう一度更新すると、IEとEdgeはdefaultに戻り、Firefoxは何度更新してもeditedが残りました。 一度目の更新のあとで、残っているeditedをそのままにしてsubmitしたとき、パラメータはもちろんb.html?example=editedですが、もう一度ブラウザバックするとIEとEdgeではvalueはdefaultに戻りました。 さすがにフォーム入力途中でページ更新はイレギュラーな行動だと思いますが。

ブラウザ hoge window.onload window.onpageshow value
Chrome default
Firefox edited
IE edited ※一度だけ保持
Edge edited ※一度だけ保持

a.htmlにwindow.onunload = function(){};を記述してみる

追記して以下のようにしました。

<h1>Page a</h1>

<form action="b.html">
  <input type="text" name="example" value="default">
  <input type="submit" value="送信">
</form>

<script>
window.onunload = function(){};

alert('hoge');

window.onload = function(){
  alert('window.onload');
};

window.onpageshow = function(){
  alert('window.onpageshow');
};
</script>

Firefoxでブラウザバックしたときにhogeとwindow.onloadのalertが実行されるようになりました。 window.onunload = function(){};を書くことで、ブラウザバック時に各alert()の実行と、編集したvalueにeditedが残るというように、4つのブラウザで同じ結果を得られるようでした。 ただ、何度更新してもvalueの編集内容が保持されるFirefoxについてはどうしたものかと思います。

ブラウザ hoge window.onload window.onpageshow value
Chrome edited
Firefox edited
IE edited ※一度だけ保持
Edge edited ※一度だけ保持

jsでテキストを変更してからsubmitして、ブラウザバックしてみる

たとえばbuttonタグを配置して、以下のようなjQueryのコードを書きます。

$(function(){
  $('button').click(function(){
    $(this).text('clicked');
    $('[name="example"]').val('clicked');
  });
});

buttonをクリックして、テキストとvalueがclickedに変わったあと、submitしてブラウザバックしたときFirefoxでは以下のようになります。

  • window.onunload = function(){};が記述されていないa.htmlではclickedが保持されました。
  • window.onunload = function(){};が記述されているa.htmlではtext()で変更した箇所は元に戻っていましたが、val()で入力したvalueはあくまでもフィールドの入力値なので保持されました。

ChromeIE、Edgeではwindow.onunload = function(){};を書いても書かなくても、ブラウザバックしたときのテキストはbuttonに戻っていて、valueはclickedを保持していました。

おわりに

Macの標準的なブラウザであるSafariを試せていません。

MaciOSAndroidを試せていませんが。

対応としてはwindow.onunload = function(){};を記述して以下のような状態にするのが多くの場合第一候補な気がしました。

  • フォームの入力値はユーザの変更を保持
  • jQueryvalueを入力した箇所はフォームの入力値なのでclickedを保持
  • jQueryでのテキスト変更は無かったことにする

ということになるようでした。

vue.js 2.x その0003-02 トランジション開始前、進行中、完了後、途中キャンセルのタイミングで任意のjs処理を実行する

参考にさせて頂いたページ

公式ページ

以前書いた記事

はじめに

以前簡単なトランジションのサンプルを作ってみました。 それを発展させて、enterとleaveの各4タイミングでjsを実行するサンプルを書いてみました。

  • enter開始前
  • enter進行中
  • enter完了後
  • enter途中キャンセル
  • leave開始前
  • leave進行中
  • leave完了後
  • leave途中キャンセル

サンプルコード

<style>
.hoge-enter-active,
.hoge-leave-active {
  transition: opacity 2s
}
.hoge-enter,
.hoge-leave-to /* hoge-leave-to クラスはバージョン 2.1.8 以降でのみ利用可能 */ {
  opacity: 0
}
</style>

<div id="transition-app">
  <h1>Vue.jsのサンプル 静的なページ</h1>
  <button v-on:click="fade">click here</button>
  <transition
    name="hoge"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:after-enter="afterEnter"
    v-on:enter-cancelled="enterCancelled"
    v-on:before-leave="beforeLeave"
    v-on:leave="leave"
    v-on:after-leave="afterLeave"
    v-on:leave-cancelled="leaveCancelled"
  >
    <div v-show="state.contentIsShow">トグルするコンテンツ</div>
  </transition>
<!--/#transition-app--></div>

<script src="js/vue.js"></script>
<script>
  var fadeApp = new Vue({
    el: '#transition-app',
    data: {
      state: {
        contentIsShow: true,
      },
    },
    methods: {
      fade: function(){
        this.state.contentIsShow = !this.state.contentIsShow;
      },
      beforeEnter: function(){
        console.log('beforeEnter')
      },
      enter: function(){
        console.log('enter')
      },
      afterEnter: function(){
        console.log('afterEnter')
      },
      enterCancelled: function(){
        console.log('enterCancelled')
      },
      beforeLeave: function(){
        console.log('beforeLeave')
      },
      leave: function(){
        console.log('leave')
      },
      afterLeave: function(){
        console.log('afterLeave')
      },
      leaveCancelled: function(){
        console.log('leaveCancelled')
      },
    },
  });
</script>

vue.js 2.x その0009 watchで配列(array)や連想配列(object)を監視する

参考にさせて頂いたページ

サンプルコード

連想配列のObjectを丸ごと監視したい場合は、処理はhandler: function(){},の方に記述して、deep: true,が必要です。
連想配列のObjectを個々に監視したい場合は、watchのキーをクォーテーションで囲って'individuallyObj.aaa'のようにします。

<div id="vue-app">
  <h2>シンプル</h2>
  <input type="text" v-model="hoge">

  <h2>配列</h2>
  <input type="text" v-model="hogeArr[0]">
  <input type="text" v-model="hogeArr[1]">
  <input type="text" v-model="hogeArr[2]">

  <h2>連想配列 丸ごと</h2>
  <input type="text" v-model="hogeObj.aaa">
  <input type="text" v-model="hogeObj.bbb">

  <h2>連想配列 個々</h2>
  <input type="text" v-model="individuallyObj.aaa">
  <input type="text" v-model="individuallyObj.bbb">
</div>

<script src="js/vue.js"></script>
<script>
  new Vue({
    el: '#vue-app',
    data: {
      hoge: 'str',
      hogeArr: [
        'arr-0',
        'arr-1',
        'arr-2',
      ],
      hogeObj: {
        aaa: 'obj-aaa',
        bbb: 'obj-bbb',
      },
      individuallyObj: {
        aaa: 'object個々に監視aaa',
        bbb: 'object個々に監視bbb',
      },
    },
    watch: {
      hoge: function(val){
        console.log(val);
      },
      hogeArr: function(val){
        console.log(val);
      },
      hogeObj: {
        handler: function(val){
          console.log(val);
          console.log(val.aaa);
          console.log(val.bbb);
        },
        deep: true,
      },
      'individuallyObj.aaa': function(val){
        console.log(val);
      },
      'individuallyObj.bbb': function(val){
        console.log(val);
      },
    },
  });
</script>

vue.js 2.x その0008 テキストフィールドに数字だけ入力を許可する (郵便番号フィールド)

参考にさせて頂いたページ

HTML5におけるinput要素のpattern、type属性のおさらい - Qiita

サンプルソース

以下のように書いてみました。

<div id="vue-app">
  <h1>Vue.jsのサンプル 静的なページ</h1>
  <input type="text" v-model="postcode1">
  -
  <input type="text" v-model="postcode2">
<!--/#vue-app--></div>

<script src="js/vue.js"></script>
<script>
var vm = new Vue({
  el: '#vue-app',

  data: {
    postcode1: '',
    postcode2: '',
  },

  watch: {
    postcode1: function(val){
      var num = this.trimNumber(val);
      num = num.substr(0, 3);
      this.postcode1 = num;
    },
    postcode2: function(val){
      var num = this.trimNumber(val);
      num = num.substr(0, 4);
      this.postcode2 = num;
    },
  },

  methods: {
    trimNumber: function(val){
      var regExp = /[0-90-9]+/;
      var matchResult = val.match(regExp);
      return matchResult === null ? '' : matchResult[0];
    },
  },
});
</script>

display:flexの学習 その0001-06 cross axis方向の余白の配分(flexアイテムの配置)を設定する align-content、align-items、align-selfについて

参考にさせて頂いたページ

MDN

その他の記事

はじめに

今回は、大雑把にいうと、cross axis方向の余白を調整する方法についてです。 以下のいずれかのプロパティを設定することによって調整できます。

  • align-content(flexコンテナに設定するプロパティ)
  • align-items(flexコンテナに設定するプロパティ)
  • align-self(flexアイテムに設定するプロパティ)

align-contentについて

効果があるのはflexアイテムが複数行のとき

align-contentプロパティはflexコンテナに設定するプロパティであり、flexアイテムが複数行になっているときにのみ効果が現れるプロパティです。 よって、flex-wrapがwrapであることも前提になると思います。

サンプルコード

align-contentを使用して、cross axisのcenterに配置するサンプルコードを書いてみました。

<style>
.flex{
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  height: 600px;
  width: 600px;
  background-color: #eeeeee;
}
.flex > div{
  background: #ffdddd;
  width: 150px;
}
.flex :nth-child(1){
  background-color: #ffeeee;
}
.flex :nth-child(2){
  background-color: #eeffee;
}
.flex :nth-child(3){
  background-color: #eeeeff;
}
.flex :nth-child(4){
  background-color: #ffffee;
}
.flex :nth-child(5){
  background-color: #eeffff;
}
</style>

<div class="flex">
  <div>flexアイテム nth-child(1)</div>
  <div>flexアイテム nth-child(2)<br>テキスト</div>
  <div>flexアイテム nth-child(3)<br>テキスト<br>テキスト</div>
  <div>flexアイテム nth-child(3)<br>テキスト<br>テキスト<br>テキスト</div>
  <div>flexアイテム nth-child(3)<br>テキスト<br>テキスト<br>テキスト<br>テキスト</div>
</div>

align-itemsについて

ここを読むと解りやすかった

flexコンテナに設定するプロパティです。

基本的には「CSS3 Flexbox の各プロパティの使い方をヴィジュアルで詳しく解説 | コリス」に画像と解説があって解りやすかったです。

サンプルの構文については「align-items - CSS | MDN」が良さそうです。

ただ前提知識として、基本的な用語を理解しておく必要はやっぱりあるかもしれないです。

基本的な用語については「CSS flexible box の利用 - CSS | MDN」が参考になりました。

align-selfについて

align-itemsの値を個別に上書き

align-selfプロパティをflexアイテムに設定することによって、align-itemsで設定した値を、flexアイテム毎に上書きできます。

サンプルコード

以下のようなサンプルコードを書いてみました。

<style>
.flex{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  height: 600px;
  width: 600px;
  background-color: #eeeeee;
}
.flex > div{
  background: #ffdddd;
  width: 150px;
}
.flex :nth-child(1){
  background-color: #ffeeee;
}
.flex :nth-child(2){
  background-color: #eeffee;
}
.flex :nth-child(3){
  background-color: #eeeeff;
}
.flex :nth-child(4){
  background-color: #ffffee;
}
.flex :nth-child(5){
  background-color: #eeffff;
  align-self: flex-end;
}
</style>

<div class="flex">
  <div>flexアイテム nth-child(1)</div>
  <div>flexアイテム nth-child(2)<br>テキスト</div>
  <div>flexアイテム nth-child(3)<br>テキスト<br>テキスト</div>
  <div>flexアイテム nth-child(3)<br>テキスト<br>テキスト<br>テキスト</div>
  <div>flexアイテム nth-child(3)<br>テキスト<br>テキスト<br>テキスト<br>テキスト</div>
</div>

display:flexの学習 その0001-05 main axis方向の余白の配分(flexアイテムの配置)を設定する justify-contentについて

参考にさせて頂いたページ

MDN

その他の記事

はじめに

今回は、大雑把にいうと、main axis方向の余白の配分についてです。

  • main-start側にflexアイテムを詰めて配置する
  • main-end側にflexアイテムを詰めて配置する
  • main-start、main-endに余白を均等に配分してflexアイテム同士はcenterに詰めて配置する
  • main-start、main-end、flexアイテムの間に余白を均等に配分する
  • main-start、main-endには余白を入れず、flexアイテムの間だけに余白を均等に配分する

main-startやmain-endとあるように、flex-directionの値をもとに、縦方向または横方向の余白が調整されます。

画像も合わせた解説はコリス

画像つきの説明によって、flexアイテムと余白の関係性が解りやすいのが「CSS3 Flexbox の各プロパティの使い方をヴィジュアルで詳しく解説 | コリス」でした。

2016年12月14日に公開された記事で、現在の日付から比較的新しくて解りやすかったです。

文字での解説はMDN

文字での説明はサンプルコードも含めて「justify-content - CSS | MDN」がとても解りやすかったです。

以下は引用です。

CSS justify-content プロパティは、コンテナの main-axis に沿ってスペースを flex アイテムの間や周囲へどのように分配するかを定義します。

長さや自動マージンが適用された後に配置が行われることから、flex-grow が 0 ではない flexible 要素が少なくとも 1 つある場合は利用可能なスペースがなくなりますので、このプロパティの効果はないでしょう。

display:flexの学習 その0001-04 flexアイテムの並び順を個別に指定する orderについて

参考にさせて頂いたページ

orderについて

flexアイテムに設定するプロパティです。 直感的にわかりやすいので、参考ページから特に補足することもありませんでした。