2014年7月19日土曜日

Firefoxで戻るボタンを押した際に二重送信防止を解除する

今回はFirefox(テストで利用したバージョンは30.0)における厄介な挙動をJavaScriptで解決しようというお話。 IE 11や最新のChrome(35系)では特に気にする必要はないものです。

フォームで二重押下を防止するために、1度ボタンを押すとボタンの状態をdisabledにするということがあります。 そこまでは何も問題ないのですが、Firefoxではボタンを押してsubmitをした後に、戻るボタンを押すとdisabledの状態が継続しており、 再度submitができない状態になってしまいます。もう一度戻るボタンを押すとsubmitできるようになるのですが、 その挙動は一般的にユーザが想定していないものであるはず。

そこで、jQuery(利用したバージョンは1.11.0)を利用して、 一度戻るボタンを押すだけでdisabledの状態が解除できるようにしてみました。コードは以下のようになります。

<script type="text/javascript"><!--
$(document).ready(function() {
    $(window).unload(function(){});
    $('#button').attr('disabled', false);
});
--></script>

1行目はDOMを構築した後に実行せよという意味です(おまじないと思って差し支えないでしょう)。 2行目はBackForwardCacheを無効にせよという意味になります。元のページに遷移した際にキャッシュを使うなという意味になります。 つまり、ボタンを押したという状態を使うなということになります。 3行目はボタンにdisabled属性をfalseにせよという意味で、ボタンを利用可能にするという意味になります。 初期状態はfalseでなければならないので、明示的に設定しました。

これにより、ボタンを1度叩いてdisabledになった状態でブラウザの戻るボタンを押しても、disabledの状態にならなくなります。 ただし、フォームにあった情報(入力したテキスト等)はすべて落ちてしまうので、再入力が必要になります。 もっとも、それは仕様としてしまっても良いとは思いますが。

2014年4月26日土曜日

jQueryの個人的メモその2

$(document).ready(function(){..})は$(function(){...})のように省略できる。

要素を指定して何かをする場合は次のように書く。セレクタについてはクラス、ID、要素が指定できる。

 $(セレクタ).メソッド(パラメータ);

何かの要素の下にある要素を指定する場合はセレクタをスペースを空けて並べればよい。以下の例ではpタグの下にある.warn要素で囲まれた箇所の色を赤に変更している。

 $("p .warn").css("color", "red");

*(ユニバーサルセレクタ)を使うと、ワイルドカードのように振る舞うことになる。pタグの下にある要素で囲まれたものすべてについて色を赤に変えることになる。pタグの下にあるセレクタ以下にある要素が変わるのであって、pタグの直下にあるものについては変わらない。

 $("p *").css("color", "red");

セレクタの箇所はカンマで区切ることで、複数の要素をまとめて指定することができる。

 $(".left, .right").css("color", "red");

チャイルドセレクタは直下にあるものに絞る。上の例は子孫セレクタであり、深さを問わない指定方法であるという点で異なる。

 $("p > .warn").css("color", "red");

隣接セレクタは連続する2つの要素を指定し、2つ目に指定したものが指定されたものになる。以下ではh2要素に隣接するh3要素が指定されることになる。

 $("h2 + h3").css("color", "blue");

間接セレクタは同じ親を持つ要素で指定した要素より後ろにあるものすべてを指定する。以下ではliにsecondというidを割り振っておけば、ulという親があるため、secondより後ろにあるli要素の色がすべて赤になる。

 $("#second ~ li").css("color", "red");

CSSにおける要の素指定方法とjQueryのセレクタ指定方法は良く似ていることが確認できる。

2014年4月21日月曜日

jQueryの個人的メモその1

HTMLのヘッダにjQueryのライブラリへのパスを設定しておくことが多い。ページの表示速度を考慮してjQueryの読み込み後回しにするため、bodyタグの一番最後に書くこともある(=多くの場合、その後ろはhtmlタグを閉じるだけであろう)。ローカルにダウンロードしてそのパスを設定してもよいし、CDN(Contents Delivery Network)に置かれているjQueryのライブラリを指定して読み込んでも良い。CDNは例えば以下に挙げたURLを指定することになる(詳しくはこちらを参照)。なお、外部との通信が発生するので、通信内容を暗号化する目的でhttpsでURLを指定することも考慮すべきである(以下のURLの場合、Googleの方ではできる)。

  • http://code.jquery.com/jquery-1.11.0.min.js
  • http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js

以下の例ではwarnクラスの要素を赤にする。例えば注意書きを囲うときに使える。

$(document).ready(function(){
 $(".warn").css("color", "red");
}

上のコードの1行目の意味はページがjQueryを実行する準備ができたらという意味である。これを書かないでいると、読み込む前にwarnクラスの要素が出てこないので、warnクラスの要素の色を変えることができない。なお、readyを用いた場合、画像の読み込みは後回し(jQueryのライブラリを読み込んだ後)となる。画像を読み込んでからjQueryのライブラリの読み込みを実行したい場合は次のようになる。画像をjQueryで変化させたいときに使うことになる。

$(window).on("load", function(){
 $(".warn").css("color", "red");
}

ただし、画像に手を加えないのであれば、パフォーマンスを考慮して前者の書き方を採用することが一般的である。

2014年3月15日土曜日

TopCoder SRM485 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文についておおまかに説明する。

マナオはすべての商品が正の整数の価格を持つ国に住んでいる。彼は電子レンジを売る会社を立ち上げており、それらを売るのに最適な価格を決める必要がある。最近彼は新しい心理学的な発見を聞いた。それは価格の小さい方の桁に9が続くにつれて、消費者に魅力的になるというものである。たとえば9099は9が2つ、8909は1つ9が最後にあるので、前者が魅力的ということになる。

マナオはminPriceを下回らない価格でのみ売る余裕があり、消費者はmaxPriceを超えない価格でしか電子レンジを買わないということを把握している。minPriceとmaxPriceの間で9が最大限後ろに続く数のうち最大のものを見つけることでマナオを手助けせよ。

public class MicrowaveSelling {

 public int mostAttractivePrice(int minPrice, int maxPrice) {
  int nNine = 0;
  int price = minPrice;
  for( int i=minPrice ; i<=maxPrice ; i++ ) {
   int nCurrent = trailing(i, 9);
   if( nCurrent >= nNine ) {
    price = i;
    nNine = nCurrent;
   }
  }
  return price;
 }
 private int trailing(int num, int target){
  int n = 0;
  while( num >= 1 ){
   if( num % 10 == 9 ){
    n++;
   }else{
    return n;
   }
   num /= 10;
  }
  return n;
 }

}

得点は173.37/250、3回目のsubmitでシステムテストクリア。ちなみにtrailingは「後端の」という意味です。

2014年3月12日水曜日

TopCoder SRM484 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文についておおまかに説明する。

カード1には1~8の整数、カード2には1~4、9~12の整数、カード3には1、2、5、6、9、10、13、14、カード4には1~15の奇数が書かれている。太郎は花子に対して、1~16の整数を1つ思い浮かべ、それが各カードに含まれているか否かを尋ねた。その答えで整数は唯一に定まる。引数のanswerという文字列にはYないしNという文字が入り、カードiに数字が含まれているか否かの回答はi番目の文字に対応しているものとする(Yなら含まれる、Nなら含まれない)。このとき、花子が想像している数字を返すメソッドを作成せよ。

import java.util.ArrayList;

public class NumberMagicEasy {

 public int theNumber(String answer) {
  int[][] numbers = {{1, 2, 3, 4, 5, 6, 7, 8},
    {1, 2, 3, 4, 9, 10, 11, 12},
    {1, 2, 5, 6, 9, 10, 13, 14},
    {1, 3, 5, 7, 9, 11, 13, 15}
  };
  int[] pts = new int[16];
  if( answer.indexOf("Y") == -1 ) return 16; // 全部Nなら16
  for( int i=0 ; i<answer.length() ; i++ ){
   if( answer.charAt(i) == 'Y' ){
    for( int j=0 ; j<numbers[i].length ; j++ ){
     pts[numbers[i][j]-1] += 1;
    }
   }else{
    ArrayList<Integer> al = new ArrayList();
    for( int j=1 ; j<16 ; j++ ){
     al.add(j);
    }
    for( int j=0 ; j<numbers[i].length ; j++ ){
     if( al.contains(numbers[i][j]) ){
      int idx = al.indexOf(numbers[i][j]);
      al.remove(idx);
     }
    }
    for( int j=0 ; j<al.size() ; j++ ){
     pts[al.get(j)-1]++;
    }
    al.clear();
   }
  }
  for( int i=0 ; i<pts.length ; i++ ){ // 全部の条件にマッチする数字を返す
   if( pts[i] == numbers.length ) return i+1;
  }
  return 16;
 }

}

得点は117.24/250、1回のsubmitでシステムテストクリア。削除の仕様に対する設計がちょっと面倒でした。方針としては、各質問の回答で条件に合う数字に1点、合わない数字は0点をつけて、4回の質問で4点(=全部の条件に合う)になったものが答えになるように実装しました。

2014年3月3日月曜日

TopCoder SRM483 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文についておおまかに説明する。

エリーのやっかいな教育アシスタントのトーブはエリーに次のパズルを与えた。42->1、1337->0、669->3(もう少し続く)。このとき45678は何になるか?エリーは考えるのが早く、問題を解く直感のおかげで解法を思いついた。Googleである。答えは10進数で表記したときの数字の桁に含まれる穴の数の合計であるとわかった(桁の先頭に0埋めはしない)。1、2、3、5、7は穴が無く、0、4、6、9は穴が1つ、8は2つある。したがって45678は1+0+1+0+2=4となる。あなたはエリーに好印象を与えるために、ある整数から正しい答えを導くプログラムを書くことにした。整数numberが与えられたとき、その数に含まれる穴の数の合計を返せ。

public class DigitHoles {

 public int numHoles(int number) {
  int[] holes = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
  char[] cnumber = ("" + number).toCharArray();
  int nholes = 0;
  for( int i=0 ; i<cnumber.length ; i++ ){
   nholes += holes[cnumber[i] - '0'];
  }
  return nholes;
 }

}

得点は245.00/250、1回のsubmitでシステムテストクリア。配列で穴の数を管理するのが一番簡単そうな気がします。

2014年3月2日日曜日

2014年1月の学習記録

最近ブログから離れがちなのは、仕事の煮詰まり具合によるものです。あと半年ぐらい続きそうな感がありますが、どうぞお付き合いくださいませ。

SpringによるWebアプリケーションスーパーサンプル 第2版(第1~3章)
初めて触るフレームワークなのですが、「設定より規約」ということで、どのようなルールがあるかということを理解していないと、簡単な書き方ができずに苦労しそうです。ちなみにパイロットプロジェクトとして問い合わせフォームを作り始めたのですが、参考書からちょっと外れるだけでかなり嵌っています。たとえば「戻る」ボタンを押したときにデータを保持したまま移動するという機能を実装するとか。いきなりMVCやオブジェクト指向をやっており、ショック療法を受けている真只中であります。
独習 Javaサーバサイド編 第2版(pp.1~80)
Springでの開発はjspを利用しているので、Web開発の教養と思って併読。

その他センター試験の数学を解くなど。私見ですが、今年の数学の問題は簡単な方だったと思います。

フォロワー

ページビューの合計