IE の showModalDialog と初期フォーカス

IE の showModalDialog で開いたウィンドウは、 先頭のリンクやフォームに、 自動的にフォーカスがセットされてしまいます。

ページが読み込まれたときに 下のようになります。

WRITE_0775_01

この状態で [Enter]キーを押すと、 当然このリンクをクリックしたことになってしまいます。 また、JavaScript で

window.scrollTo(0, xx);

のようなスクロール操作を行っても フォーカスがセットされたオブジェクトが 隠れるようなスクロールはさせてくれません。

対処方法の 1つとして、 次のように showModalDialog で開いたウィンドウの onload イベントで、 ウィンドウ全体にフォーカスを当て直します。

  <script>
      if (window.attachEvent) {
          window.attachEvent("onload", function() {
                  window.focus();
              });
      }
  </script>
</body>
</html>

IE 用の対策なので window.attachEvent を使用しています。


        

WRITE_0775_02

これで、フォーカスが解除されます。

JavaScript の +new Date()

var s = +new Date();

こんな記述があったので「何だろう?」と思ってやってみると 数値が返ってきました。

どうやら .getTime() と同じものを返しているようです。

var s = +new Date();
var s = (new Date()).getTime(); // 同じ

調べてみると + を付けた場合 .valueOf() が呼ばるそうです。

[参考]
JavaScript の算術演算子と数値変換 - Togetter

実験。

var obj = {
    toString : function () {
        return "ABC";
    },
    valueOf : function () {
        return 123;
    }
}

window.alert(obj);  // →ABC
window.alert(+obj); // →123

つまり ↓ ということになります。

var s = +new Date();
var s = (new Date()).valueOf(); // 同じ
var s = (new Date()).getTime(); // 同じ

node.js で CoffeeScript を試してみる 1

以前「CoffeeScript を試してみる」というネタを書きましたが CoffeeScript は node.js で使うことができるので node.js に入れて試してみます。

まずはグローバルインストール。

$ sudo npm install -g coffee-script

CoffeeScript のソースを書きます。

$ vi test.coffee
alert "hello"

こんな感じ。

CoffeeScript が 全然わからない、って人は 下のサイトが参考になると思います。

[参考]
CoffeeScriptってなんぞ?

コンパイルすると js ファイルができます。

$ coffee -c test.coffee

できた js ファイルを見てみます。

$ cat test.js
(function() {

  alert("hello");

}).call(this);

ちゃんと JavaScript になってました。

CoffeeScript を試してみる

以前、HTML5 など勉強会で紹介された CoffeeScript を試してみます。 CoffeeScript は JavaScript を書くためのスクリプトです。

CoffeeScript を使うメリットは次のような感じです。

  • お決まりの呪文を書く量が減る
  • 人ごとのブレが少なくなる
  • 知識が少なくても「よく落ちる穴」に落ちにくくなる

勉強会では次のサイトが紹介されていました。

[参考]
ちっちゃいCoffeeScriptの本

CoffeeScript は Node.js の拡張で 簡単に試せないのですが 本家のサイトに行くとブラウザ上で試すことができます。

[参考]
CoffeeScript

上記サイトの上部メニューにある「 TRY COFFEESCRIPT 」をクリックすると ウィンドウが表示されるので、左側に CoffeeScript を記述すると右側にコンパイルされた JavaScript が 出力されます。

実際に試してみます。

[CoffeeScript]
alert "success"

  ↓

[JavaScript]
alert("success");

まず、カッコを省略することが出来ます(カッコがないとわかりにくくなる場合は付けます)。 セミコロンも省略できます。

[CoffeeScript]
alert "success" if document? 

  ↓

[JavaScript]
if (typeof document !== "undefined" && document !== null) {
  alert("success");
}

オブジェクトの存在判定が ? だけで記述できます。 この辺りは言語仕様を知らないと難しいですし ハマりやすいところですね。

[CoffeeScript]
if check()
  run1()
  run2()
else
  run3()

  ↓

[JavaScript]
if (check()) {
  run1();
  run2();
} else {
  run3();
}

ブロックは Python のようにインデントで表現します。 ブロックの開始カッコの位置とかブレやすいところですね。

ブラウザ上でそのまま使えないと普及は難しいと思いますが 柔軟な言語仕様に手を入れず、外から整えるやり方は好きです。

oncopy oncut onpaste

次のように“確認用メールアドレス”がある場合で 「確認用なのにコピー&ペーストをされては意味がない」と思うことがあります。

メールアドレス
確認用メールアドレス

そんなときにテキストボックスに oncopy oncut onpaste のイベントを設定して コピー、カット、ペーストを禁止することができます。

次のように定義します。

<input type="text" name="mailaddress"
       oncopy="return false"
       oncut="return false"
       onpaste="return false">

警告を出すこともできます。

<input type="text" name="mailaddress"
       oncopy="alert('コピー禁止');return false"
       oncut="alert('カット禁止');return false"
       onpaste="alert('ペースト禁止');return false">

次のようになります。

メールアドレス
確認用メールアドレス

JavaScript ですし、根本的な対策にはならないですが 覚えておくと何かのときに役に立つかもしれません。

Firefox で「戻る」したときも JavaScript を実行させる

Internet Explorer (6) では、前のページから戻った場合も JavaScript を再実行します。

例えば、次のようなスクリプトがある場合、 このページに「戻る」したときも、表示される時刻は更新されます。

document.write("<p>");
document.write(new Date());
document.write("<\/p>");

確認用デモ

しかし Firefox (3.6) では、スクリプトの状態を保存しているためか 再実行されません。

ところが、window.onunload を何か定義してやると 再実行されるようになります。

例えば、次のようなに window.onunload を足すと Firefox (3.6) でも時刻が更新されるようになります。

document.write("<p>");
document.write(new Date());
document.write("<\/p>");

window.onunload = function () {}

確認用デモ

ここでは window.onunload 空の関数をセットしていますが、内容のあるものでも OK です。

Google AJAX Language API を使ってみる

以前、Google Chart API を紹介しましたが Google は、他にも API を無料提供しています。

そのひとつに Google AJAX Language API があります。 これは AJAX を使った非同期の翻訳 API です。

これを使って簡単なサンプルを作ってみました。

アイデア次第で、いろいろできそうです。

QuickFlip 2 を 試してみました。

QuickFlip 2 は JQuery のプラグインで、 簡単にパネルをめくるような動きを作ることができます。

こちら を参考にして サンプルを作ってみました。

最近は JQuery だな、と思いつつ作ってみたのですが とにかく簡単でした。 基本的に、外部 js ファイルの読込と 次の HTML の 記述だけで OK です。 (枠線や背景などは必要に応じて)

<div class="quickFlip">
  <div class="front">
    [表]
    <a href="#" class="quickFlipCta">click to flip</a>
  </div>
  <div class="rear">
    [裏]
    <a href="#" class="quickFlipCta">click to flip</a>
  </div>
</div>

<script type="text/javascript">
  $(function() {  
      $('.quickFlip').quickFlip();  
  });  
</script>

☆評価

Amazon での本の評価など、★★★☆☆ のように☆で表す場合があります。 以前、☆ 4.5 のように小数点も可で、 動的なものを JavaScript で作ったサンプルがでてきたので 倉庫代わりに上げておきます。

このサンプルを、今のサイトに上げるときに Firefox 絡みで 1 つ ハマったことがあります。

次のように オブジェクトの width に値を設定しているのですが

with (document.getElementById('xxx')) {
    style.width = size;
}

Firefox は、標準モードではオブジェクトの width height の 値は設定できない(エラーになる)のでした。

次のようにしたら OK になりました。

with (document.getElementById('xxx')) {
    style.width = size + 'px';
}

作ったときは、互換モードだったので気づいていませんでした。

ブレゼンハムのアルゴリズム

ブレゼンハムという直線描画のアルゴリズムがあります。

過去に作った HTML などを整理していたら 昔これを教えてもらったときに JavaScript で作った サンプルが出てきたので 倉庫代わりに サイトに上げておきます。

ユークリッドの互除法による最大公約数・最小公倍数

ユークリッドの互除法とは、2つの自然数の最大公約数を求める場合に 大きい方から小さい方を引き、さらに小さい方から引いてできた数を引く処理を繰り返して、 引く数と引かれる数が同じになったとき、それが最大公約数であるというものです。

これを使うと引き算だけで最大公約数を求めることができます。

具体的には次のようになります。

45 と 33 の 最大公約数を求める

45 - 33 = 12
     33 - 12 = 21
          21 - 12 = 9 ( 21 > 12 )
               12 - 9 = 3
                    9 - 3 = 6
                        6 - 3 = 3 ( 6 > 3 )
                            3 - 3 = 0 <---- 3 が最大公約数

これを JavaScript で書くと次のようになります。

function gcd(a, b) {
    return (a == b) ? a : gcd(Math.abs(a - b), (a > b) ? b : a);
}

ちなみに 上の例では何度も 3 を引いていますが 大きい方から小さい方を引くのではなく、 割った余りを求める方法だと もっと簡単になります。

次に最小公倍数ですが 最大公約数と最小公倍数には、下のような関係があります。

a × b = aとbの最大公約数 × aとbの最小公倍数

つまり最大公約数がわかれば最小公倍数は計算できるので 次のような JavaScript で最小公倍数が求められます。

function lcm(a, b) {
    return a * b / gcd(a, b);
}

gcd() は、先ほど作った最大公約数を求める関数です。

JavaScript などのように 標準で最大公約数・最小公倍数を求める関数を持っていない言語を 使うときに これを知ってるとちょっと便利です。

フォーム内の同名エレメントが単数/複数になる

新人さんから質問されたのでメモを書いておきます。

HTML の フォーム内に 同じ名前でエレメントが 1つだったり 複数だったりすることがあるそうです。 そんな場合は、次のような "document.FORM.ELEMENT" 指定だと if 文等で分岐させなくてはなりません。

if ( 1 つのとき ) {
    window.alert( document.FORM.ELEMENT.name );
} else {
    for ( var i = 0; i < document.FORM.ELEMENT.length; i++ ) {
        window.alert( document.FORM.ELEMENT[i].name );
    }
}

1 つの案として document.getElementsByName() を使う方法があります。

var objs = dicument.getElementsByName("element");
for ( obj in objs ) {
    window.alert( obj );
}

document.getElementsByName() は、エレメントが 1 つでも複数でも 配列で返してくれるため分岐が不要になるのです。