2007年7月30日 (月)

[CSS]IE6とIE7でスタイルシートを分けるテクニック

前回からだいぶ更新をサボってしまいましたが、久々のアップです。

スタイルシートを適用してページを作成するとIEとFireFoxで期待したとおりの表示ができない場合がよくあります。またIEでもバージョン6と7でも違って表示される場合があります。

こんなときにはFireFoxでとりあえず表示できるようにしておいて、IE6とIE7でそれぞれ別のCSSを適用して表示を思ったようにするテクニックがあります。

IE6の場合には、セレクタの頭に「* html」とつけます。

たとえば、

* html .sample {
    color: #00ff00;
}

とするとクラスが「sample」となっている部分の文字の色が緑で表示されるようになります。

IE7に適用したい場合は、セレクタの頭に「*:first-child+html」とつけます。

たとえば、

*:first-child+html .sample {
    color: #0000ff;
}

とするとクラスが「sample」となっている部分の文字の色が青く表示されるようになります。

両方を同じスタイルシートに記述することでアクセスしたブラウザによって表示を変えることができます。

.sample {
    color: #ff0000;
}
html .sample {
    color: #00ff00;
}
*:first-child+html .sample {
    color: #0000ff;
}

これは、FireFoxとSafariでアクセスした場合は、IE6は、IE7ではで表示されるようになります。

こんな↓感じになります。ブラウザを変えてアクセスしてみてください。

このテクニックは、主にpositionを利用した場合にアクセスしたブラウザで微妙に位置がずれるといった場合によく使うと思います。

注意ですが、記述された順番でCSSが適用されるので頭に何もつかないセレクタを最後にもってくると最後のCSSが適用されてしまうので意味がなくなってしまいます。ですのでくれぐれも順番に気をつけてください。

| | コメント (0) | トラックバック (0)

2007年4月28日 (土)

fix onが雑誌に掲載されました。

fix onが、YAHOO! Internet Guide 6月号に掲載されました。

特集1の「インターネットでできること333」の仕事に使えるツールとして紹介されています。

| | コメント (0) | トラックバック (0)

2007年4月17日 (火)

ケータイからも利用ができる無料の予定調整ツール「fix on」を公開いたしました。

リリースから1週間以上過ぎてしまいましたが、Webサービスの第二弾としてケータイからも利用ができる無料の予定調整ツール「fix on」を公開いたしました。

fix onのURLはこちらから
[fix on]

報道関係各位 2007年4月5日
プレスリリース グルーブテクノロジー株式会社
http://groovetechnology.co.jp/

簡単に予定の調整ができるWeb サービス「fix on」(ベータ版)無償提供開始
~ケータイからも簡単に予定を調整できる~

グルーブテクノロジー株式会社(本社:埼玉県川口市 代表取締役:嶋 敦)は、簡単に予定を調整することができる無料サービス「fix on(フィックスオン)」(ベータ版) を本日、2007 年 4 月 5 日 (木)より公開します。

「fix on」は、予定を登録したときに生成される予定のURLを仲間同士で共有し予定の調整簡単に行うことができるWebサービスです。

プレスリリースの詳しい内容は、こちらに書いてありますので興味のある方は、ご覧ください。
簡単に予定の調整ができるWeb サービス「fix on」(ベータ版)無償提供開始 ~ケータイからも簡単に予定を調整ができる~

簡単にサービス内容を説明すると、予定を登録したときに生成されるURLを仲間どうして共有して予定の調整を行うというサービスです。

主に飲み会やサークルなどの会合の予定を調整するときに使えるツールです。

ほかにも似たようなサービスはありますが、fix onの特徴として

  • ケータイで利用ができる
  • 通知がメールで来るので予定の返答が登録されたかどうかいちいちチェックに行かなくてよい
  • メンバーの登録はいらない
  • 余計な機能がないので使い方は簡単

といった感じです。

日付を入れる部分は、テキストで入力するようになっているので日付だけでなく場所やお店などの候補も入れることができるようになっているので簡単なアンケートツールとしても利用できます。

無料で使えるツールになっているのでよかったら使ってください。また、ご意見やご要望などいろいろありましたらどんどんお寄せください。

| | コメント (0) | トラックバック (0)

2007年3月 9日 (金)

[JavaScript]JavaScript(JSONP)で郵便番号検索API利用する

前回公開したWeb サービスですが実際に使用する方法を簡単に説明したいと思います。

Ajaxなどを利用してサーバーから非同期にデータを取得する方法が最近は流行ですが、Ajaxで問題になるのは、呼び出したサイトとしか通信ができないので自分のサーバーに仕組みを作っておかなければならないということです。

このため、いままで住所の入力をするときに郵便番号から住所を入力を保管するような仕組みを作ろうとすると、自分たちの管理しているサーバーに仕組みを構築して、そのデータを自分たちで管理しなければなりませんでした。

これらの手間を考えると面倒だし、レンタルサーバーなどで思うように仕組みを構築できない場合には、手で入力すればいいやと思うためあきらめていなかったのではないでしょうか?

そんなときこのサービスを使っていただきたいと思います。

サーバーの構築などは必要ありませんし、データの更新も自動的に行ってくれるので管理の手間はいりません。

それでは、実際の使い方について説明したいと思います。使い方といっても、JavaScriptを読み込むコードを書くだけなんですけど。

function zipsearch()
{
  var zipcode = document.getElementById( 'zipcode' ).value;
  
  if( ! check_zipcode( zipcode ) )
   return false;
  var target = document.createElement('script');
  target.charset = 'utf-8';
  target.src = 'http://groovetechnology.co.jp/ZipSearchService/v1/zipsearch?zipcode='+encodeURIComponent( zipcode )+'&callback=callback1';

  document.body.appendChild(target);
}

上記のコードは、郵便番号が入力されて検索ボタンが押されたときに呼び出される関数と思ってください。

やっていることは、郵便番号の入力フィールドから入力された郵便番号を取り出してその入力をチェックした後にドキュメント内にscriptタグを新たに作ってそこに外部からJavaScriptを呼び出しているということを行っています。このとき読み込むJavaScriptのソースにパラメータ(郵便番号とコールバックの関数名)を渡して呼び出しています。

これで外部のJavScriptのソースの読み込みが完了するとコールバック関数が呼び出されてそこに引数としてサーバーで検索された結果が入ってきます。

下記のソースは、そのコールバック関数の一例で検索結果を一覧表示するというものです。このコールバックの中身を替えることで一覧表示させるだけではなく、ほかの処理をさせることができます。

function callback1( data )
{
  zip_data = data;
  var html = '<table style="width:100%;border:1px solid #666666;border-collapse:collapse;" border="1">';
  html += '<col style="width:1em;">';
  for (var i in zip_data.zipcode )
  {
    html += '<tr><td><input type="button" name="" value=" 利用する" onclick="used( \''+ i +'\' );return false;" /></td><td style="white-space:nowrap">' + data.zipcode[i].zipcode.substr(0,3) + '-' + data.zipcode[i].zipcode.substr(3) +'</td><td style="white-space:nowrap">' + data.zipcode[i].prefecture + '</td><td style="white-space:nowrap">' + data.zipcode[i].city  + '</td><td style="white-space: nowrap;text-align:left;">' +  data.zipcode[i].town  + "</td><td> </td></tr>\r\n";
  }
  for (var i in zip_data.office )
  {
    html += '<tr><td><input type="button" name="" value=" 利用する" onclick="used( \''+ i +'\' );return false;" /></td><td style="white-space:nowrap">' + data.office[i].zipcode.substr(0,3) + '-' + data.office[i].zipcode.substr(3) +'</td><td colspan="3" style="white-space:nowrap">' + data.office[i].office_name + '</td><td style="white-space:nowrap">' + data.office[i].prefecture + data.office[i].city + data.office[i].town + data.office[i].street + "</td></tr>\r\n";
  }
  html += "</table>\r\n";

  document.getElementById( 'codes' ).innerHTML = html;
}

これらの仕組みは、JavaScriptの外部のファイルの呼び出しがドメインに関係なくできるということを利用しています。これにより、サーバーに仕組みを構築しなくても、JavaScriptだけでほかのサーバーにあるデータを読み込んでそのデータを活用できるということになります。

ここで用いられているのがJSONP(JSON with padding)という方法(というか形式)で最近では、GoogleやYahooのWebサービスでも使われるようになっています。

実際に動くようにしたのが下のサンプルになります。3桁以上の郵便番号を入力してから住所検索ボタンを押すとポップアップ画面が表示されて複数の候補から選択できるようになっています。ハイフンの有無は関係ありません。

このように違うサーバーからデータを取得してきてそのデータを利用することができます。

下のリンクは、このサンプルをZIPにしたファイルです。自分のローカルで試すこともできますし、自分で管理しているサーバーにおいて使用することも可能です。

| | コメント (1) | トラックバック (1)

2007年3月 7日 (水)

Webサービスを開始、第一弾として郵便番号検索APIを公開いたしました

Webサービスを開始して、第一弾として郵便番号検索APIを公開いたしました。


報道関係各位 2007年3月7日
プレスリリース グルーブテクノロジー株式会社
http://groovetechnology.co.jp/

グルーブテクノロジー Web サービスを開始
~第一弾として郵便番号検索APIを公開いたしました~
JSONP,XMLなど複数のデータ形式の出力に対応

グルーブテクノロジー株式会社(本社:埼玉県川口市 代表取締役:嶋 敦)は、グルーブテクノロジー Webサービスを本日、2007 年 3 月 7 日 (水)より公開します。
第一弾として「郵便番号検索API」を一般公開しました。

さらに詳しい内容は、こちらに書いてありますので興味のある方は、ご覧ください。
グルーブテクノロジー Webサービスを開始 ~第一弾として郵便番号検索APIを公開いたしました~

| | コメント (0) | トラックバック (0)

2007年2月22日 (木)

発売を開始します。

ようやく、製品が完成して発売までこぎつけました。

まだまだ、足りないこところはありますが、どんどん改良を重ねてよいものにしていきたいと考えていますので、よろしくお願いします。


報道関係各位 2007年2月22日
プレスリリース グルーブテクノロジー株式会社
http://groovetechnology.co.jp/

グルーブテクノロジー 『GT 顧客管理』発売開始
~さまざまな顧客情報を一元管理して顧客対応を強化する~
- 5月末までの発売記念キャンペーンも開始 -

グルーブテクノロジー株式会社(本社:埼玉県川口市 代表取締役:嶋 敦)は、顧客管理システム「GT 顧客管理」を本日、2007 年 2 月 22 日 (木)より発売します。ホームページでは 60 日間、全機能を無償でお試しいただける「GT 顧客管理」製品版のダウンロード提供を開始しました。発売を記念して、通常価格から30%OFFを割引くキャンペーンも実施いたします。


さらに詳しい内容は、こちらに書いてありますので興味のある方は、ご覧ください。
『GT 顧客管理』の発売を開始いたします。

| | コメント (0) | トラックバック (0)

2007年2月15日 (木)

拡張子がHTMLのファイルをPHPとして実行させる

PHP を Apache 上で動作させるときには。モジュールとして組み込む方法が一般的だと思います。

通常は、「AddType」を用いて PHP ファイルを認識させます。「httpd.conf」ファイルに以下のような文を追加します。

AddType application/x-httpd-php .php

しかし、これでは明らかにPHPを使用していることがわかってしまいます。それにHTMLファイルの中に一部PHPを埋め込んで動作させたい場合があると思います。
そういった場合には、httpd.confファイルにHTMLの拡張子である「.html」を追加します。

AddType application/x-httpd-php .php .html

このままだとすべての「.html」という拡張子がついたファイルがいったんPHPで読み込まれることになるので無駄な処理が実行されてしまいます。

こういった場合は、特定のディレクトリのファイルだけ対象になるように「.htaccess」ファイルに上記の設定を行います。

このときhttpd.confファイルの設定で該当のディレクトの<Directory>セクションにあるAllowOverrideディレクティブに「FileInfo」が指定されていない場合動作しないので気をつけてください。自分でサーバーを管理していない場合は、管理者にお問い合わせください。

<Directory>セクションとAllowOverrideディレクティブの詳しいことは、Apacheのドキュメントに書かれているのでそちらを参考にしてください。
<Directory>セクションのドキュメント
AllowOverrideディレクティブのドキュメント

しかし、これでもまだ関係ないファイルが多い場合などは無駄な処理が実行されてしまいます。こういった場合は、.htaccessファイルに<Files>セクションを追加することで指定のファイルだけをPHPとして処理することが可能です。

<Files form.html>
    ForceType  application/x-httpd-php
</Files>

こうすることで特定のファイルだけをPHPのファイルとして実行させることが可能です。<Files>セクションのファイル名は正規表現を使うことができるようです。

<Files>セクションとForceTypeディレクティブの詳しいことは、Apacheのドキュメントに書かれているのでそちらを参考にしてください。
<Files>セクションのドキュメント
ForceTypeディレクティブのドキュメント

これでスマートにPHPを実行させることができます。

| | コメント (0) | トラックバック (0)

2007年1月29日 (月)

[PHP]拡張モジュールを自作する

あけましおめでとうございます。といってもすでに1月も終わろうとしていますが ^^;
本年もヨロシクお願いします。

今年一発目のネタは、PHPで拡張モジュールを自分で作ってしまおうというネタです。

PHPはすでにいろいろな機能が、標準でついているのでほとんど自作する必要はありません。それ以外にもPEARPECL といった拡張モジュールもいろいろあるので、それらを使うといろいろなことができます。
しかし、ライセンスの問題であったり、パフォーマンスを出すために独自機能をスクリプト以外で作ろうとするためには、やはり自分で拡張モジュールを作る必要があります。

そこで今回は、実際に拡張モジュールを作ってみました。

方法は、すでに標準のPHPのソースの中に拡張モジュールを簡単に作る機能があるのでそれを使用していきます。

まずはじめに、関数の雛形を作ります。これは、実際にスクリプトから呼び出す関数の宣言を行うファイルで関数名とその関数の引数や戻り値を書いておきます。これを使用するとこの宣言しておいた関数を基にソースの中身を作成してくれるのであとの作業が楽になります。

test.protoファイルの内容
void myfunction_a(string szInput)・・・(1)
string myfunction_b(string szInput , int nIDs )・・・(2)
string myfunction_c(mixed mInput , array aIDs )・・・(3)

(1)は、引数が文字列で戻り値がなしの関数で(2)は戻り値が文字列で引数が文字列と整数型になっています。(3)の関数は戻り値が文字列で第1引数が何でもありで第2引数が配列型になっています。。
string」,「mixed」,「array」は、PHPの型です。
これ以外の型については、PHPのマニュアルの型の部分に書いてあるものが使用できるはずです。(「string」,「int」,「array」,「mixed」以外は試してませんがこれらについては雛形がきちんとできていました。)
ちなみに関数名に英大文字を使用すると怒られるようです。

関数の雛形ファイルを作成したら今度はこれを使用して実際のソースの雛形を作成します。

Windowsの場合はCygwinが必要になりますのでCygwinプロジェクトからダウンロードしてインストールをしておいてください。

Cygwinまたは、UNIXのシェルから以下のコマンドを発行してソースを作成します。

$ sh ext_skel --extname=test --proto=test.proto

「--extname」で拡張モジュールのパッケージ名を指定します。この指定した名前のディレクトリが作成されてその中にソースの雛形が作成されます。
「--proto」に先ほど作成した関数の雛形が書いてあるファイル名を指定します。それでこの関数の雛形がソースの中に作成されます。

作成されたディレクトリの中をみると以下のファイルが作成されています。

$ ls -l
合計 32
-rw-r--r--  1 shima  shima     4  1月 29 22:19 CREDITS
-rw-r--r--  1 shima  shima     0  1月 29 22:19 EXPERIMENTAL
-rw-r--r--  1 shima  shima    1975  1月 29 22:19 config.m4
-rw-r--r--  1 shima  shima   282  1月 29 22:19 config.w32
-rw-r--r--  1 shima  shima    2771  1月 29 22:19 php_test.h
-rw-r--r--  1 shima  shima    6467  1月 29 22:19 test.c
-rw-r--r--  1 shima  shima   496  1月 29 22:19 test.php
drwxr-xr-x  2 shima  shima    4096  1月 29 22:19 tests

「test.c」と「php_test.h」が関数の中身を実装していくファイルになります。このファイルに関しては、後は普通のCの関数として実装していけばよいです。戻り値や引数などの処理については、このほかの拡張モジュールのソースを参考にしていけば大変ですが実装は可能です。

関数の実装が終わった後は、組み込みを行います。そのまま組み込に条件「--with-XXX」とか「--enable-XXX」をつける場合は、「config.m4」と「config.w32」を編集して必要な部分からコメントの記号をのぞいて有効にします。
注意点ですが、「config.w32」で「--with-XXX」を有効にしたときにほかの部分のコメントを残しておいたまま処理を行った場合にうまくいきませんでした。うまくいかなかった場合は、先頭2行以外のコメント部分を完全に削除したほうがいいかもしれません。

組み込みは、buildconfを実行して「configure」スクリプトに反映させます。これを行わないとビルドしたときに組み込まれません。Windowsでは、「buildconf.bat」を実行します。

$ ./buildconf

ここでエラーが出なければ「configure」スクリプトを実行します。Windowsでは、「cscript /nologo configure.js」を実行します。ほかのオプションに関しては、必要なものを指定してください。

$ ./configure '--enable-mbstring' '--enable-mbregex' '--with-pcre-regex' '--enable-session' ・・・

続いてビルドします。

$ make

これでビルドのエラーが出なければ完成です。

もし、関数が正しく実装されたかどうかを確認する場合は、「tests」ディレクトリ内の「001.phpt」ファイル内に関数のテストコードを実装しておけば「make test」とビルド後に実行すれば自動的にテストを行ってきちんと動作しているか確認することができます。

以上で拡張モジュールを自分で作成する方法を簡単に説明しました。実際には、PHP独自の実装をいろいろ行わなければなりませんが似たような機能が実装されている拡張モジュールがほかにあると思いますのでそちらの関数を参考にしながら実装するのが簡単だと思います。くれぐれもそのままパクらないでくださいね。

| | コメント (0) | トラックバック (0)

2006年12月26日 (火)

[JavaScript]JavaScriptでiframeの中身の操作

前回、「iframe」タグを用いたメニューの作成方法をご紹介しました。この方法だとIEでも後ろの「select」タグがきちんと隠れるように表示できます。
しかし、この方法だと「div」タグを使用した方法のように表示のサイズをないように応じて動的に変更させたい場合には、うまくいきません。
今回は、それを回避できる方法をご紹介したいと思います。ただし、この方法はIE以外ではあまりうまくいかないのでブラウザごとに処理を分けてIEでのみ実施したほうがいいです。

方法といってもそれほど難しい方法ではなく単純に「iframe」タグの中身を動的にJavaScriptで書き換えるのと「iframe」タグのスタイルで「width」と「height」に値をあたえて大きさを調整するといった方法です。

では、実際のサンプルです。メニューは、サブメニューのリンクをクリックして閉じてください。

メニュー ⇒

中身を見ていくと

HTMLの内容
<div id="topmenu" class="topmenu" style="width:6em;float:left;" onmouseover="showmenu( 'sample' );">メニュー ⇒</div><div>
 <iframe id="sample3" class="submenu" style="display:none;z-index:1000;" frameborder="0"></iframe>

JavaScriptの内容
function show_iframe( id )
{
  var target = document.getElementById( id );

  var idoc = null;
  if( target.contentDocument )
    idoc = target.contentDocument;
  else
    idoc = document.frames[id].document;

  html  = '<html><head><title></title><head><body style="margin:0px">\r\n';
  html += '<table style="width:100%;margin:0px">\r\n';
  html += '<tr><td style="white-space:nowrap"><a href="#" onclick="window.parent.close_iframe( \'sample\' )">サブメニュー1</a></td></tr>\r\n';
  html += '<tr><td style="white-space:nowrap"><a href="#" onclick="window.parent.close_iframe( \'sample\' )">サブメニュー2</a></td></tr>\r\n';
  html += '<tr><td style="white-space:nowrap"><a href="#" onclick="window.parent.close_iframe( \'sample\' )">サブメニュー3</a></td></tr>\r\n';
  html += '<tr><td style="white-space:nowrap"><a href="#" onclick="window.parent.close_iframe( \'sample\' )">ちょっと長くなったサブメニュー4</a></td></tr>\r\n';
  html += '<tr><td style="white-space:nowrap"><a href="#" onclick="window.parent.close_iframe( \'sample\' )">さらにちょっと長くなったサブメニュー5</a></td></tr>\r\n';
  html += '</table>\r\n';
  html += '</body></html>\r\n';

  idoc.open();
  idoc.write( html );
  idoc.close();

  target.style.display = '';

  idoc.body.offsetHeight;
  idoc.body.offsetWidth;
  target.style.height = idoc.body.scrollHeight;
  target.style.width = idoc.body.scrollWidth;
}

function close_iframe( id )
{
  var target = document.getElementById( id );
  target.style.display = 'none';
}

JavaScriptの内容は、iframe内のdocumentオブジェクトを取得してそれにHTMLの内容を書き込んでいます。ドキュメントとの取得方法は、IEとFireFoxで違っていてFireFoxでは「target.contentDocument」、IEでは「document.frames[id].document;」として取得しています。
取得したオブジェクトに対して「open」「write」「close」で内容を書き込んでいきます。

その後、サイズを繁栄させるのですが、このままではまだ画面に表示していないので実際のサイズはわかりません。そこで一度、「target.style.display='';」を実行して表示させてから、画面のサイズを取得しています。
ここでなぜか、関係のない

  idoc.body.offsetHeight;
  idoc.body.offsetWidth;

を行っていますが、これはその後の「idoc.body.scrollHeight」で値を取得するために呼び出しています。なぜかわかりませんが一度、この呼び出し(どちらか一方でいいです)をしないときちんと取れなかったので呼び出しています。

あとは、取得した表示領域の大きさを「iframe」タグに反映させれば、うまい具合に表示されるようになります。

この方法で問題があるのが、MacのSafariで動作しないということです。おそらくセキュリティの問題とは、思われますが気をつけてください。
それと当然のことですが、「iframe」タグ内にドメインの違うHTMLを表示するとセキュリティ上の制約で操作できないので「src」には、何も記述しないようにしてください。

1つにまとめたサンプルです。

今回の記事で今年は、終わりになります。今年は、独立したりといろいろ激動の年になりましたが来年はいよいよ製品のリリースをして本格的なスタートを行いたいと思っています。
来年もよろしくお願いいたします。

| | コメント (0) | トラックバック (0)

2006年12月19日 (火)

[JavaScript]JavaScriptで作るメニュー パート3

前回までのJavaScriptで、ダイアログやメニューなどを作成してきましたが、実はIEの場合のみある条件であまりよろしくない状態になってしまうことがあります。
それは、「div」の指定で「position:absolute」の指定をして表示した場合に表示している領域の下に「select」タグがあるとそちらが表示されてしまうという現象が発生します。

実際に行ってみるとこんな感じになります。

メニュー ⇒

このようにIEでは、「z-index」をいくら大きくしても下にある「select」タグの内容が表示されてしまいせっかく作ったダイアログやメニューが台無しになってしまいます。

しかし、これについて回避する方法があります。それは、「iframe」を使用することにより回避できるようになります。
「iframe」タグは、インラインフレームのことでHTMLのページの中にほかのページを埋め込むことができる機能です。

実際にやってみるとこのようになります。

メニュー ⇒

これで、IEでも問題なくダイアログやメニューが表示できるようになります。

中身を見ていくと

HTMLの内容
<div id="topmenu" class="topmenu" style="width:6em;float:left;" onmouseover="showmenu( this, 'sample3' );" onmouseout="hiddenmenu( 'sample3' );">メニュー ⇒</div><div><select>
 <option>選択1</option>
 <option>選択2</option>
 <option>選択3</option>
 <option>選択4</option>
 <option>選択5</option>
</select></div>
 <iframe id="sample3" class="submenu" style="display:none;z-index:1000;height:6.6em;" frameborder="0" src="http://at-shima.cocolog-nifty.com/sample/menu3_iframe.html" onmouseover="onmousemenu( 'sample3' );" onmouseout="hiddenmenu( 'sample3' );"></iframe>

iframeで読み込んでいるHTMLの内容
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
 <meta http-equiv="content-type" content="text/html;charset=UTF-8">
 <meta http-equiv="Content-Style-Type" content="text/css">
 <meta http-equiv="Content-Script-Type" content="text/javascript">
 <link href="http://at-shima.cocolog-nifty.com/css/menu.css" type="text/css" rel="stylesheet" />
</head>
<body style="margin:0px;padding:0px;">
  <div class="menuitem"><a class="menuitem" href="#" onclick="window.parent.closeMenu( 'sample3' );return false;">サブメニュー1</a></div>
  <div class="menuitem"><a class="menuitem"  href="#" onclick="window.parent.closeMenu( 'sample3' );return false;">サブメニュー2</a></div>
  <div class="menuitem"><a class="menuitem"  href="#" onclick="window.parent.closeMenu( 'sample3' );return false;">サブメニュー3</a></div>
  <div class="menuitem"><a class="menuitem"  href="#" onclick="window.parent.closeMenu( 'sample3' );return false;">サブメニュー4</a></div>
  <div class="menuitem"><a class="menuitem"  href="#" onclick="window.parent.closeMenu( 'sample3' );return false;">サブメニュー5</a></div>
</body>
</html>

「iframe」タグで読み込んでいる内容とHTMLの中身が変わっただけでスタイルシートやJavaScriptの内容は、[JavaScript]JavaScriptで作るメニューと同じ内容になっています。イガっているのは、メニューの表示部分で「iframe」を使用しているということだけになります。

「iframe」タグの中でメニューを閉じるために「window.parent.closeMenu( 'sample3' );」と呼び出していますがこれは、iframeを読んでいるウインドウ(トップメニューがあるほうのWindow)のJavaScriptを呼び出していることになります。

注意点としては、「iframe」タグで呼び出すHTMLの中身はそれ自体で表示されるHTMLとして記述する必要があるので「html」タグからきちんと記述する必要があります。当然別のHTMLとして記述するので必要なスタイルシートやJavaScriptもきちんと記述する必要があります。
あと、基本的には「iframe」タグを使用するのは、IEのみにしてほかのブラウザで表示する場合には、前回までの表示方法を使用することをお勧めします。「iframe」タグは別のHTMLを表示していることになるので2回サーバーに対してリクエストを発行することになりますし、表示の大きさなどをきちんと指定しないとスクロールバーが表示されたりします。これがすべてのブラウザで同じ場合はいいのですがIEとFireFoxで表示する大きさがちょっとずつ違っているので大変なことになります。

1つにまとめたサンプルです。

| | コメント (0) | トラックバック (0)

2006年12月 8日 (金)

JavaScript]JavaScriptで作るメニュー パート2

今回は、前回に引き続きJavaScriptでメニューの作成を行いたいと思います。

前回の動的なメニューの作成では、マウスがメニューから外れてしまうと開いていたプルダウンメニューが勝手に消えてしまうので実際に使用していると使い勝手が悪かったりします。
そこで今回のメニューではプルダウンで開いたメニューが、メニューの領域以外の画面のほかの部分をクリックしたときに閉じるようにしてみたいと思います。

メニュー ⇒

中身をみていくと

HTMLの内容
<div id="topmenu" class="topmenu" style="width:6em;" onclick="showmenu2( 'sample1' );">メニュー ⇒</div>
 <div id="sample1" class="submenu" style="display:none;">
  <div class="menuitem"><a class="menuitem" href="" onclick="alert( 'サブメニュー1' );closeMenu2();return false;">サブメニュー1</a></div>
  <div class="menuitem"><a class="menuitem" href="" onclick="alert( 'サブメニュー2' );closeMenu2();return false;">サブメニュー2</a></div>
  <div class="menuitem"><a class="menuitem" href="" onclick="alert( 'サブメニュー3' );closeMenu2();return false;">サブメニュー3</a></div>
  <div class="menuitem"><a class="menuitem" href="" onclick="alert( 'サブメニュー4' );closeMenu2();return false;">サブメニュー4</a></div>
  <div class="menuitem"><a class="menuitem" href="" onclick="alert( 'サブメニュー5' );closeMenu2();return false;">サブメニュー5</a></div>
</div>

読み込んでいるCSSファイルの内容(前回と同じです)
.topmenu {
 border:solid 1px gray;
}

.submenu {
 width: 10em;
 background-color:white;
 border:solid 1px gray;
 position: absolute;
 z-index:1000;
}
.menuitem {
 width:100%;
 white-space:nowrap;
 border-bottom:solid 1px gray;
 margin:0;
}

a.menuitem:link{
 text-decoration:none;
}
a.menuitem:visited{
 text-decoration:none;
}
a.menuitem:hover{
 text-decoration:none;
 background-color:lightcyan;
}
a.menuitem:active{
 text-decoration:none;
 background-color:lightcyan;
}

JavaScriptの内容
var menuobj = null;
var menu_id = null;

function showmenu2( id )
{
  var target = document.getElementById( id );

  target.style.display = '';
  
  menuobj = new Rect(0,0,0,0);
  menuobj.getElementRect( target );
  menu_id = id;
}

document.onmousedown = function( e )
{
 if( ! menuobj  ) return;

  var target = document.getElementById( menu_id );

  if( target.display != 'none' )
  {
    var pt = null;
    if( document.all )
    {
      pt = new Point(event.x , event.y );
    }
    else
    {
      pt = new Point(e.pageX , e.pageY );
    }

    if( ! menuobj.PtInRect( pt ) )
    {
      menuobj = null;
      target.style.display = 'none';
    }
  }

  return true;
}

function  closeMenu2()
{
  var target = document.getElementById( menu_id );
  if( target )
  {
    target.style.display = 'none';
  }
  menuobj = null;
  menu_id = null;
}

function Rect( x, y, width, height )
{
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
  
}

Rect.prototype.getElementRect = function( target )
{
  if( target.display != 'none' )
  {
    var top = target.offsetTop;
    var left = target.offsetLeft;
    var obj = target.offsetParent;
    for( ;; )
    {
      if( ! obj )
        break;

      top += obj.offsetTop;
      left += obj.offsetLeft;

      obj = obj.offsetParent;
    }

    this.x = left;
    this.y = top;
    this.width = target.offsetWidth;
    this.height = target.offsetHeight;

    return true;
  }

  return false;
}

Rect.prototype.PtInRect = function(point)
{
  if( this.x > point.x || (this.x+this.width ) < point.x )
   return false;
  if( this.y > point.y || (this.y+this.height ) < point.y )
   return false;

  return true;
}

Rect.prototype.toString = function()
{
  return 'X:' + this.x + ' Y:' + this.y + ' Width:' + this.width + ' Height:' + this.height;
}

function Point( x, y )
{
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function()
{
  return 'X:' + this.x + ' Y:' + this.y;
}

となっています。

中身を見ていくといつものようにプルダウンの部分を「display:none;」で隠しておいてトップメニューをクリックしたときにそれを表示るようにしています。
そしてプルダウンメニューの部分の領域を保存しておいて、マウスをクリックしたときにその保存しておいた領域外でイベントが発生してたときにプルダウンメニューを再び隠すということを行っています。

このJavaScriptの中で「Rect」と「Point」がありますがこれは「function」を用いてユーザー定義の独自のクラスを定義してます。
このように独自のクラスを用いることでオブジェクト指向な実装をすることが可能になっています。

1つにまとめたサンプルです。

| | コメント (0) | トラックバック (0)

2006年11月30日 (木)

[JavaScript]JavaScriptで作るメニュー

ちょっと前回の更新から時間が空いてしまいましたが今回は、JavaScriptでプルダウン形のメニューを作成します。

一番簡単なのは、最初にサブメニューの部分に「display:none;」を指定して隠していおいて、マウスのクリックイベントなどでメニュー部分を表示するタイプで

という風になります。

もう少し高度になるとNiftyのトップページでも行っていますが、メニューの部分にマウスカーソルを持っていくと新たなメニューが表示されてそこから新しい選択肢を選択できるというものです。実際にデモしてみると

メニュー ⇒

という感じになります。

こちらは、マウスがメニューの上に来たときにonmouseoverイベントでメニューを表示して、onmouseoutイベントでタイマーを発生させてある程度の時間メニューからマウスが離れていたらメニューを消すような処理を行っています。

中身を見ていくと

HTMLの内容
<div id="topmenu" class="topmenu" onmouseover="showmenu( this, 'sample2' );"  onmouseout="hiddenmenu( 'sample2' );">メニュー ⇒</div>
 <div id="sample2" class="submenu" style="display:none;" onmouseover="onmousemenu( 'sample2' );" onmouseout="hiddenmenu( 'sample2' );">
  <div class="menuitem"><a class="menuitem" href="" onclick="closeMenu( 'sample2' );return false;">サブメニュー1</a></div>
  <div class="menuitem"><a class="menuitem"  href="" onclick="closeMenu( 'sample2' );return false;">サブメニュー2</a></div>
  <div class="menuitem"><a class="menuitem"  href="" onclick="closeMenu( 'sample2' );return false;">サブメニュー3</a></div>
  <div class="menuitem"><a class="menuitem"  href="" onclick="closeMenu( 'sample2' );return false;">サブメニュー4</a></div>
  <div class="menuitem"><a class="menuitem"  href="" onclick="closeMenu( 'sample2' );return false;">サブメニュー5</a></div>
</div>

読み込んでいるCSSファイルの内容
.topmenu {
 border:solid 1px gray;
}

.submenu {
 width: 10em;
 background-color:white;
 border:solid 1px gray;
 position: absolute;
 z-index:1000;
}
.menuitem {
 width:100%;
 white-space:nowrap;
 border-bottom:solid 1px gray;
 margin:0;
}

a.menuitem:link{
 text-decoration:none;
}
a.menuitem:visited{
 text-decoration:none;
}
a.menuitem:hover{
 text-decoration:none;
 background-color:lightcyan;
}
a.menuitem:active{
 text-decoration:none;
 background-color:lightcyan;
}

JavaScriptの内容
var timer_id = null;
function showmenu( parent, id )
{
  var target = document.getElementById( id );
  var top = 0;
  var left = 0;
  var obj = parent.offsetParent;
  for( ;; )
  {
    if( ! obj )
      break;

    top += obj.offsetTop;
    left += obj.offsetLeft;

    obj = obj.offsetParent;
  }

  target.style.top = top + parent.offsetTop;
  target.style.left = left + parent.offsetLeft + parent.offsetWidth;
  target.style.display = '';
  if( timer_id )
  {
    clearTimeout( timer_id );
    timer_id = null;
  }
}

function onmousemenu()
{
  if( timer_id )
  {
    clearTimeout( timer_id );
    timer_id = null;
  }
}

function hiddenmenu(id)
{
  timer_id = setTimeout( "closeMenu('"+id+"')", 400 );
}

function closeMenu(id)
{
  var submenu = document.getElementById( id );
  submenu.style.display = 'none';
  timer_id = null;
}

となっています。

注意点ですが、setTimeout関数で別の関数を呼び出すときに単純にsetTimeout( "closeMenu("+id+")", 400 )とすると文字列を渡していたidが受け取り側のcloseMenuでは、オブジェクトととして渡されてくるのでうまく動きません。そのためsetTimeout( "closeMenu('"+id+"')", 400 )という風にidを「'(シングルクォート)」でくくる必要があります。

前回と同様に1つにまとめたサンプルになります。

| | コメント (0) | トラックバック (0)

2006年11月16日 (木)

[CSS&JavaScript]CSSでダイアログの作成 パート2

今回は、前回パート1で作成したダイアログをドラッグ&ドロップで画面上を動くようにしたいと思います。

といっても難しいことはなく、JavaScriptのマウスイベントを利用してスタイルシートで指定している位置を動かすということを行っています。

まずは、ダイアログの作成でこれは前回のものを利用します。ダイアログを動かすためにスタイルのpositionabsoluteにすることを忘れないようにしてください。この指定をしないと動きません。

ダイアログの部分
<div class="dlg" id="dlg" style="display: none;position:absolute;">
<div id="dlghead" >
  <div class="dlghead1"></div>
  <div class="dlghead2"></div>
  <div class="dlghead3"></div>
  <div class="dlghead4"><a onclick="close_dialog();return false;" href="#">×</a></div>
</div>
  <div class="dlgbody">
   <table style="margin:0px 5px;padding:2px 5px;">
    <tr>
     <th style="text-align:left;">名前</th>
     <td><input type="text" size="30"></td>
    </tr>
    <tr>
     <th style="text-align:left;">パスワード</th>
     <td><input type="password" size="30"></td>
    </tr>
   </table>
   <input type="button" value="登録する" onclick="close_dialog();return false;" style="margin-left:5px">
</div>
</div>

続いては、これを動かすためのJavaScriptを作成します。

JavaScriptの部分
var target;var offsetX;var offsetY; ①

function mouseDown( e ) ②
{
  target = document.getElementById( 'dlg' );
  target.style.cursor = 'move';
  
  if( e )
  {
    offsetX = e.layerX;offsetY = e.layerY;
  }
  else if( event )
  {
    offsetX = event.offsetX;offsetY = event.offsetY;
  }
  
  return false;
}

function mouseMove( e ) ③
{
  if( ! target ) return false;
  
  var x;var y;
  if( e )
  {
    x = e.pageX;y = e.pageY;
  }
  else if( event )
  {
    x = event.clientX + document.body.scrollLeft;
    y = event.clientY + document.body.scrollTop;
  }
  x -= offsetX;y-=offsetY;
  target.style.left = x; target.style.top = y;
  return false;
}

function mouseUp( e ) ④
{
  if( ! target ) return false;
  target.style.cursor = 'auto';
  target = null;
}

function init_page() ⑤
{
  var dialogHead = document.getElementById( 'dlghead' );
  dialogHead.onmousedown= mouseDown;
  document.onmouseup= mouseUp;
  document.onmousemove= mouseMove;
}

window.onload = init_page; ⑥

解説していきます。

は、ダイアログとその位置を保存するための変数です。これがないと動かしているときの位置などがわからなくなってしまいます。

は、ダイアログのタイトルバーの部分をクリックしたときに発生するイベントです。これ以降マウスボタンをあげるまで動かすことができるようになります。中身は、マウスカーソルの形を変更して動かせるようにユーザーにわかってもらえるようにして、クリックされたダイアログのオブジェクトを①で用意した変数に代入しています。同様にイベントの位置も変数に代入しています。

は、実際にダイアログを動かしている部分でスタイルの位置指定をマウスを動かした分量だけ変化させています。if( e )else if( event )は、ブラウザごとに位置の算出方法を変えているということになります。

は、マウスボタンを離してダイアログの移動を終了させるときに呼び出されます。中身は、マウスカーソルを通常の状態に戻して、覚えていたダイアログのオブジェクトをクリアしています。

は、この画面が表示されたときに呼び出される関数で、標準のイベントハンドラを定義している関数に置き換えています。最初の2つは、ダイアログのタイトル部分でマウスが押されたときのイベントを置き換えています。

は、実際にこの画面が表示されたときに⑤を呼び出すための関数になります。

前回と同様に1つにまとめたサンプルになります。

という感じで、スタイルシートとJavaScriptでウインドウを画面内に作成してそれを動かすということができるようになりました。 中身を知らないと難しい気がしますが実際にやってみるとそんなには難しいことは行っていません。あとは、いろいろ試してみてください。

| | コメント (0) | トラックバック (0)

2006年10月17日 (火)

[CSS]スタイルシートだけでふちを丸くするタブを作る

よくタブのUIを作るときに左右に丸いふちの画像を配置してそれにはさむように文字を書き込みますが、divタグとそれに対するスタイルを指定することによりタブ見たいなUIを作ることができます。

たとえば

こんな感じになります。

これを複数使うことで画像を使わないタブができます。

タブ2

あとは、スタイルの色に変化をつけることで選択されているタブかどうかとか利用できるかどうかといったことが簡単にできます。

やっていること自体は、表示する領域の大きさをちょっとづつ変化させていってそれの背景色やふちに色をつけていくという単純なものです。

<div style="FLOAT: left; WIDTH: 5em; MARGIN-RIGHT: 5px">
<div style="TEXT-DECORATION: none">
  <div style="BORDER-RIGHT: gray 1px solid; BORDER-TOP: gray 1px solid; MARGIN: 0px 5px; OVERFLOW: hidden; BORDER-LEFT: gray 1px solid; HEIGHT: 1px; BACKGROUND-COLOR: #f0eee4"></div>
  <div style="BORDER-RIGHT: gray 1px solid; MARGIN: 0px 3px; OVERFLOW: hidden; BORDER-LEFT: gray 1px solid; HEIGHT: 1px; BACKGROUND-COLOR: #f0eee4"></div>
  <div style="BORDER-RIGHT: gray 1px solid; MARGIN: 0px 2px; OVERFLOW: hidden; BORDER-LEFT: gray 1px solid; HEIGHT: 1px; BACKGROUND-COLOR: #f0eee4"></div>
  <div style="BORDER-RIGHT: gray 1px solid; MARGIN: 0px 1px; OVERFLOW: hidden; BORDER-LEFT: gray 1px solid; HEIGHT: 2px; BACKGROUND-COLOR: #f0eee4"></div>
  <div style="BORDER-RIGHT: gray 1px solid; PADDING-RIGHT: 1px; PADDING-LEFT: 1px; PADDING-BOTTOM: 1px; BORDER-LEFT: gray 1px solid; PADDING-TOP: 1px; WHITE-SPACE: nowrap; BACKGROUND-COLOR: #f0eee4; TEXT-ALIGN: center">
   <a href="#" style="FONT-SIZE: 0.9em">タブ1</a>
  </div>
</div>
</div>

先頭にあるdivタグの『float』は、続けて作成するタブを左側に持っていくためにあり、そのほかのスタイルの属性はタブの大きさとタブ同士の間隔を決めています。文字が多い場合などは、widthの値を増やせばタブが大きくなっていきます。

これの応用で、

タブ2

といった丸い表示領域を作成することができます。これは文字を表示するところまでは同じで、表示した後でdivタグの順番を逆に繰り返すということでできちゃいます。

スタイルの変更だけでいろいろできるので、JavaScriptで色を変更させたり、疑似クラスのhover(マウスが表示領域の上に来た場合)やactive(マウスをクリックした場合)を利用して動的なページを作ることができます。

| | コメント (0) | トラックバック (0)

2006年10月16日 (月)

[JavaScript]JSONでのデータの受け渡し

今日は、開発ねたで。

Webアプリケーションの開発を行っていますが、当然のように最近流行のAjaxを使用しています。その中で簡単なものは、サーバーからHTML形式のデータを送信して指定された場所に表示するというコードを利用します。(データのやり取りには、prototype.jsを使用しています。日本語の解説は、こちら

<html> <body>

<div id="view"></div>

<script language="javascript" type="text/javascript">
<!--
function get_data()
{
  var url = '/calc.html';
  var post_params = 'a=10&b=20';

  var ajax = new Ajax.Request( url, { method: 'post', postBody: post_params, onComplete: view_data} );
}

function view_data( res )
{
  // エラー処理

  // 結果の表示
  document.getElementById( 'view' ).innerHTML = res.responseText;
}

//--> </script>

XMLでデータをやり取りするのが本来のAjaxのX部分なのですが、中身を加工するのにそれなりに面倒な処理を行う必要があります。
そこで簡単にデータのやり取りができるJSON (JavaScript Object Notation)という形式を用いて行うと簡単に受け取ったデータをJavaScript内でオブジェクトとして取り扱うことができるようになります。詳しい解説は、ググッてください。

簡単に説明すると

{ "user":
  {
    "name":"shima",
    "age":"37"
  }
}

というデータを返すようにサーバが実装されている場合にAjaxでデータを受け取ったあとで

person = eval( "(" + res.res.responseText + ")" );

alert( person.name ); // shimaが表示される
alert( person.age);  // 37が表示される

という感じに簡単に受け取ったデータの操作ができるようになります。
ここで私がはまったのは、eval関数を使用するときに単純に

person = eval( res.res.responseText );

としたところきちんとオブジェクトにはなりませんでした。そこで受け取ったデータを『()』でくくるとうまくオブジェクトにすることができました。

person = eval( '(' + res.res.responseText + ')' );

eval関数を利用するときに注意しなければならないのは、受け取った文字列を単純にJavaScriptのソースとして評価してしまうので危険なデータがサーバーから送られてきた場合にセキュリティの問題が発生してしまいます。もし信頼の置けないような場合は、JSON parserを使用するなど安全には、注意してください。

ちなみにJSONは、RFC 4627として2006年7月に登録されています。

[追記 2006/10/26 15:01]
JSONでデータを渡すときの注意点ですが、オブジェクト同士を区切る「,」が一番最後のデータについているとevalで評価されずにオブジェクトにならないので気をつけてください。

| | コメント (0) | トラックバック (1)