6.プロジェクトの構成

初めに

 空のプロジェクトを作成するまでは、 3章 に記述しました。ここでは、それ以降の作業について議論したいと思います。
 その話題は以下のものになります。

  • Web Form の場合
    Web Form で作業を進めていくうえでの一般的な話題を書きます
  • MVC の場合
    MVC で作業を進めていくうえでの一般的な話題を書きます
  • ブラウザの機能
    ブラウザで利用している技術は、 Web Form や MVC といったサーバー側の技術とは独立です
    2つのプログラムで共通に使用している技術に関して書きます

 Web Form と MVC の2つのプログラムで提供している画面については、 2章 で説明しました。画面数は決して多くはありません。
 そして、マスタ系の画面はほぼ同じような見た目と操作方法になっています。また、フィールドワークデータを操作する画面も複雑なものではありません。 そこで、これ以降の実装に関する議論では、以下の画面に限定して説明したいと思います。

  • 大分類画面
    マスタ系の画面の代表として取り上げます
  • フィールドワークデータ一覧画面
    フィールドワークデータを検索し、その一覧を表示する画面です
  • フィールドワークデータ追加画面
    フィールドワークデータに関連して、追加の画面を取り上げます
  • 地図操作画面
    Google Map Api を利用した画面を簡単に取り上げます
    この画面は、 Web Form と MVC との違いはほとんどありません

Web Form の場合

 Web Form でプログラムを開発する場合、最初に検討するのは、どのような画面がいくつ必要かということです。作業の中心となるのは画面です。 そこで、以下の作業を順に行うことになります。

  • その画面に対応した、Web フォームを追加
    Web フォームは、画面要素の部分と処理内容であるプログラム部分とが一体となっています
    このWeb フォームを必要な数だけ作成することになります
  • 画面要素は、html で定義
    画面要素は、 Web フォームの構成要素中 aspx の拡張子を持つファイルに、html の書式で記述します
    その中に、asp: で始まる特殊タグと html の通常のタグによりブラウザに表示される画面を構築していきます
    画面の構築については、 html の一般的な知識と Web Form 専用の asp: で始まる特殊タグに関する知識が必要です
  • プログラム部分は、 C# で記述
    プログラム部分は、Web フォームの構成要素中 aspx.cs の拡張子を持つファイルに、 C# で記述していきます
    Windows Form や Windows WPF と同様に、さまざまなイベントハンドラを記述することになります
    もちろん、VB.NET で記述することも可能です(その場合の拡張子は、 aspx.vb となります)

 Web Form でプログラムを作ろうとした場合、上記の Web フォームクラス一つだけでプログラムの記述が可能となります。 C# の部分ですべてのプログラムを書いてしまうというやり方です。 この条件だけが必須であって、これ以外の設計や実装の指針が強制されることはありません。このことは、ややもすればスパゲッティプログラムにつながりかねないといえます。

そこで、次のようなフォルダー階層を導入して、役割を明確にすることにしました。

画面1
  • Ajax
    Web サービスとして実装し、 Ajax により呼び出される機能を収めたフォルダーです
    その説明は こちら を参照してください
  • Data
    モデルクラスのうち、データベース関連のクラスを収めたフォルダーです
    その説明は こちら を参照してください
  • Fieldwork
    フィールドワークデータを操作する Web フォームクラスを収めたフォルダーです
  • MapPage
    地図画面を表示するための Web フォームクラスを収めたフォルダーです
  • MasterDataPage
    マスタ系の Web フォームクラスを収めたフォルダーです
  • Model
    モデルクラスのうち、問題領域クラスを収めたフォルダーです
    その説明は こちら を参照してください
  • resource
    html で使用するさまざまなリソースを収めたフォルダーです
    • cs
      CSS ファイルを収めたフォルダーです
    • img
      イメージファイルを収めたフォルダーです
    • js
      javascript を収めたフォルダーです

 すべての Web フォームクラスの親となる BasePage クラスのソースは一番上のフォルダーにあります。 BasePage の説明は こちら を参照してください。

 MVC と比較した場合、View クラスは Web フォームクラスの html に対応し、 Controller クラスは Web フォームクラスの プログラム部分に対応すると考えると分かりやすいかもしれません。
 Web Form では、 Web フォームクラスは画面部分とプログラム部分が一体となったクラスですので、プログラムの中心となるのはこのクラスであるのは当然ですね。
 そしてモデルクラスについては、 Web Form と MVC に関係なく、ほぼ流用が可能となります。これもまた当然の結果ですね。 モデルクラスは、今プログラムを作成しようとしているその分野に対応したクラスのことです。 Web Form や MVC といったサーバー側の実現手法とは独立したクラスになります。

aspx ファイルのテンプレート

  Visual Studio を使用して Web フォームを追加すると、拡張子 aspx を持つファイルが作られます。このファイルにブラウザで表示される html の基となるタグを記述していきます。
 以下に、今回の Web Form で使用している aspx ファイルのテンプレートを示します。デフォルトで作成される aspx ファイルとは内容が違っていますので、必要に応じて読み替えや書き換えを行ってください。

            		
1     <code><%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XXX.aspx.cs" Inherits="NNN.XXX" %>

2     <!DOCTYPE html>
3     <html lang="ja">
4     <head id="Head1" runat="server">
5         <meta charset="utf-8">
6         <title></title>
7         <link href="../resource/css/bootstrap.min.css" rel="stylesheet" />
8         <script src="../resource/js/jquery-3.1.0.min.js"<>/script>
9         <script src="../resource/js/bootstrap.min.js"></script>
10        <script>
11            $(function () {
12            });
13        </script>
14        <style type="text/css">
15        </style>
16    </head>
17    <body>
18    </body>
19    </html>
            		
            		

 1行目:Web フォームの情報が自動的に生成されます
 2行目:html 5 で記述することを指定しています
 6行目:タイトルを記述してください
 7~9行目:使用する CSS ファイルと javascript ファイルを指定します
 10~13行目:jQuery プログラムを記述する場所になります
 14~15行目:html 中に直接 CSS を記述する場所になります
 17~18行目:この位置に、 html の標準タグや asp: を先頭に持つ特殊タグを書き込んでいきます。特殊タグは Web サーバにより解釈・処理されます。その結果は html の標準タグに変換されてブラウザに返されますので、 どの特殊タグがどのような標準タグに変換されるかは知悉している必要があります

aspx.cs ファイルのテンプレート

  Web フォームを追加すると、拡張子 aspx.cs を持つファイルも同時に作られます。このファイルに C# のプログラムを記述することになります。
 以下に、 aspx.cs ファイルのテンプレートを示します。デフォルトの内容とは違っていますし、 import などは省略しています。読み替えや書き換えを行ってください。

            		
1     namespace NNN
2     {
3         public partial class XXX : BasePage
4         {
5             protected void Page_Load(object sender, EventArgs e)
6             {

7             }
8         }
9     }
            		

 1行目:名前空間の定義です
 2行目:Web フォームクラス名の定義です。 BasePage については こちら を参照してください
 5~7行目:ページがロードされた時に呼び出されるハンドラの定義です
 7行目以降:この部分に、さまざまなハンドラなどの必要なメソッドを追加していきます。


Page_Load() イベントについて

 ページがロードされるときのイベントは Windows Form や Windows WPF でも馴染みのあるイベントです。それは XXX_Loaded (XXX はクラス名)というメソッド名になります。
 しかし、このイベントが発生するタイミングが Web アプリケーションと Windows アプリケーションとでは異なります。

  Windows アプリケーションの場合、このイベントはそのウィンドウが生成されて、初めて表示されるとき一度だけ発生します。一方、 Web アプリケーションの場合、ブラウザから Web サーバに要求があるたびに発生します。

 ブラウザからの要求に対して、 Web サーバが応答をブラウザに返すと、そのあいだの処理に使用したリソースはすべて開放してしまいます。次にブラウザから要求があった場合には、このページを再構築する必要がありますので、 このイベントが発生することになるわけです。
 このことは、初めて Web アプリケーションを作成する人が戸惑う点の一つと思います。
 初めての要求で発生したイベントなのか、2回目以降の要求によるイベントなのかを調べるには、 IsPostBack を利用することができます。

						
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // 初めての時だけの処理を記述する
        }
    }
						

MVC の場合

 Web MVC でプログラムを開発するとなった場合、設計や実装の上で一定の制約が課されてきます。また、標準となるフォルダー構成も決まります。
 そして、 Web MVC プログラムで中心となるクラスはコントローラクラスになります。
 標準のフォルダー構成に準拠したうえで、さらに以下のようなフォルダーを導入することにしました。

画面2
  • Ajax
    Web サービスとして実装し、 Ajax により呼び出される機能を収めたフォルダーです
    その説明は こちら を参照してください
  • App_Data
    デフォルトのままです
  • App_Start
    デフォルトのままです
  • Contents
    CSS と イメージファイルを収めるフォルダーです
  • Controllers
    Controller クラスを収めるフォルダーです
  • Data
    モデルクラスのうち、データベース関連のクラスを収めたフォルダーです
    その説明は こちら を参照してください
  • Deploy
    デプロイ用パッケージを収めるフォルダーです
    その説明は こちら を参照してください
  • Fonts
    bootstrap が使用するフォント用のフォルダーです
  • MapPage
    地図画面を表示するための Web フォームクラスを収めたフォルダーです
  • Models
    モデルクラスのうち、問題領域クラスを収めたフォルダーです
    その説明は こちら を参照してください
  • Scripts
    javascript を収めたフォルダーです
  • Views
    View クラスを収めたフォルダーです
    対応する Controller クラスごとにサブフォルダーの階層になっています
    複数の View で利用される部分ビューを格納する Shared も存在します

状態遷移図

 MVC の分かりにくさは、 こちら に書きました。ではどのように考えたら、コントローラクラスが分かりやすくなるのか?
 そのカギとなるのは状態遷移図だと思います。例があった方が議論が進めやすいので、マスタ系の画面である大分類画面を取り上げます。 その画面と操作方法の詳細については、 こちら を参照してください。画面を再掲します。(画像をクリックすると、拡大表示します)

画面3

 状態遷移図とは、プログラムがとりうる状態と、その状態間を遷移していく原因を表現したものになります。仕様によってある程度は決まってきますが、 設計によっても変わってきます。そのため、これが正解といったものはありません。以下では、今回 Web MVC で採用した大分類画面の状態遷移図を示します。

画面4

 状態遷移図の簡単な説明です

  • 開始点
    出る向きの矢印からなる小円です
    処理が開始される場所を表します
    この図の一番上にあるものが該当します
  • 終了点
    入る向きの矢印からなる小円です
    処理の終了場所を表しますが、この図にはありません。 Web アプリケーションでは一般的には不要でしょうか
  • 状態
    楕円とその状態名で表します
    今回は、「初期状態」と「読出後」の2つの状態を持ちます
  • 矢印
    今の状態から次の状態への遷移を示します
    その遷移の原因となった理由と結果をラベルで現します
    「更新:成功」は、更新処理が成功した場合の状態遷移です
    「更新:失敗」は、更新処理が失敗した場合の状態遷移です(実際は、遷移せず、エラー内容を返します)

 これ以降の状態遷移図では、エラー発生時の状態遷移は示さないこととします。エラー発生時には元の状態にとどまります。そうではない例外の場合にだけ、記述することにします。
 また、自明と思われる場合は「クリア」による状態遷移も示しません。「初期状態」に遷移すると考えてください。

 それでは、この状態遷移図をコントローラクラスの構造に読み替えてみましょう。
 まず、状態を2つ持ちますから、以下のメソッドが必要です。ただし、「読出後」の状態を必要としないとすることも可能です。 そうすると、一つの状態でまかなってしまうことになります。 Web Form のプログラムは、状態が一つだけとなっていると考えるとよいかもしれません。

  • 初期状態-Index
    初期状態に対応したメソッドです
    メソッド名は慣習的に、 Index と決めました
  • 読出後-Selected
    読出後に対応したメソッドです
    初期状態から、読出ボタンのクリックで遷移してきます

 上記の2つの状態は、どちらもその状態に入ってくる矢印と、その状態から出ていく矢印があります。そこで、上記のメソッドはさらに2つに分かれたメソッドが必要になります。

  • GET 用 Index
    初期状態に入ってくる場合に対応したメソッドです
    ブラウザからの要求により、無条件に到達する状態です
  • POST 用 Index
    初期状態から出ていく場合に対応したメソッドです
    このメソッドでは、追加と読出ボタンの処理を記述します
  • GET 用 Selected
    読出後に入ってくる場合に対応したメソッドです
    読出後の画面を返す処理を行います
  • POST 用 Selected
    読出後から出ていく場合に対応したメソッドです
    このメソッドでは、更新・削除・クリアの処理を行います
    更新と削除では、その処理の結果-成功か?失敗か?-に応じて遷移先が異なります

 状態遷移図からコントローラの構造が透けて見えてきたと思います。ここまでくれば、必要なビューも自明になるでしょう。 MVC で作成するとなった場合、 設計資料には状態遷移図が欠かせないものになると思います。

コントローラクラスのテンプレート

 コントローラクラスのテンプレートを示します。 import などは省略してありますので、読み替えや書き換えを行ってください。

            		
1     namespace NNN
2     {
3         public class XXX : FieldworkController
4         {
5            // GET: Default
6            public ActionResult Index()
7            {
8                return View();
9            }
10        }
11    }
            		

 1行目:このクラスが含まれる名前空間の宣言です
 2行目:クラス名の定義です。親クラスとなる FieldworkController については こちら を参照してください
 6行目:デフォルトの GET 用初期状態に対応したメソッドです。必要に応じて、メソッド名や処理内容を変更してください
 8行目:GET 用初期状態の画面を呼び出しています。必要に応じて変更してください

ビュークラスの作成方法

  Web MVC プログラムの中心となるのはコントローラクラスです。ビュークラスを作成するには、コントローラクラスから作成するのが一般的と思います。その手順は、次のようになります。

  • コントローラクラスのソースを表示
  • ビューを定義したいコントローラのメソッドに移動
  • マウスの右ボタンメニューから「ビューを追加」を選択
  • 必要な項目を入力
    「ビュー名」を必要に応じて変更します(デフォルトではコントローラのメソッド名と同じです)
    「テンプレート」では、「Empty」を選択することをお勧めします
    「モデル」では、ビューで使用するモデルを選択します(ビューの作成前に、モデルクラスの作成が終了していることが必要です)
  • ビュークラスの確認
    「Views/コントローラ名」の下に、指定したビュークラスのファイルができていることを確認してください

 この操作手順からも、 MVC の中心はコントローラクラスであることが分かると思います。

ビュークラスのテンプレート

 ビュークラスのテンプレートを示します。必要に応じて、読み替えてください。

            		
1     @model XXX

2     @{
3         Layout = null;
4     }

5     <!DOCTYPE html>

6     <html lang="ja">
7     <head>
8         <meta name="viewport" content="width=device-width" />
9         <title>タイトル</title>
10        <link href="~/Contents/bootstrap.min.css" rel="stylesheet" />
11        <link href="~/Contents/common.css" rel="stylesheet" />
12        <link href="~/Contents/fieldwork-base.css" rel="stylesheet" />
13        <script src="~/Scripts/jquery-3.1.0.min.js"></script>
14        <script src="~/Scripts/bootstrap.min.js"></script>
15        <script src="~/Scripts/bluesky.js"></script>
16        <script>
17            $(function () {
18            });
19        </script>
20    </head>
21    <body>
22        <div>
23            @using (Html.BeginForm())
24            {
25            }
26        </div>
27    </body>
28    </html>
            		

 1行目:モデルクラスを指定します。このビューで表示するためのデータを管理しているのがモデルクラスです
 5行目:html 5 で記述することを指定します
 9行目:タイトルを指定します
 10~15行目:CSS と javascript ファイルを指定します
 16~19行目:jQuery を記述する場所です
 23~26行目:<form> タグの本体を記述する場所です


Post-Redirect-Get(PRG) について

 ブラウザから POST 要求がサーバに届いた場合、必要な処理を行って次にどうするか?処理が失敗したならば、そのエラー内容をブラウザに返すことになりますが、 成功した場合は次の遷移先の URL をブラウザに送り返し(Redirect)、ブラウザは新しい URL に対して GET 要求を再度だすようにするのが定石です。
 サーバとブラウザ間に一回余分なやり取りが発生しますが、この処理がユーザの操作からは望ましい手順になります。 POST 要求の結果をそのままブラウザに 返した場合、その POST 要求はブラウザの履歴に残ってしまいます。すると、ブラウザの「再読込」や「前ページ」「次ページ」ボタンをクリックするたびに、履歴にある POST 要求が出されてしまいます。 これは望ましくないですね。

 さて、ここまでは復習です。 Web Form と MVC とを比較すると、 Web Form では気が付かないうちに Post-Redirect-Get パターン違反を犯しやすい気がします。
 とくに気が付きにくいと思われるのは、コンボボックスで項目を選択した場合です。この場合、 Web Form では以下のようにすることが多いでしょう。

						
<asp:DropDownList ID="XXX" runat="server" AutoPostBack="true"
    OnSelectedIndexChanged="XXX_SelectedIndexChanged">
</asp:DropDownList>

						

 asp:DropDownList を AutoPostBack="true" で使用するものです。こうすると、コンボボックスから選択するたびにポストバッグが発生します。 その時に起動される XXX_SelectedIndexChanged メソッドでは、処理結果をそのままブラウザに返すことが多いでしょう。つまり、PRG パターン違反になります。 この場合のパターン違反をどう考えるかは、面倒な問題ですね。これといった実害はないのですが、不可思議なメッセージ(以下に記述)がユーザに提示されるのは望ましくありません。

 MVC でも気が付きにくいパターン違反の場合があります。 こちら の状態遷移図において「初期状態」から「追加」で遷移した場合です。 追加処理が失敗した場合は、そのまま遷移する必要がありません。一方、追加が成功した場合は次のように2つの実装があり得ます。

						
    // PRG パターン違反の例
    if (処理は成功か?)
    {
        return Index();
    }
    
    // PRG パターンに従った例
    if (処理は成功か?)
    {
        return RedirectToAction("Index");
    }
						
						

 処理が成功した場合に、そのまま初期画面をブラウザに返すのか、一度リダイレクトさせるのかの違いになります。う~ん、めんどくさい。

 現在の画面が、PRG パターンに準拠しているかどうかを試すには、ブラウザの「再読込」ボタンをクリックするのが簡単です。 次のメッセージが表示された場合、パターン違反を犯しています。

 これはブラウザに Chrome を使用している場合になります。ご使用のブラウザと読み替えてください。

ブラウザの処理

 ブラウザの処理は javascript で直接記述することをしません。より記述力が高い jQuery を選択しました。そして、この処理はサーバー側の技術とは関連していません。独立した部分になります。そのため、 Web Form や MVC に限らず、例えば Java で開発した Web アプリケーションでも利用可能です。
 ここでは、 jQuery さらには bootstrap を使ってライブラリ的に利用可能な便利な機能を取り上げます。

モーダル画面を中央に表示する方法

 モーダル画面は bootstrap の機能を利用しています。デフォルトではモーダルダイアログは、画面の上1/3くらいの位置に表示されます。 これを、画面中に表示するには次のようにします。

						
     <!-- jQuery の一部 -->
1    $(function () {
2        $(".modal").on("show.bs.modal", function () {
3            $(this).css("display", "block");
4            var dialog = $(this).find(".modal-dialog");
5            var offset = ($(window).innerHeight() - dialog.height()) / 2;
6            dialog.css("margin-top", offset);
7        });
8    });
						
						

 注意が必要なのは、2行目:モーダルには「class="modal"」の記述が必要という点だけです。

ボタンの二重押し禁止の方法

 この方法も bootstrap のモーダルダイアログを利用しています。ブラウザからのサブミット時に、全画面をモーダルダイアログでおおってしまい、サーバーからの応答があるまで 画面操作を禁止することで実現しています。

						
     <!-- jQuery の一部 -->
1    $("#mainForm").submit(function () {
2        $(".modal").hide();
3        $("#hideModal").modal();
4        return true;
5    });

     <!-- html の一部 -->
      略    
6    <form id="mainForm" method="post">
      略
7    <div id="hideModal" class="modal" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false">
8       <div class="modal-dialog modal-sm">
9           <div class="modal-content">
10              <div class="modal-body">
11                  <img src="~/Contents/loader.gif" alt="" />
12                    <strong>Loading ...</strong>
13              </div>
14          </div>
15      </div>
16   </div>

						

 1行目: <form> がサブミットされたときに、ダイアログが表示されます。<form> タグの id は「mainForm」固定です
 2行目:表示中のダイアログがあれば表示を消します
 3行目:二重押し禁止用のダイアログを表示します
 6行目:<form> タグの id に注意
 7行目:マウスクリックでモーダル中止を禁止するのが、 data-backdrop="static"。 ESC キー入力でモーダル中止を禁止するのが、 data-keyboard="false"。この2つが重要な部分です
 7~16行目:二重押し禁止用のダイアログの本体です

添付ファイルのカスタマイズの方法

 添付ファイルは <input> タグの type="file" で行います。この時の”添付”ボタンの外観を bootstrap のボタンに合わせる方法です。

						
     <!-- html の一部 -->
1    <button class="btn btn-primary" type="button" onclick="$('#fileUpload').click();">ファイルを選択</button>
2    <label id="fileName">選択されていません</label>
3    <input class="hidden" id="fileUpload" multiple="multiple" name="fileUpload" type="file" value="" />
						
						

 1~2行目:ボタンとラベルを並べて、添付ファイル用の表示を自前で用意する。ボタンクリック時に、 hidden 項目の本来の添付ファイルを起動する
 3行目: hidden として消されている添付ファイル項目

自前の jQuery 関数

 ブラウザでエラー検査を行いますが、その際に使用している jQuery の関数を示します。大量のコメントが付いていますので、説明がなくとも理解は容易と思います。

						
(function ($) {
    /*
    入力がなにもないかどうかを検査する
    空白コードが存在しても,入力があったと判断する
      
    戻り値:
    入力がない場合にtrue,そうでない場合にfalse
    */
    $.fn.isNull = function () {
        return (this.val().length == 0);
    };

    /*
    引数で指定した文字数が入力されているかどうかを検査する
       
    引数:
    min 最少文字数
    max 最大文字数
      
    戻り値:
    必要な文字数が入力されている場合にtrue,そうでない場合にfalse
    */
    $.fn.isValidLength = function (min, max) {
        var len = this.val().length;
        return (len >= min && len <= max);
    };

    /*
    数字キー(0-9)以外のキーが入力されていないかどうかを検査する
    入力がない場合も真と判断するため,必須項目の場合は,isNull()と併用すること
       
    戻り値:
    数字キーだけまたは空文字列の場合にtrue,そうでない場合にfalse
    */
    $.fn.isNumber = function () {
        var value = this.val();
        if (value.length == 0)
            return true;

        return !(value.match(/^\d+$/));
    };

    /*
    英文字以外のキーが入力されていないかどうかを検査する
    入力がない場合も真と判断するため,必須項目の場合は,isNull()と併用すること

    戻り値:
    英文字だけまたは空文字列の場合にtrue,そうでない場合にfalse
    */
    $.fn.isAlpha = function () {
        var value = this.val();
        if (value.length == 0)
            return true;

        return !(value.match(/[^a-zA-Z]/));
    };

    /*
    英数文字以外のキーが入力されていないかどうかを検査する
    入力がない場合も真と判断するため,必須項目の場合は,isNull()と併用すること

    戻り値:
    英数文字だけまたは空文字列の場合にtrue,そうでない場合にfalse
    */
    $.fn.isAlphaNumber = function () {
        var value = this.val();
        if (value.length == 0)
            return true;

        return !(value.match(/[^0-9a-zA-Z]/));
    };

    /*
    0以上の整数かどうかを検査する
    05は整数ではないのでfalseとなる
    入力がない場合も真と判断するため,必須項目の場合は,isNull()と併用すること
       
    戻り値:
    0以上の整数の場合にtrue,そうでない場合にfalse
    */
    $.fn.isPositiveNumber = function () {
        var value = this.val();
        if (value.length == 0)
            return true;

        if (!value.match(/^\d+$/))
            return false;

        if (value.length <= 1)
            return true;

        return (value.charAt(0) != "0");
    };


    /*
    整数かどうかを検査する
    05は整数ではないのでfalseとなる
    入力がない場合も真と判断するため,必須項目の場合は,isNull()と併用すること
       
    戻り値:
    整数の場合にtrue,そうでない場合にfalse
    */
    $.fn.isNumber = function () {
        var value = this.val();
        if (value.length == 0)
            return true;

        if (!value.match(/^[-]?[0-9]+(\.[0-9]+)?$/))
            return false;

        if (value.length <= 1)
            return true;

        return (value.charAt(0) != "0");
    }
    /*
    正しい日付と判断できるかどうかを検査する
    有効な書式は,区切り文字に「-」または「/」を使用した場合,または
    年4桁・月2桁・日2桁の8桁の数字を使用し,
    日付として有効な組み合わせであること
       
    例:
    2014/1/1
    2014/1-1
    20140228
      
    戻り値:
    有効な日付の場合にtrue,そうでない場合にfalse	
    */
    $.fn.isDate = function () {
        return this.getDate() != null;
    };

    /*
    日付に対応するDate型のオブジェクトを返す
    有効な日付の書式は,isDate()のコメントを参照せよ
       
    戻り値:
    有効な日付の場合にDate型のオブジェクトを,そうでない場合null
    */
    $.fn.getDate = function () {
        var value = this.val();
        if (value.length == 0)
            return null;

        var a = new Array();
        var date = value.replace("-", "/");
        if (date.match(/^\d{2,4}\/\d{1,2}\/\d{1,2}$/))
            a = date.split("/");
        else if (date.match(/^\d\d\d\d\d\d\d\d$/)) {
            a[0] = date.substring(0, 4);
            a[1] = date.substring(4, 6);
            a[2] = date.substring(6, 8);
        }
        else
            return null;

        var nd = new Date(a[0], a[1] - 1, a[2]);
        if (a[0] == nd.getFullYear() && a[1] == nd.getMonth() + 1 && a[2] == nd.getDate())
            return nd;

        return null;
    };
})(jQuery);