ColdFusion の HTML フォームやコントロールには、Ajax ベースの機能が実装されています。
- cfgrid、cfinput、cfselect、cftextarea および cftree コントロールではバインディングがサポートされており、コントロールの内容を取得できます。
- ColdFusion 関数では、フォームの非同期送信がサポートされています。この機能を使用すれば、ページ全体を更新せずに済みます。Ajax コンテナコントロールの中にあるフォームは、自動的に非同期で送信されます。また、JavaScript の ColdFusion.Ajax.SubmitForm 関数と Ajax プロキシの setForm 関数を使用すれば、手動で非同期送信を行えます。
- cfgrid および cftree タグを使用すれば、HTML のグリッドとツリーを作成できるので、Java アプレットや Flash を使用する必要はありません。
- cftextarea コントロールでは、リッチテキストエディターのオプションを使用できます。このテキストエディターは設定可能です。
- cfinput タグでは datefield というタイプがサポートされており、Ajax ベースのポップアップカレンダーから日付を選択することができます。
- cfinput タグの text タイプでは autosuggest 属性がサポートされており、ユーザーが入力したテキストに基づいてドロップダウンリストに入力候補を表示することができます。
- cfinput、cfselect および cftextarea タグでは tooltip 属性がサポートされており、ユーザーがコントロールの上にマウスのカーソルを合わせたときに表示するツールヒントを指定できます。cftooltip タグを使用すれば、フォームコントロールだけでなく、ページの任意の部分でツールヒントを表示できます。
Ajax フォームコントロールの使用
ColdFusion の Ajax ベースのフォームコントロールを使用すれば、ページ全体を更新せずに Ajax フォームを送信できます。
Ajax を使用してフォームをページから非同期で送信する場合は、cfinput または input タグを使用してファイルをアップロードすることはできません。
Ajax コンテナによるフォーム送信
ColdFusion の Ajax コンテナタグである cfdiv、cflayoutarea、cfpod、cfwindow タグでは、その中に含まれているフォームは自動的に非同期で送信されます。フォームが送信されると、アクションページから結果が返されて、コンテナの内容が更新されますが、ページのそれ以外の領域は変化しません。
この処理を行う submitSimple.cfm ページの例を次に示します。
<html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> <cflayout type="vbox" name="layout1"> <cflayoutarea> <h3>This area is not refreshed when the form is submitted.</h3> <br /> </cflayoutarea> <cflayoutarea> <h3>This form is replaced by the action page</h3> <cfform name="myform" format="html" action="showName.cfm"> <cfinput type = "Text" name = "name"> <cfinput type = "submit" name = "submit" value = "Enter name"> </cfform> </cflayoutarea> </cflayout> </body> </html>
次の例では、テキスト入力に名前を入力して「名前を入力」ボタンをクリックすると、入力したテキストがページのフォームに表示されますが、それ以外の部分は更新されません。showName.cfm アクションページは次のようになります。
<cfoutput>The Name is : <strong>#Form.name#</strong></cfoutput> </cfif>
cfajaxproxy の SetForm 関数の使用
cfajaxproxy タグによって作成されるプロキシオブジェクトには、SetForm という関数が用意されています。SetForm 関数を呼び出すと、その次に呼び出す CFC 関数に、フォームの値が引数として渡されます。この方法を使用すれば、特定の CFC 関数にフォームの現在のフィールド値を渡して必要な処理を行い、結果を返すことができます。
SetForm 関数を使用する場合、CFC 関数に渡される引数には次のルールが適用されます。
- cfargument タグでフォームフィールドを指定しなくても、フィールド名を介してフィールド値を取得できます。
- フォームフィールドと同じ名前の CFC 引数がある場合、その引数はフォームフィールド値によって上書きされます。
- cfargument タグでフォームフィールドを指定しなかった場合、arguments 構造体で位置引数の表記法(配列表記法)を使用するときは注意が必要です。明示的に宣言された引数の後にフォームフィールドがあるとは限りません。
- CFC 関数の arguments スコープには、ColdFusion がその動作を制御するために使用する 2 つのフィールドが含まれています。それらは内部的に使用されるフィールドであり、その名前は今後のリリースで変更される可能性があります。現在の名前は次のとおりです。どちらも true に設定されています。
- _CF_NODEBUG。true の場合、ColdFusion は呼び出しの応答でデバッグ出力を返しません。
- _CF_NOCACHE。true の場合、ColdFusion は応答でノーキャッシュヘッダーを送信します。これによって、ブラウザーに応答がキャッシュされなくなるので、Ajax リクエストのたびに必ずネットワークコールが実行されるようになります。
次の例で、SetForm 関数を使用してログインフォームの内容を送信する方法を示します。ユーザーが「Login!」ボタンをクリックすると、doLogin 関数からプロキシの setForm 関数、その後に AuthenticationSystem.cfcvalidateCredentials メソッドが呼び出されます。validateCredentials メソッドはユーザーのパスワードを照合し、有効である場合はプロキシに true を返します。doLogin メソッドは戻り値を取得し、値が true であればログインウィンドウを閉じます。プロキシは同期式(デフォルト)で動作するので、これらの処理が完了するまでユーザーはページの内容にアクセスできません。戻り値が false の場合は、ログインウィンドウのタイトルバーにメッセージを表示します。
setForm.cfm アプリケーションは次のようになります。
<head>
<script type="text/javascript">
function doLogin() {
// Create the Ajax proxy instance.
var auth = new AuthenticationSystem();
// setForm() implicitly passes the form fields to the CFC function.
auth.setForm("loginForm");
//Call the CFC validateCredentials function.
if (auth.validateCredentials()) {
ColdFusion.Window.hide("loginWindow");
} else {
var msg = document.getElementById("loginWindow_title");
msg.innerHTML = "Incorrect username/password. Please try again!";
}
}
</script>
</head>
<body>
<cfajaxproxy cfc="AuthenticationSystem" />
<cfif structKeyExists(URL,"logout") and URL.logout>
<cflogout />
</cfif>
<cflogin>
<cfwindow name="loginWindow" center="true" closable="false"
draggable="false" modal="true"
title="Please login to use this system"
initshow="true" width="400" height="200">
<!--- Notice that the form does not have a submit button.
Submit action is performed by the doLogin function. --->
<cfform name="loginForm" format="xml">
<cfinput type="text" name="username" label="username" /><br />
<cfinput type="password" name="password" label="password" />
<cfinput type="button" name="login" value="Login!" onclick="doLogin();" />
</cfform>
</cfwindow>
</cflogin>
<p>
This page is secured by login.
You can see the window containing the login form.
The window is modal; so the page cannot be accessed until you log in.
<ul>
<li><a href="setForm.cfm">Continue using the application</a>!</li>
<li><a href="setForm.cfm?logout=true">Logout</a>!</li>
</ul>
</p>
</body>
</html>
"AuthenticationSystem.cfc" ファイルを次の例に示します。
<cffunction name="validateCredentials" access="remote" returntype="boolean" output="false"> <cfargument name="username" type="string"/> <cfargument name="password" type="string"/> <cfset var validated = false/> <!--- Ensure that attempts to authenticate start with new credentials. ---> <cflogout/> <cflogin> <cfif arguments.username is "user" and arguments.password is "secret"> <cfloginuser name="#arguments.username#" password="#arguments.password#" roles="admin"/> <cfset validated = true/> </cfif> </cflogin> <cfreturn validated/> </cffunction> </cfcomponent>
ColdFusion.Ajax.submitForm 関数の使用
ColdFusion.Ajax.submitForm 関数を使用すると、フォームの内容を CFML ページなどのアクティブページにいつでも送信できます。たとえば、この関数を使用して、入力が完了していないフォームを自動的に保存できます。この関数はフォームへの添付ファイルのアップロードをサポートしていません。
この関数を使用するときは、送信するフォームの名前と、フォームを処理するページの URL を関数に渡します。また、次のオプションのパラメータも指定できます。
- 返される結果を処理するコールバック関数
- エラーハンドラ(HTTP エラーコードとエラーメッセージの 2 つのパラメーターを取ります)
- HTTP メソッド(デフォルトでは POST)
- フォームを非同期で送信するかどうか(デフォルトでは true)
次の例では、ColdFusion.Ajax.submitForm 関数を使用して、2 つのフォームフィールドを asyncFormHandler.cfm ページに送信します。このページは、フォームの値をそのまま表示します。コールバックハンドラを使用してウィンドウを開き、返された情報を表示します。
<head>
<!--- The cfajaximport tag is required for the submitForm function to work
because the page does not have any Ajax-based tags. --->
<cfajaximport>
<script>
function submitForm() {
ColdFusion.Ajax.submitForm('myform', 'asyncFormHandler.cfm', callback,
errorHandler);
}
function callback(text)
{
alert("Callback: " + text);
}
function errorHandler(code, msg)
{
alert("Error!!! " + code + ": " + msg);
}
</script>
</head>
<body>
<cfform name="myform">
<cfinput name="mytext1"><br />
<cfinput name="mytext2">
</cfform>
<a href="javascript:submitForm()">Submit form</a>
</body>
</html>
"asynchFormHandler.cfm" ページの内容は次の 1 行です。
<cfoutput>Echo: #form.mytext1# #form.mytext2#</cfoutput>
ColdFusion.navigate 関数によるフォーム送信
JavaScript の ColdFusion.navigate 関数を使用すると、URL にフォームを送信し、返された結果を特定のコンテナコントロール(cfdiv、cflayout、cfpod、cfwindow タグなど)に表示できます。ユーザーがデータを送信したフォームが含まれているコントロール以外のコントロールに結果を表示できます。また、この関数を使用すると、ユーザーがフォームの外部で何らかのアクションを行ったとき (たとえばメニューアイテムをクリックしたとき) に、フォームを非同期で送信できます。
この関数の使用例については、『CFML リファレンス』で ColdFusion.navigate 関数を参照してください。
HTML グリッドの使用
ColdFusion には HTML の cfgrid コントロールが用意されており、バインド式を使用してダイナミックにデータを設定できます。バインド式を使用する HTML のグリッドは、ページ形式で生成されます。ユーザーがグリッドのページを切り替えると、移動先のページに必要な分のデータがデータソースから取得されてグリッドに表示されます。ユーザーがフォームの内容を編集するときにもバインド式を使用できます。また、その他の ColdFusion コントロールもグリッドにバインドできます。HTML のグリッドには、グリッドの管理や操作を行うための JavaScript 関数が用意されています。
また、スタティックな HTML のグリッドも作成できます。それには、バインド式を指定せずに cfgrid タグを使用します。スタティックなグリッドでは、すべてのデータがまとめて表示されます。
HTML モードでは、マウスカーソルを列ヘッダー上に置くと、下矢印ボタンが表示されます。このボタンをクリックすると、次のオプションが含まれたリストが表示されます。
- 列の内容に基づいて昇順または降順でグリッドをソートする。
- 表示する列を選択する。
- グリッドに groupfield 属性がある場合:グループ化の無効と有効を切り替えて列の値でグループ化する。
HTML グリッドで selectMode="edit" を指定すると、グリッドの下部にあるバーに、「挿入」、「保存」、「キャンセル」、「削除」の各ボタンが表示されます。「挿入」ボタンは、編集可能な新しい行を開きます。「保存」ボタンは、バインドソースに変更をコミットします。[キャンセル] ボタンは、保存されていない変更をロールバックします。[削除] ボタンは、選択されている行を削除します。[削除] ボタンをクリックした後に [保存] ボタンをクリックする必要はありません。
フォームデータのダイナミックな設定
HTML グリッドでは、bind 属性にバインド式を指定することで、グリッドデータをダイナミックに設定できます。バインド式では、CFC 関数、JavaScript 関数または URL を呼び出します。また、バインドパラメーターを指定して、グリッドにダイナミックに表示する情報や、他のフォームフィールドの属性値を指定することができます。
バインド式には、次のバインドパラメーターを渡します。関数呼び出しまたは URL のパラメータを 1 つでも省略すると、エラーが発生します。これらのパラメータを渡すことにより、グリッドやその状態に関する情報がデータ生成関数に通知されます。パラメータの実際のデータは自動的に供給されます。手動で値を設定することはできません。
パラメータ名 |
説明 |
|---|---|
cfgridpage |
データを取得するページの番号。 |
cfgridpagesize |
ページに表示するデータの行数。このパラメーターの値は、pageSize 属性の値です。 |
cfgridsortcolumn |
グリッドのソート順序の基準となる列の名前。ユーザーが列のヘッダをクリックするまで、この値は設定されません。 |
cfgridsortdirection |
ソートの方向。ASC(昇順)または DESC(降順)のいずれかです。ユーザーが列のヘッダーをクリックするまで、この値は設定されません。 |
ユーザーまたはアプリケーションによってグリッドのソート(グリッドの列ヘッダーのクリックなど)がまだ実行されていない場合、cfgridsortcolumn および cfgridsortdirection パラメーターは空になります。 |
バインディングとバインドパラメーターについて詳しくは、『CFML リファレンス』の「Ajax データ機能および開発機能の使用」を参照してください。
オプションのパラメーターを使用して、呼び出す関数に追加の情報を渡すことができます。これは、返すデータを決定するために必要なデータを提供する場合に使用します。たとえば、市の名前を返す関数に、都道府県の名前を渡す場合などが考えられます。オプションの関数パラメータは、その一部または全部をバインドパラメータとして指定できます。例えば、都道府県を選択する cfselect コントロールから都道府県名を取得することができます。
他のコントロールが変更されてもグリッドを自動的に更新したくない場合は、すべてのオプションのバインドパラメーターに @none 指定子を使用します。これによって、バインドしているコントロールの値が変更されても、グリッドが自動更新されなくなります。グリッドの内容を明示的に更新するには、JavaScript の ColdFusion.Grid.refresh 関数を使用します。@none 指定子の使用方法と、コントロールを明示的に更新する方法について詳しくは、「フォームフィールドへのデータのバインディング」の「バインドパラメーターの指定」を参照してください。
ユーザーがデータをソートできる場合(sort 属性が true である場合)、バインド式から呼び出された関数では、バインドパラメーターの cfgridsortcolumn と cfgridsortdirection の値を参照してソート方法を確認し、適切にソートしたデータを返す必要があります。ユーザーによるソートを許可していない場合でも、これらのパラメーターを関数に渡す必要があります。渡さないとエラーが発生します。また、これらのパラメーターが空の文字列である場合にも対処できるように、関数またはアクションページを記述する必要があります。グリッドをソートするためにユーザーが列ヘッダーを選択するか、JavaScript の ColdFusion.Grid.sort 関数を呼び出すまで、これらの値は設定されないからです。
返すデータの形式は、データの取得方法によって異なります。
バインドのタイプ |
戻り値 |
|---|---|
CFC |
ColdFusion の構造体。呼び出し元に合わせて自動的に変換されます。または、JSON 形式の構造体を返すこともできます。 |
URL |
JSON 形式の構造体。本文にその他の内容を含めることはできません。 |
JavaScript |
JavaScript オブジェクト。 |
bind 属性に CFC を指定した場合は、queryConvertForGrid 関数を使用してクエリーを構造体に直接変換し、CFC の戻り値として使用することができます。
bind 属性に CFML ページを指定した場合は、queryConvertForGrid 関数を使用してクエリーを構造体に変換し、serializeJSON 関数を使用してその構造体を JSON 形式に変換します。
JavaScript オブジェクトまたはその JSON 形式を手動で作成する場合、その最上位には次の 2 つのキーが必要です。
- TOTALROWCOUNT:返すクエリーデータセットに含まれている行の数。この値は、グリッド内の全ページに含まれているデータ行の数です。現在のページの行数ではありません。
- QUERY:返すクエリーの内容。QUERY の値は、次の 2 つのキーを持つオブジェクトであることが必要です。
- COLUMNS:列名の配列。
- DATA:1 つ目の次元が行、2 つ目の次元がフィールド値に対応した 2 次元配列です。順序は、COLUMNS 配列と同じです。
戻り構造体を CFC で手動で作成する場合は、QUERY の値に ColdFusion のクエリーオブジェクトを使用できます。これは、ColdFusion によってリモートアクセス用の形式に自動的に変換されます。
例えば次のオブジェクトは、cfgrid タグにデータを提供するために JavaScript のバインド関数から返すことができます。
{"TOTALROWCOUNT":6,"QUERY":{"COLUMNS":["EMP_ID","FIRSTNAME",
"EMAIL"],"DATA":[[1,"Carolynn","CPETERSON"],
[2,"Dave","FHEARTSDALE"], [3,"Linda","LSTEWART"],
[4,"Aaron","ASMITH"], [5,"Peter","PBARKEN"],
[6,"Linda","LJENNINGS"],]}};
次の例では、バインド式と CFC を使用して、ページ化されたデータグリッドにダイナミックにデータを設定します。CFML ページのフォームは次のとおりです。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<cfform name="form01">
<cfgrid format="html" name="grid01" pagesize=5 sort=true
bind="cfc:places.getData({cfgridpage},{cfgridpagesize},
{cfgridsortcolumn},{cfgridsortdirection})">
<cfgridcolumn name="Emp_ID" display=true header="eid" />
<cfgridcolumn name="FirstName" display=true header="Name"/>
<cfgridcolumn name="Email" display=true header="Email" />
</cfgrid>
</cfform>
</body>
</html>
"places.cfc" ファイルは次のようになります。関数が呼び出されるたびにすべてのデータセットが取得され、QueryConvertForGrid 関数によってページに必要なデータのみが抽出され返されます。
<cffunction name="getData" access="remote" output="false"> <cfargument name="page"> <cfargument name="pageSize"> <cfargument name="gridsortcolumn"> <cfargument name="gridsortdirection"> <cfquery name="team" datasource="cfdocexamples"> SELECT Emp_ID, FirstName, EMail FROM Employees <cfif gridsortcolumn neq "" or gridsortdirection neq ""> order by #gridsortcolumn# #gridsortdirection# </cfif> </cfquery> <cfreturn QueryConvertForGrid(team, page, pageSize)> </cffunction> </cfcomponent>
次の例は、前の例と同じ処理を行っていますが、メインページで URL バインド式を使用し、データを返すために CFML ページを使用している点が異なります。
メインページのフォームは次のとおりです。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<cfform name="form01">
<cfgrid format="html" name="grid01" pagesize=5 sort=true
bind="url:getdata.cfm?page={cfgridpage}&pageSize={cfgridpagesize}
&sortCol={cfgridsortcolumn}&sortDir={cfgridsortdirection}">
<cfgridcolumn name="Emp_ID" display=true header="eid" />
<cfgridcolumn name="FirstName" display=true header="Name"/>
<cfgridcolumn name="Email" display=true header="Email" />
</cfgrid>
</cfform>
</body>
</html>
"getdata.cfm" ページを次の例に示します。
<cfset queryEnd=""> <cfquery name="team" datasource="cfdocexamples"> SELECT Emp_ID, FirstName, EMail FROM Employees <cfif sortcol neq "" or sortdir neq ""> order by #sortcol# #sortdir# </cfif> </cfquery> <!--- Format the query so that the bind expression can use it. ---> <cfoutput>#serializeJSON(QueryConvertForGrid(team, page, pageSize))# </cfoutput>
データベースに対して SQL クエリーを実行できる場合は、ページに必要なデータのみをクエリーで取得することによって、効率化を図ることができます。QueryConvertForGrid 関数を使用せずに、戻り構造体を手動で作成して 1 ページ分のデータのみを返します。TotalRowCount フィールドには、データセット全体の行数を設定します。返すページに含めるデータの行数ではないので注意してください。
bindOnLoad 属性の使用
通常は、イベントがトリガーされてからコントロールのバインド式が実行されますが、bindOnLoad 属性を使用すると、コントロールがロードされた直後にバインド式が実行されます。これを利用すれば、コントロールに初期値を設定できます。この属性を持つすべての Ajax コントロールでは、この属性がデフォルトで false になっています(ただし、cfdiv および cfgrid は例外で、デフォルトで true になっています)。これらのコントロールで bindOnLoad の値を true に設定すれば、ロード時にコントロールの初期値が設定されます。
bindOnLoad 属性が true であるコントロールが 2 つあり、一方が他方をバインドしている場合は、まず onLoad ページイベントの発生時に両方のコントロールがロードされます。ロードが完了すると、バインドされているコントロールからバインドしているコントロールに変更イベントが送信されるので、バインドしているコントロールが再度ロードされます。開発者としては、どちらのコントロールも 1 回ずつ呼び出して初期値を設定したかったのですが、実際には、バインドされているコントロールがロードを完了すると、バインドしているコントロールが 2 回呼び出されてしまいます。
cfinput、cfselect および cftextarea コントロールの bindOnLoad 属性はデフォルトで false になっているので、bindOnLoad 属性を明示的に設定しない限り、cfgrid または cfdiv タグでこれらのコントロールをバインドしても問題は発生しません。ただし、これらのコントロールの bindOnLoad 属性を true に設定している場合は、これらのコントロールが返すデータのみを取得するように、cfgrid または cfdiv 属性を false に設定します。
グリッドが Spry データセットにバインドされている場合も、二重ロードが発生することがあります。デフォルトでは、ページがロードされるとグリッドおよびデータセットにデータがロードされますが、最初の行にフォーカスが設定されるとデータセットからグリッドに選択変更イベントが送信されるので、グリッドがデータを再度ロードします。bindOnLoad 属性を false に設定すれば、データセットからグリッドに選択の change イベントが送信されたときにのみグリッドにデータがロードされるようになります。
グリッドの内容のダイナミックな編集
バインド式を使用して cfgrid のデータをダイナミックに取得している場合は、ユーザーがフォームを送信しなくても、入力データを使用してデータソースをダイナミックに更新したり、データソースのデータをダイナミックに削除することができます。cfgrid のデータを編集するには、フィールドの内容を選択してから新しい値を入力します。行を削除するには、行のフィールドを選択し、グリッドの一番下にある削除ボタンをクリックします。
バインド式を使用しているグリッドに新しい行を直接挿入することはできません。行を挿入するには、フォームにデータを入力します。フォームを送信するとグリッドが更新されます。
データをダイナミックに更新または削除するには、次の作業を行います。
- cfgrid タグで selectmode="edit" と指定します。これでユーザーがグリッドを編集できるようになります。
- cfgrid タグで onChange 属性を指定します。この属性のバインド式には、データソースを更新する CFC メソッド、JavaScript 関数またはページの URL を指定する必要があります。このバインド式の形式は、以下の「フォームデータのダイナミックな設定」で説明した形式と同じですが、グリッドから自動的に渡される、次のバインドパラメーターを指定する必要があります。これらのパラメーターを渡すことにより、グリッドやその状態に関する情報が onChange 関数に通知されます。
パラメータ名 |
説明 |
|---|---|
cfgridaction |
グリッドで実行するアクション。更新は 'U'、削除は 'D' です。 |
cfgridrow |
構造体または JavaScript オブジェクト。キーは列の名前で、値は更新または削除する行の元の値です。 |
cfgridchanged |
エントリが 1 つの構造体または JavaScript オブジェクト。キーは値を変更する列の名前で、値はフィールドの新しい値です。グリッドのアクションが削除の場合、この構造体は存在しますが空になります。 |
データをダイナミックに更新する場合、onError 属性を使用すれば、エラーが発生して CFC または URL から HTTP エラーステータスが返されたときに実行する JavaScript 関数の名前を指定できます。このメソッドは、HTTP エラーコードと、エラーの内容を説明するテキストメッセージの 2 つのパラメーターを取ります。次の例では、onError ハンドラ関数の使用方法を示します。
<script type="text/javascript">
function errorhandler(id,message) {
alert("Error while updating \n Error code: "+id+" \nMessage:
"+message);}
</script>
次の例では、特定の部署に所属する社員を表示し、ユーザーがフィールドのデータを編集できるようにします。フォーカスが編集対象のフィールドから移動すると、onChange イベントがトリガーされ、CFC の editData 関数が呼び出されてデータソースが更新されます。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function errorhandler(id,message) {
alert("Error while updating\n Error code: "+id+"\n Message: "+message);
}
</script>
</head>
<body>
<cfform name="form01">
<cfgrid format="html" name="grid01" pagesize=11
stripeRows=true stripeRowColor="gray"
bind="cfc:places.getData({cfgridpage},{cfgridpagesize},
{cfgridsortcolumn},{cfgridsortdirection})"
delete="yes" selectmode="edit"
onchange="cfc:places.editData({cfgridaction},{cfgridrow},{cfgridchanged})">
<cfgridcolumn name="Emp_ID" display=true header="Employee ID"/>
<cfgridcolumn name="FirstName" display=true header="Name"/>
<cfgridcolumn name="Email" display=true header="Email"/>
</cfgrid>
</cfform>
</body>
</html>
getData 関数は、以下の「フォームデータのダイナミックな設定」で説明する getData 関数と同じです。CFC の editData 関数は次のようになります。
<cfargument name="gridaction"> <cfargument name="gridrow"> <cfargument name="gridchanged"> <cfif isStruct(gridrow) and isStruct(gridchanged)> <cfif gridaction eq "U"> <cfset colname=structkeylist(gridchanged)> <cfset value=structfind(gridchanged,#colname#)> <cfquery name="team" datasource="cfdocexamples"> update employees set <cfoutput>#colname#</cfoutput> = '<cfoutput>#value#</cfoutput>' where Emp_ID = <cfoutput>#gridrow.Emp_ID#</cfoutput> </cfquery> <cfelse> <cfquery name="team" datasource="cfdocexamples"> delete from employees where emp_id = <cfoutput>#gridrow.Emp_ID# </cfoutput> </cfquery> </cfif> </cfif> </cffunction>
コントロールへのグリッドの内容のバインディング
グリッドフィールドのデータをフォームコントロールにバインドするには、フォームコントロールの bind 属性の値としてバインドパラメーターを指定します。そのシンタックスは次のようになります。
<cfinput name="name" type="text" bind="{gridName.columnName}">
デフォルトでは、グリッドの選択行が変わるたびにバインドパラメータが再評価されて、選択されたグリッドセルの該当する列の値がコントロールに反映されます。
JavaScript のグリッド関数
次の JavaScript 関数を使用して、HTML 形式のグリッドを管理できます。
関数 |
説明 |
|---|---|
ColdFusion.Grid.getGridObject |
Ext JS JavaScript ライブラリオブジェクトを取得します。 |
ColdFusion.Grid.refresh |
グリッドの表示を手動で更新します。 |
ColdFusion.Grid.sort |
グリッドをソートします。 |
詳しくは、『CFML リファレンス』で ColdFusion.Grid.getGridObject、ColdFusion.Grid.refresh および ColdFusion.Grid.sort の各関数を参照してください。
ブール型の列の使用とグループ化
次の例では、ブール型の列の使用方法を示します。このコードは、選択したグリッド列でグリッドのデータをグループ化する方法も示しています。
この例では、すべてのタイプのブール型表現を使用しています。グループ化のために、groupField が active に設定されているので、それに従ってグリッドデータがグループ化されます。
<cfset queryaddrow(emps,10)> <cfset querysetcell(emps,"firstname","Debra",1)> <cfset querysetcell(emps,"department","Accounting",1)> <cfset querysetcell(emps,"salary","100000",1)> <cfset querysetcell(emps,"active","Y",1)> <cfset querysetcell(emps,"firstname","Doherty",2)> <cfset querysetcell(emps,"department","Finance",2)> <cfset querysetcell(emps,"salary","120000",2)> <cfset querysetcell(emps,"active","Yes",2)> <cfset querysetcell(emps,"firstname","Ben",3)> <cfset querysetcell(emps,"department","Law",3)> <cfset querysetcell(emps,"salary","200000",3)> <cfset querysetcell(emps,"active","true",3)> <cfset querysetcell(emps,"firstname","Aaron",4)> <cfset querysetcell(emps,"department","Accounting",4)> <cfset querysetcell(emps,"salary","200000",4)> <cfset querysetcell(emps,"active","1",4)> <cfset querysetcell(emps,"firstname","Josh",5)> <cfset querysetcell(emps,"department","CF",5)> <cfset querysetcell(emps,"salary","400000",5)> <cfset querysetcell(emps,"active",true,5)> <cfset querysetcell(emps,"firstname","Peterson",6)> <cfset querysetcell(emps,"department","Accounting",6)> <cfset querysetcell(emps,"salary","150000",6)> <cfset querysetcell(emps,"active","0",6)> <cfset querysetcell(emps,"firstname","Damon",7)> <cfset querysetcell(emps,"department","Finance",7)> <cfset querysetcell(emps,"salary","100000",7)> <cfset querysetcell(emps,"active","N",7)> <cfset querysetcell(emps,"firstname","Tom",8)> <cfset querysetcell(emps,"department","CF",8)> <cfset querysetcell(emps,"salary","100000",8)> <cfset querysetcell(emps,"active","false",8)> <cfset querysetcell(emps,"firstname","Adam",9)> <cfset querysetcell(emps,"department","CF",9)> <cfset querysetcell(emps,"salary","300000",9)> <cfset querysetcell(emps,"active",false,9)> <cfset querysetcell(emps,"firstname","Sean",10)> <cfset querysetcell(emps,"department","CF",10)> <cfset querysetcell(emps,"salary","250000",10)> <cfset querysetcell(emps,"active","No",10)> <cfform name="form01"> <cfgrid format="html" insert="yes" insertButton="Add Row" name="grid01" selectmode="edit" width=600 collapsible="true" title="Employees" autowidth="yes" query="emps" sort="yes" groupField="active"> <cfgridcolumn name="FirstName" header="FirstName"/> <cfgridcolumn name="Department" header="Department" /> <cfgridcolumn name="Salary" display=true header="Salary" type="numeric" values="1000000,1200000" valuesdisplay="1000000,1200000"/> <cfgridcolumn name="Active" display=true header="Contract" type="boolean" /> </cfgrid> </cfform>
日付列の使用
次の例では、日付列の使用方法を示します。このコードでは、startdate 列の型が date に設定されています。mask には Y/m/d を使用します。Y は 4 桁の年、m は先頭にゼロを付けた月、d は先頭にゼロを付けた日を表します。
<cfset emps = querynew("firstname,department, salary,startdate")>
<cfset queryaddrow(emps,3)>
<cfset querysetcell(emps,"firstname","Debra",1)>
<cfset querysetcell(emps,"department","Accounting",1)>
<cfset querysetcell(emps,"salary","100000",1)>
<cfset querysetcell(emps,"startdate","2009/1/1",1)>
<cfset querysetcell(emps,"firstname","Doherty",2)>
<cfset querysetcell(emps,"department","Finance",2)>
<cfset querysetcell(emps,"salary","120000",2)>
<cfset querysetcell(emps,"startdate","2005/2/21",2)>
<cfset querysetcell(emps,"firstname","Ben",3)>
<cfset querysetcell(emps,"department","Law",3)>
<cfset querysetcell(emps,"salary","200000",3)>
<cfset querysetcell(emps,"startdate","2008/03/03",3)>
<cfform name="form01">
<cfgrid format="html" insert="yes" insertButton="Add Row"
name="grid01"
selectmode="edit"
width=600
collapsible="true"
title="Employees"
autowidth="yes"
query="emps"
sort="yes"
groupField="department">
<cfgridcolumn name="FirstName" header="FirstName"/>
<cfgridcolumn name="Department" header="Department" />
<cfgridcolumn name="Salary" display=true header="Salary" type="numeric" values="1000000,1200000" valuesdisplay="1000000,1200000"/>
<cfgridcolumn name="StartDate" display=true header="StartDate" type="date" mask="Y/m/d"/>
</cfgrid>
</cfform>
使用可能なマスクの種類について詳しくは、『CFML リファレンス』を参照してください。
ColdFusion 9.0.1 での mask 属性を使用したときの日付処理
HTML グリッドの datefield 列に mask 属性を適用すると、日付は、ColdFusion によって
MMMMM, dd yyyy HH:mms
という中間形式に変換されます。例えば、
January, 19 2005 07:35:42
のようになります。これは、日付の正しい変換処理に必要で、データがサーバーに送信されたとき(例えば、onChange グリッドイベントを使用したとき)と、データがサーバーから受信されたとき(例えば、グリッドの日付フィールドにデータを挿入したとき)の両方のタイミングで適用されます。そのため、場合によっては、データベースの日付列を更新するときに、ユーザーによる日付の形式編集が必要になる場合があります。
NULL の日付値は、フォームの送信時に空の文字列で送信されます。このような場合は、データベースの日付列を更新するときに、明示的に値に NULL を設定します。
HTML のツリーの使用
HTML の cftree タグを使用して、Ajax ベースのツリーデータ表現を作成できます。ツリーデータは、クエリーまたはバインド式を使用して取得できます。クエリーを使用する場合の動作は、アプレットや Flash のツリーの場合と同じです。バインド式を使用する場合は、他のコントロールや Spry データセットの値に基づいてツリーを作成できます。ツリーはダイナミックにロードされ、現在の表示に必要なデータのみが取得されます。
バインド式によるツリーの作成
bind 属性とバインド式を使用すると、ユーザーのツリー操作に合わせて、ツリーデータのロードと表示をダイナミックに行えます。子のツリー項目のデータは親ノードが展開されるまでロードされません。この動作を利用すると、大量のデータをあらかじめツリーに渡す必要がなくなります。また、(項目が展開されるたびに子を取得するように設定することもでき) ツリーの子をダイナミックに変更できるので、アプリケーションの応答性が向上します。
バインディングとバインドパラメーターについて詳しくは、「フォームフィールドへのデータのバインディング」を参照してください。
ツリーにおけるバインド式は次のように動作します。
- バインド式を使用する場合、cftree タグで使用できる cftreeitem タグは 1 つのみです。したがって、バインド式から呼び出される関数または URL では、ツリーのすべてのレベルにデータを設定できることが必要です。
- ツリー項目を展開すると、bind 属性で指定されている CFC 関数、JavaScript 関数またはアクティブページから、その項目の子ノードの値を含む配列が返されます。クライアントのダイナミックツリーコードでは、それらの値を使用して子項目が構築されます。
- ツリーがバインドしているコントロールで、ツリーがリスンしているイベントが発生すると、ツリーが更新されます。たとえば、ツリーのバインド式でバインドパラメータに選択ボックスを指定している場合は、選択ボックスの選択値が変わると、ルートノードまでツリーが折り畳まれます。
バインド式を使用して cftree コントロールにデータを設定する場合は、CFC 関数、JavaScript 関数または URL を指定し、その関数または URL に、次のバインドパラメーターをすべて渡します。渡していないバインドパラメーターが 1 つでもあると、エラーが発生します。これらのパラメーターを渡すことにより、ツリーやその状態に関する情報がコントロールに自動的に通知されます。
バインドパラメータ |
説明 |
|---|---|
{cftreeitempath} |
現在のノード(親ノード)のパスをメソッドに渡します。メソッドはこれに基づいて次のノードを生成します。 |
{cftreeitemvalue} |
現在のツリー項目の値(通常は value 属性)を渡します。 |
呼び出された関数または URL が返せるのは単一のレベルに属する項目だけで、ネストされた配列や構造体は返せません。
ルートレベルのツリー項目を生成するために最初に関数または URL が呼び出されるときは、cftreeitemvalue 変数に空の文字列が渡されます。バインド関数では、渡された値が空の文字列かどうかを確認し、空の文字列であればルートレベルのツリーを生成します。
JavaScript の ColdFusion.Tree.refresh 関数を使用してツリーを手動で更新する場合は、@none イベント指定子も役に立ちます。Refresh 関数を呼び出すと、@none が指定されているパラメーターを含むすべてのバインドパラメーターからデータが取得されます。他のコントロールを指定するすべてのバインドパラメーターに @none を指定すると、そのコントロールに変更があってもツリーは自動的に更新されなくなります。ツリーを明示的に更新する ColdFusion.Tree.Referesh 関数を使用すれば、バインドパラメーターからデータが取得されます。
バインド式の関数または URL が返すデータの形式は、バインド式の種類によって異なります。
バインドのタイプ |
戻り値 |
|---|---|
CFC |
ColdFusion の構造体の配列。構造体は、ColdFusion が呼び出し元に結果を返すときに自動的に JSON 形式に変換されます。または、JSON 形式の構造体を返すこともできます。 |
JavaScript |
JavaScript のオブジェクトの配列。 |
URL |
JSON 形式の構造体の配列。本文にその他の内容を含めることはできません。 |
配列内の各構造体では、子項目のノードの内容と外観が定義されます。どの構造体にも必ず VALUE フィールドが存在しますが、この他にそれぞれの構造体に応じて次のフィールドが存在します。LEAFNODE を除き、これらの構造体のキーは cftreeitem の属性に対応します。
- DISPLAY
- EXPAND
- HREF
- IMG
- IMGOPEN
- LEAFNODE
- TARGET
CFC が有効なフィールドを返さない場合、エラーが発生しませんが、ツリーは正常に動作しません。
LEAFNODE 構造体要素は、バインド応答構造体でのみ使用されます。これはブール値で、リーフノードであるかどうかを表します。この値が true の場合、ノードの横に +/- アイコンが表示されないので、ユーザーはノードを展開することができません。
バインド式で JavaScript 関数を指定する場合、その関数で使用するフィールド名はすべて大文字にする必要があります。例えば、VALUE と DISPLAY は使用できますが、value と display は使用できません。ColdFusion では構造体のキー名で大文字のみを使用します。ColdFusion では大文字と小文字が区別されないので、CFC のフィールド名では小文字を使用できますが、JavaScript では大文字と小文字が区別されるので、JavaScript 関数のフィールド名では大文字を適切に使用する必要があります。
URL を使用して CFML ページからツリー項目を取得する場合は、serializeJSON 関数を使用すれば、配列を JSON 形式に変換できます。たとえば、ツリー項目を格納した配列の名前が itemsArray の場合、ページ出力を指定する行は次のようになります。
<cfoutput>#serializeJSON(itemsArray)#</cfoutput>
例 1 : 単純なツリー
次の例では、レベル数に制限のない、レベルごとに 1 つのノードがある単純な階層ツリーを作成します。display 属性で指定する各ノードのラベルは、ノードのレベルを表します。
CFML ページを次の例に示します。
<cftree name="t1" format="html">
<cftreeitem bind="cfc:makeTree.getNodes({cftreeitemvalue},{cftreeitempath})">
</cftree>
</cfform>
ユーザーがノードを展開したときに呼び出される getNodes メソッドを持つ maketree.cfc ファイルを次の例に示します。
<cffunction name="getNodes" returnType="array" output="no" access="remote"> <cfargument name="nodeitemid" required="true"> <cfargument name="nodeitempath" required="true"> <!--- The initial value of the top level is the empty string. ---> <cfif nodeitemid IS ""> <cfset nodeitemid =0> </cfif> <!--- Create an array with one element defining the child node. ---> <cfset nodeArray = ArrayNew(1)> <cfset element1 = StructNew()> <cfset element1.value = nodeitemid + 1> <cfset element1.display = "Node #nodeitemid#"> <cfset nodeArray[1] = element1> <cfreturn nodeArray> </cffunction> </cfcomponent>
リーフノードの処理
ツリーのリーフノードに関する情報を返すコードでは、構造体の LEAFNODE フィールドを true に設定してください。これによって、リーフノードのツリーエントリに + のアイコンが表示されないので、そのノードを展開できないことをユーザーが認識できます。LEAFNODE フィールドの使用例を次に示します。
例 2 : リーフノードを処理する複雑なツリー
次のツリーの例では、cfartgallery データベースを使用して、最上位レベルに分野、2 番目のレベルにアーティスト、リーフノードに作品を生成します。ユーザーが作品をクリックすると、その作品のイメージが表示されます。
この例では、ツリーのレベルごとの戻り値や親の値の生成方法を示します。また、戻り構造体の LEAFNODE 要素の使用方法も示します。
このアプリケーションでは、CFC 戻り構造体のキーを小文字にしていますが、自動的に大文字に変換されます。データベースに収録されている分野は絵画、彫刻、写真であるので、これらの分野を表示する最上位レベルのツリーノードにのみ子ノードが表示されます。
アプリケーションのメインページは次のようになります。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!--- The loadimage function displays the image of the selected art.
It is called when the user clicks the image item. --->
<script>
function loadImage(img) {
var imgURL = '<img src="/cfdocs/images/artgallery/'+img+'">';
var imgDiv = document.getElementById('image');
imgDiv.innerHTML = imgURL;
}
</script>
</head>
<body>
<!--- The form uses a table to place the tree and the image. --->
<cfform name="ex1" action="ex1.cfm" method="post">
<table>
<tr valign="top">
<td>
<cftree name="mytree" format="html">
<!--- When you use a bind expression, you must have only one
cftreeitem, which populates the tree level. --->
<cftreeitem bind="cfc:tree.getItems({cftreeitempath},
{cftreeitemvalue})">
</cftree>
</td>
<td>
<div id="image"></div>
</td>
</tr>
</table>
</cfform>
</body>
</html>
"tree.cfc" ファイルを次の例に示します。
<cfset variables.dsn = "cfartgallery">
<!--- Function to populate the current level of the tree. --->
<cffunction name="getItems" returnType="array" output="false" access="remote">
<cfargument name="path" type="string" required="false" default="">
<cfargument name="value" type="string" required="false" default="">
<cfset var result = arrayNew(1)>
<cfset var q = "">
<cfset var s = "">
<!--- The cfif statements determine the tree level. --->
<!--- If there is no value argument, the tree is empty. Get the media types. --->
<cfif arguments.value is "">
<cfquery name="q" datasource="#variables.dsn#">
SELECT mediaid, mediatype
FROM media
</cfquery>
<cfloop query="q">
<cfset s = structNew()>
<cfset s.value = mediaid>
<cfset s.display = mediatype>
<cfset arrayAppend(result, s)>
</cfloop>
<!--- If the value argument has one list entry, it is a media type. Get the artists for
the media type.--->
<cfelseif listLen(arguments.value) is 1>
<cfquery name="q" datasource="#variables.dsn#">
SELECT artists.lastname, artists.firstname, artists.artistid
FROM art, artists
WHERE art.mediaid = <cfqueryparam cfsqltype="cf_sql_integer"
value="#arguments.value#">
AND art.artistid = artists.artistid
GROUP BY artists.artistid, artists.lastname, artists.firstname
</cfquery>
<cfloop query="q">
<cfset s = structNew()>
<cfset s.value = arguments.value & "," & artistid>
<cfset s.display = firstName & " " & lastname>
<cfset arrayAppend(result, s)>
</cfloop>
<!--- We only get here when populating an artist's works. --->
<cfelse>
<cfquery name="q" datasource="#variables.dsn#">
SELECT art.artid, art.artname, art.price, art.description,
art.largeimage, artists.lastname, artists.firstname
FROM art, artists
WHERE art.mediaid = <cfqueryparam cfsqltype="cf_sql_integer"
value="#listFirst(arguments.value)#">
AND art.artistid = artists.artistid
AND artists.artistid = <cfqueryparam cfsqltype="cf_sql_integer"
value="#listLast(arguments.value)#">
</cfquery>
<cfloop query="q">
<cfset s = structNew()>
<cfset s.value = arguments.value & "," & artid>
<cfset s.display = artname & " (" & dollarFormat(price) & ")">
<cfset s.href = "javaScript:loadImage('#largeimage#');">
<cfset s.children=arrayNew(1)>
<!--- leafnode=true prevents node expansion and further calls to the
bind expression. --->
<cfset s.leafnode=true>
<cfset arrayAppend(result, s)>
</cfloop>
</cfif>
<cfreturn result>
</cffunction>
</cfcomponent>
ツリーへの他のコントロールのバインディング
JavaScript のツリー関数
次の JavaScript 関数を使用して、HTML ツリーを管理できます。
関数 |
説明 |
|---|---|
ColdFusion.Tree.getTreeObject |
Yahoo User Interface Library の TreeView JavaScript オブジェクトを取得します。 |
ColdFusion.Tree.refresh |
ツリーを手動で更新します。 |
詳しくは、『CFML リファレンス』で ColdFusion.Tree.getTreeObject 関数および ColdFusion.Tree.refresh 関数を参照してください。
リッチテキストエディターの使用
ColdFusion のリッチテキストエディターを使用すると、オープンソースの CKeditor Ajax ウィジェットをベースにしたアイコン形式のインターフェイスを操作しながら、リッチテキスト(HTML)形式のテキストの入力と形式設定を行えます。このエディターには様々な形式設定用のコントロールと、テキストの検索、印刷、プレビューなどの標準的な操作用のアイコンが装備されています。ただし、ここではテキストエディターのコントロールについては説明しません。
リッチテキストエディターのアイコンおよびコントロールについて詳しくは、http://docs.ckeditor.com/#!/guide/dev_installation を参照してください。
ページをロードするときに(テキストボックスのような別のコントロールなどから)リッチテキスト領域にバインドしないように注意してください。
簡単なリッチテキストエディタの例を次に示します。この例では、ユーザーがテキストを入力し [Enter] ボタンをクリックすると、画面が更新されて、エディタ領域の上部に形式設定後のテキストが表示されます。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<!--- Display the text if the form has been submitted with text. --->
<cfif isdefined("form.text01") AND (form.text01 NEQ "")>
<cfoutput>#form.text01#</cfoutput><br />
</cfif>
<!--- A form with a basic rich text editor and a submit button. --->
<cfform name="form01" >
<cftextarea richtext=true name="text01" />
<cfinput type="submit" value="Enter" name="submit01"/>
</cfform>
</body>
</html>
ページでリッチテキストエディタを使用する場合、拡張子が .html または .htm のファイルを ColdFusion で処理するように Web サーバーを設定することはできません。これらの拡張子を持つページはデフォルトの HTML プロセッサで処理する必要があります。
リッチテキストエディタの設定
リッチテキストエディターでは様々なカスタマイズが行えます。cftextarea 属性では、いくつかの基本的なカスタマイズ機能がサポートされています。詳しくは、http://docs.ckeditor.com/ を参照してください。
カスタムツールバーの定義
ツールバーの外観を制御するには、次の方法があります。
config.toolbar_<Your Custom Toolbar Name> でツールバー定義を開始します(引用符は使用せず、1 つの単語からなる名前のみを使用します)。 cftextarea タグツールバー属性で、この名前を使用します(大文字と小文字を区別します)。
- 上記の後に等号(=)を続けます。
- 一連の角括弧([ ])の中にツールバーコントロールを指定し、定義の最後にセミコロン(;)を付けます。
- 中括弧によってコントロールがグループ化されます。
- 各項目は一重引用符(')で囲み、カンマ(,)で区切って指定します。
- 区切り線を指定するときは、ハイフン(-)を使用します。
- 改行するときはスラッシュ(/)を使用します。
有効なツールバー項目のすべてのリストについては、config.js の Default 設定を参照してください。
詳しくは、http://docs.ckeditor.com/#!/guide/dev_toolbarconcepts-section-%22item-by-item%22-configuration を参照してください。
config.toolbar = 'Custom';
config.toolbar_Custom =
[
{ name: 'document', items : [ 'NewPage','Preview' ] },
{ name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] },
{ name: 'editing', items : [ 'Find','Replace','-','SelectAll','-','Scayt' ] },
{ name: 'insert', items : [ 'Image','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'
,'Iframe' ] },
'/',
{ name: 'styles', items : [ 'Styles','Format' ] },
{ name: 'basicstyles', items : [ 'Bold','Italic','Strike','-','RemoveFormat' ] },
{ name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote' ] },
{ name: 'links', items : [ 'Link','Unlink','Anchor' ] },
{ name: 'tools', items : [ 'Maximize','-','About' ] }
];
出力
基本ツールバー
カスタムツールバー
カスタムスタイルの定義
CKEDITOR.stylesSet.add( 'my_styles', [
// Block-level styles.
{ name: 'Blue Title', element: 'h2', styles: { color: 'Blue' } },
{ name: 'Red Title', element: 'h3', styles: { color: 'Red' } },
// Inline styles.
{ name: 'CSS Style', element: 'span', attributes: { 'class': 'my_style' } },
{ name: 'Marker: Yellow', element: 'span', styles: { 'background-color': 'Yellow' } }
]);
出力
デフォルトのスタイル
カスタムのスタイル
スタイルの設定について詳しくは、このドキュメントを参照してください。
cftextarea の basepath 属性の使用
- http://ckeditor.com/download から CKEditor ライブラリをダウンロードします。ライブラリには、ckeditor.js が含まれています。
- Web ルートまたはサブフォルダーにフォルダーをコピーします。
- basepath の値を webroot に設定します。先頭は「/」とします。
- ページで CKEDITOR のインスタンスを複数使用する場合は、最初の textarea (richtext="true")の basepath の値が、ページ上のすべてのエディターのインスタンスで使用されます。最初の リッチテキスト textarea でこの属性が設定されていない場合は、指定されているデフォルトの CKEDITOR が使用されます。
カスタムスキンの定義
カスタムスタイルの作成について詳しくは、このドキュメントを参照してください。新しいスキンを設定するには、次のようにします。
- CKEditor インストールの skins フォルダー内のフォルダーにあるソースファイルをコピーします。
- フォルダーに、新しいスキンの名前を付けます(小文字で、スペースは入れません)。
- このスキンをスキン属性 cftextarea で使用します。
ファイルマネージャーの使用
CKeditor は、ファイルマネージャーをプラグインとして使用します。これは、 組み込みの コンポーネントとして使用されていた FCKeditor とは異なります。
settings.cfm ファイル( ckeditor フォルダー内)には、アップロードディレクトリの設定、サーバーへのアップロードの許可、許可されるファイルタイプなど、ファイルマネージャーの設定が含まれています。
デフォルトのアップロードディレクトリは /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/uploadedFiles です。
ディレクトリのアップロードおよび作成の権限の設定
settings. cfm (cf_scripts/scripts/ajax/ckeditor/)で以下の変数を true に設定します。
- settings.AllowUploads
- settings.AllowDirectoryCreation
日付フィールドの入力コントロールの使用
タイプの値が datefield である HTML の cfinput コントロールでは、ポップアップカレンダーから日付を選択したり、入力ボックスに直接日付を入力したりできます。このコントロールを使用する場合は、次の点に注意してください。
- Internet Explorer と Firefox で、コントロールの横にラベルテキストが正しく表示されるようにするには、ラベルテキストを <div style="float:left;"> タグで囲み、各行の間に <br> を 3 つ指定します。
- cflayoutarea タグの overflow 属性の値を visible にすれば、ポップアップカレンダーがレイアウト領域の枠からはみ出ても、完全に表示されます。
- mask 属性を使用して日付形式を指定しても、ユーザーはその形式以外の日付も入力することができます。mask 属性は、ユーザーがポップアップカレンダーで日付を選択したときに使用する形式を指定するものです。また、ユーザーがフィールドに日付を入力してからポップアップカレンダーを開いた場合、カレンダーにその日付が表示されるのは、入力した日付がマスクパターンに従っている場合のみです。mask 属性を指定していない場合、ポップアップカレンダーではデフォルトの一致パターンが使用されます。
- ユーザーがポップアップカレンダーを使用せず、月の名前または月の略称を使用してコントロールに日付を入力した場合、ポップアップカレンダーにその日付が表示されるのは、次の条件が両方とも満たされている場合のみです。
- 月の入力位置と名前の形式が、マスクパターンと一致している。
- 月の名前が、大文字と小文字の区別も含めて、monthNames 属性で指定した月の名前(mmm マスクの場合は 3 文字の略称)に一致している。
- 年の日付マスクとして yy を指定した場合、ポップアップカレンダーでは 1951 年~ 2050 年の範囲が使用されます。例えば、テキストフィールドに「3/3/49」と入力すると、カレンダーには 2049 年 3 月 3 日が表示されます。
- 無効な数字を日付として入力した場合は、その数字をもとに正しい日付が推測されてポップアップカレンダーに表示されます。例えば、dd/mm/yyyy マスクを指定している場合に「32/13/2007」と入力すると、ポップアップカレンダーには 2008 年 2 月 1 日が表示されます。
次の例では、簡単なタブのレイアウトを示します。それぞれのタブには、複数の日付フィールドコントロールから構成されるフォームが表示されます。
<head> </head> <body> <cflayout type="tab" tabheight="250px" style="width:400px;"> <cflayoutarea title="test" overflow="visible"> <br> <cfform name="mycfform1"> <div style="float:left;">Date 1: </div> <cfinput type="datefield" name="mydate1"><br><br><br> <div style="float:left;">Date 2: </div> <cfinput type="datefield" name="mydate2" value="15/1/2007"><br><br><br> <div style="float:left;">Date 3: </div> <cfinput type="datefield" name="mydate3" required="yes"><br><br><br> <div style="float:left;">Date 4: </div> <cfinput type="datefield" name="mydate4" required="no"><br><br><br> </cfform> </cflayoutarea> <cflayoutarea title="Mask" overflow="visible"> <cfform name="mycfform2"> <br> <div style="float:left;">Date 1: </div> <cfinput type="datefield" name="mydate5" mask="dd/mm/yyyy"> (dd/mm/yyyy)<br><br><br> <div style="float:left;">Date 2: </div> <cfinput type="datefield" name="mydate6" mask="mm/dd/yyyy"> (mm/dd/yyyy)<br><br><br> <div style="float:left;">Date 3: </div> <cfinput type="datefield" name="mydate7" mask="d/m/yy"> (d/m/yy)<br><br><br> <div style="float:left;">Date 4: </div> <cfinput type="datefield" name="mydate8" mask="m/d/yy"> (m/d/yy)<br><br><br> </cfform> </cflayoutarea> </cflayout> </body> </html>
Internet Explorer のバージョンが IE 7 よりも前の場合は、ページの最初の 3 つのフィールドに対応するカレンダーが、後続の入力コントロールの背後に表示される可能性があります。
選択候補を表示するテキスト入力フィールドの使用
HTML でテキスト入力(type="text")を作成するときは、ユーザーの入力内容に応じてフィールドの選択候補を表示するためのスタティックソースまたはダイナミックなソースを autosuggest 属性で指定できます。ユーザーが一定の文字数を入力してから選択候補を表示するには、autosuggestMinLength 属性に文字数を指定します。
autosuggest 属性を使用する cfinput コントロールの横にラベルテキストを配置し、Internet Explorer と Firefox で正しく表示されるようにするには、style="float: left" 属性を指定した HTML の div タグでラベルテキストを囲みます。また、コントロールが複数あり、各コントロールを別の行に表示する場合は、次の例に示すように、入力コントロールの後に <br> タグを 3 つ続けます。これを行わないと、ラベルとコントロールが正しく配置されません。
<div style="float: left"> Name: </div> <cfinput name="userName" type="text" autosuggest="Andrew, Jane, Robert"> <br><br><br>
選択候補のエントリは、スタティックな値のリストとして提供します。スタティックな選択候補リストを使用するには、autosuggest 属性にリストのエントリを指定します。各エントリは、delimiter 属性で指定した文字(デフォルトはカンマ)で区切ります。その例を次に示します。
autosuggest="Alabama\Alaska\Arkansas\Arizona\Maryland\Minnesota\Missouri" name="city" delimiter="\">
この例では、cfinput コントロールに「a」または「A」と入力すると、A で始まる州のリストがドロップダウンリストに表示されます。矢印キーを押して選択対象まで移動し Enter を押すと、そのアイテムが選択されます。
また、選択候補のリストをダイナミックに生成できます。ダイナミックなリストを使用するには、CFC 関数、JavaScript 関数または URL を autosuggest 属性に指定します。関数を呼び出す最小間隔を指定するには、autosuggestBindDelay 属性を使用します。この時間間隔を指定することで、サーバーに送信されるリクエストの数が制限されます。ダイナミックなリストでは、選択候補を取得中であることを示すアイコンが、入力フィールドの右にアニメーション表示されます。
バインド式を使用するときは、{cfautosuggestvalue} バインドパラメーターを関数呼び出しまたは URL のパラメーターに指定する必要があります。
このパラメーター
を介して、入力コントロールにユーザーが入力した値が、
関数またはページに渡されます。
選択候補を生成する CFC または JavaScript 関数は、1 次元配列またはカンマ区切りリストの形式で選択候補値を返します。
URL から返す HTTP レスポンスの本文は、選択候補値を列挙した JSON 形式の配列またはリストのみで構成されている必要があります。ColdFusion の serializeJSON 関数を使用すれば、配列を JSON 形式に変換できます。例えば、選択候補を格納した配列の名前が nodeArray である場合、バインド式の URL で呼び出された CFML ページでは、次の行のみを出力します。
<cfoutput>#serializeJSON(nodeArray)#</cfoutput>
返すデータは、cfautosuggestvalue の内容に一致していなくてもかまいません。ユーザー入力に一致していない値は、クライアントサイドコードによって除外されます。実際、呼び出された関数やページでは、cfautosuggestvalue パラメーターの値を使用しなくてもかまいません。ただし、このパラメーターを使用しないと大量のデータが返される場合は、使用してください。
次の例では、バインド式を使用して、選択候補リストを表示します。[姓] テキストボックスに姓を入力すると、データベース内の該当する姓がすべて選択候補リストに表示されます。[名] テキストボックスではバインド式を使用して [姓] テキストボックスにバインドし、姓と [名] ボックスに入力されたテキストに該当する名のみを [名] テキストボックスに表示します。データベースクエリーを使用して、選択候補の条件に一致する結果のみを返しているので、選択候補リストには返された結果がすべて表示されます。また、大文字と小文字を含めてデータベースエントリと一致した場合にのみ、選択候補と一致したと見なされます。
cfdocexamples データベースを使用してこの例をテストするには、最初のボックスに「S」と入力し、選択候補リストに「Smith」と「Stewart」が表示されることを確認します。「Smith」を選択してから、「名」ボックスに「A」または「J」と入力すると、名前の選択候補が表示されます。
このアプリケーションは次のようになります。
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<cfform>
Last Name:<br />
<cfinput type="text" name="lastName"
autosuggest="cfc:suggestcfc.getLNames({cfautosuggestvalue})"><br />
<br />
First Name:<br />
<cfinput type="text" name="firstName"
autosuggest="cfc:suggestcfc.getFNames({cfautosuggestvalue},{lastName})">
</cfform>
</body>
</html>
"suggestcfc.cfc" ファイルを次の例に示します。
<cffunction name="getLNames" access="remote" returntype="array" output="false"> <cfargument name="suggestvalue" required="true"> <!--- The function must return suggestions as an array. ---> <cfset var myarray = ArrayNew(1)> <!--- Get all unique last names that match the typed characters. ---> <cfquery name="getDBNames" datasource="cfdocexamples"> SELECT DISTINCT LASTNAME FROM Employees WHERE LASTNAME LIKE <cfqueryparam value="#suggestvalue#%" cfsqltype="cf_sql_varchar"> </cfquery> <!--- Convert the query to an array. ---> <cfloop query="getDBNames"> <cfset arrayAppend(myarray, lastname)> </cfloop> <cfreturn myarray> </cffunction> <cffunction name="getFNames" access="remote" returntype="array" output="false"> <cfargument name="suggestvalue" required="true"> <cfargument name="lastName" required="true"> <cfset var myarray = ArrayNew(1)> <cfquery name="getFirstNames" datasource="cfdocexamples"> <!--- Get the first names that match the last name and the typed characters. ---> SELECT FIRSTNAME FROM Employees WHERE LASTNAME = <cfqueryparam value="#lastName#" cfsqltype="cf_sql_varchar"> AND FIRSTNAME LIKE <cfqueryparam value="#suggestvalue & '%'#" cfsqltype="cf_sql_varchar"> </cfquery> <cfloop query="getFirstNames"> <cfset arrayAppend(myarray, Firstname)> </cfloop> <cfreturn myarray> </cffunction> </cfcomponent>
数値データに関する問題
先頭にゼロが付く数値データ(例えば、郵便番号の 02674)を返す CFC メソッドでは、returnformat="string" を設定していても、このゼロはバインド式で 8 進数値として解釈され、それに相当する 10 進数値(この例の場合は 1468)として解釈されます。この問題を解決するには、URL バインドまたは JavaScript 関数(例えば cfajaxproxy を使用)によってルーティングされるバインドの場合は、returnformat=plain を設定することで数値を維持できます。また、選択候補を表示するコントロールの選択候補リストからは、先頭のゼロが除去されます。
cfslider タグの使用
cfslider タグを使用すると、一定の範囲から数値を選択するためのスライダコントロールが ColdFusion フォーム内に配置されます。このスライダは、HTML 形式およびアプレット形式のフォームを表す cfform タグ内で使用できます。cfslider は、Flash フォームではサポートされません。
HTML フォームの場合は、最大値、最小値およびインクリメント値を指定して、複雑な結果をすばやくフィルタ処理できます。使用可能なスライダコントロールには、上下にコントロールを調整できる Vertical、左右にコントロールを調整できる Horizontal、データヒントとして値が表示される Tip、指定したインクリメント値に基づき一定の間隔で移動する Snapping の 4 種類があります。
実行時のスライダの操作
次のコードは、実行時にスライダを操作する方法を示しています。
//use Coldfusion AJAX functions
var sliderChange = function(slider,value)
{
//get slider name
slidername = slider.getId();
//get slider value
currValue = ColdFusion.Slider.getValue(slidername);
//set a new slider value
newValue = parseInt(currValue+10);
ColdFusion.Slider.setValue(slidername,newValue);
//hide slider
if(confirm("Do you want to hide slider?"))
{
ColdFusion.Slider.hide(slidername);
}
//show slider
if(confirm("Do you want to show slider?"))
{
ColdFusion.Slider.show(slidername);
}
//disable slider
if(confirm("Do you disable the slider?"))
{
ColdFusion.Slider.disable(slidername);
}
//enable slider
if(confirm("Do you enable the slider?"))
{
ColdFusion.Slider.enable(slidername);
}
}
var sliderDrag = function(slider)
{
//get slider name
slidername = slider.getId();
document.getElementById('currentSliderValue').innerHTML = "Current Slider value : <font color='red'><strong>" + ColdFusion.Slider.getValue(slidername) + "<strong></font>";
}
</script>
<br>
<cfform name="frm1">
<p>
<span id="currentSliderValue">Current Slider Value: <font color="red"><strong>50</strong></font></span><br>
</p>
</cfform>
<p>
<br><b>Volume</b>:
<cfslider
name="s"
format="html"
min=1
max=100
value="50"
tip="yes"
onChange="sliderChange"
onDrag = "sliderDrag"
vertical="no"
width="200pt"
>
</p>