手描きからGIMP用作業ファイルに変換

クリップアートを公開するサイトを作ってみた。普段しているどうでもいいラクガキを、何か再利用できる形にしてみようかなと思ったので。

(サイトはある程度できていて、こんな感じになっている。)

まず、適当な紙に描きなぐったラクガキを…
f:id:yamatt2:20140215094219j:plain

普通にスキャンする。自炊用に持っている連続スキャナにポンと突っ込むだけなので楽。

スキャナを接続しているコンピュータと、それ以降の処理をするコンピュータがたまたま別なのだけど、dropboxを使って同期させれば何ら気にならない。

スキャナの仕様では、モノクロのjpeg画像として取り込むようになっている。クリップアートとして扱いやすくするには透過PNGがいいと思ったので、それを目指してGIMPで処理する。

GIMPでやることは、

  • jpeg画像を取り込んで、輪郭をはっきりさせるために二値化処理する。
  • 二値化の結果白(つまり輪郭以外)になったところを、色選択して透明に直す。
  • 輪郭レイヤの下に着色用の不透明レイヤをひとつ敷き、背景っぽい灰色で塗りつぶす。

こんなもの。何度も行うためにscript-fuを書いたが、大体下のようになる。

(define (script-fu-prepare-for-clipart in-filename out-filename)
  (let* (
    (image-id (car (file-jpeg-load 0 in-filename in-filename)))
    (layer-width (car (gimp-image-width image-id)))
    (layer-height (car (gimp-image-height image-id)))
    (drawable-id (vector-ref (cadr (gimp-image-get-layers image-id)) 0))
    (layer-id (car (gimp-layer-new image-id layer-width layer-height 0 "background" 100 0)))
    )

    (if (= 1 (car (gimp-drawable-is-gray drawable-id)))
        (gimp-image-convert-rgb image-id))
    (gimp-threshold drawable-id 157 255)
    (gimp-layer-add-alpha drawable-id)
    (gimp-image-select-color image-id 2 drawable-id "white")
    (gimp-edit-cut drawable-id)
    (gimp-selection-none image-id)
    (gimp-layer-set-name drawable-id "outline")
    (gimp-context-set-background '(230 230 230))
    (gimp-drawable-fill layer-id BACKGROUND-FILL)
    (gimp-image-insert-layer image-id layer-id 0 1)
    ;(gimp-display-new image-id)
    (gimp-xcf-save 0 image-id layer-id out-filename out-filename)
))


(script-fu-register "script-fu-prepare-for-clipart"
  "prepare for clipart..."
  "Load jpeg and save to something"
  "yamamoto tetsuya<mymailaddress@gmailorsomething.com>"
  "yamamoto tetsuya"
  "2013"
  ""
  SF-FILENAME  "Input file name" ""
  SF-STRING  "Output file name" ""
)

;; GIMPのGUIから動作を試してみたければ、下をコメントアウト
;;(script-fu-menu-register "script-fu-prepare-for-clipart"
;;                         "<Image>/File/Create")

この関数は、入力ファイル名(jpeg画像)と出力ファイル名(GIMP用ファイル)を受け取って動作する。コマンドラインから扱いたければ、

gimp -i -d -f -b '(script-fu-prepare-for-clipart "ファイル名1" "ファイル名2")' -b '(gimp-quit 0)'

とかそんな感じに実行する。直接叩いてもいいし、別のプログラムからサブプロセスとして叩いてもいい。

ところで、あとでこのGIMP用画像に着色したあと、作業用のpng画像に一旦変換することも必要になるので、同様にscript-fuを書いた。GIMP用ファイルを開き、レイヤをすべて統合したpngファイルに落とすだけのもの。

(define (script-fu-prepare-for-clipart2 in-filename out-filename)
  (let* (
    (image-id (car (gimp-xcf-load 0 in-filename in-filename)))
    (drawable-id (car (gimp-image-merge-visible-layers image-id 0)))
    )
    (file-png-save 1 image-id drawable-id out-filename out-filename 0 1 0 0 0 0 0)
))

(script-fu-register "script-fu-prepare-for-clipart2"
  "prepare for clipart (2)..."
  "Load xcf and save as png"
  "yamamoto tetsuya<mymailaddress@gmailorsomething.com>"
  "yamamoto tetsuya"
  "2013"
  ""
  SF-FILENAME  "Input file name" ""
  SF-STRING  "Output file name" ""
)

;; GIMPのGUIから動作を試してみたければ、下をコメントアウト
;;(script-fu-menu-register "script-fu-prepare-for-clipart2"
;;                         "<Image>/File/Create")

これら二つのscript-fuは、適当な名前でひとつのファイルにまとめて、GIMPスクリプトフォルダに放り込んでおけば使える。

これが、着色作業中のGIMPの画面で…
f:id:yamatt2:20140215100129j:plain

これが、できあがる実際のPNG画像の一部。
f:id:yamatt2:20140215100404j:plain

クリップアートを切り抜くための目印を含む着色のルールをつくったのだけど、これは次回に書く。

perlin noiseをPILでつくった

※いまさらながら、これって全然パーリンノイズじゃないよね。2018.5.29

パーリンノイズ(perlin noise)ってやつを作ってみたいなと思っていたが、道具さえ選べば簡単だった。

まじめにやると、画像の補間法をちゃんと勉強しなければいけないんだけど、pythonのPILモジュールは画像の拡大にバイキュービック法が使えるようだったので、これを活用するとよい。

まず、2x2ピクセルのモノクロ画像をつくり、全ピクセル(といっても4つ)を0から255のランダムな明度で埋める。そののち、適当なサイズに拡大する。このときの拡大はバイキュービック法で。できる画像は下のとおり。

f:id:yamatt2:20140213101052p:plain

次に、4x4ピクセルのモノクロ画像をつくって、同じようなことをしてから、さっきと同じサイズに拡大する。

f:id:yamatt2:20140213101104p:plain

次に8x8。

f:id:yamatt2:20140213101112p:plain

16x16、32x32、64x64… と、順々に同様の画像をつくる。すこしづつ、画像を暗くしていくのがミソ。つまり、はじめは0から255の明度にしたけど、次は0から216、次は0から183まで…といったように、暗めの範囲を使うようにしていく。

f:id:yamatt2:20140213101120p:plain
f:id:yamatt2:20140213101127p:plain
f:id:yamatt2:20140213101131p:plain
f:id:yamatt2:20140213101140p:plain
f:id:yamatt2:20140213101144p:plain

最後にこれらの明度をすべて足し合わせた画像をつくればできあがり。単純に足せば明度は255を振り切ってしまうので、明度を足し合わせた結果をさらに0から255の範囲にとどまるように調整することが必要だけど。

f:id:yamatt2:20140213101203p:plain

スクリプトは下のよう(要PIL)。動作の調整には、size変数に最終的に作りたい画像サイズ(縦横同じ)、ampd変数に明度の減衰率をセットする程度。

#
# Generate Perlin noise
#

import random
from PIL import Image

size = 256
amp = 255
ampd = 0.85

buf = [[0 for _ in xrange(size)] for _ in xrange(size)]

o = 2
oa = [o,]
while o < size:
  o *= 2
  oa.append(o)

for x in oa:

  # generate seed image with random pixels
  img = Image.new("L", (x, x))
  px = img.load()
  for i in xrange(x):
    for j in xrange(x):
      px[j, i] = random.randint(0,amp)

  # magnify seed image (using any interpolation)
  img2 = img.resize((size,size), Image.BICUBIC)
  px2 = img2.load()
  for i in xrange(size):
    for j in xrange(size):
      buf[j][i] += px2[j,i]

  amp = int(amp * ampd)

mx = max([max(i) for i in buf])
mn = min([min(i) for i in buf])

img3 = Image.new("L", (size,size))
px3 = img3.load()
for i in xrange(size):
  for j in xrange(size):
    c = int((buf[j][i]-mn) * 255 / (mx-mn))
    px3[j,i] = c

img3.save("perlin.png")

JavaScriptの実用例(5)

ドキュメントの内容を変化させるようなJavaScriptは、ページの最後の方で実行させたほうがよいという話までしました。

ですが、管理上、JavaScriptはすべてページの冒頭に記しておきたいという要求もあるはずです。JavaScriptをHTML文書のそこらへんにバラバラと書いてあると、あとで困ることも多くなりがちですから。とはいえ、ページの冒頭で、まだ表示もされていない要素のinnerHTMLを操作しようとしてもうまくいかないわけですから、どうしたらよいでしょう。

こういうときは、スクリプトが実行されるタイミングを指定しておけばよいです。具体的には、ページがすべてロードされ終わったら、その時点ではじめて一連の命令を実行してくれるように予約しておけばいいというわけです。

下のような書き方をします。

<script>
function do_something() {
  var a = document.getElementById('add1');
  a.innerHTML = '<table border="1"><tr><td bgcolor="yellow">AD here!</td></tr></table>';
}
window.onload = do_something;
</script>

functionは、一連の命令を「関数」という名前のものに仕立てて、あとでまとめて実行できる形にするためのものです。このfunction文そのものを実行(実行っていう言葉はここでは不正確なんですけど)している時点では、何も起こりません。あとで do_something っていう関数を別に呼び出したときに、はじめてこの関数の内容が実行されます。

window.onloadは、ページを全部ロードし終わったときに何かをさせたいときの書き方です。ここでは、「(今は何もしないけど)ページを全部ロードし終わったときにはdo_something関数を実行してね、ということを表現しています。

こういう書き方のスクリプトなら、ページの冒頭に書いておいても大丈夫です。

(実際のサンプル)

window.onloadのような仕組みを使って、「何かが起こった時に、何かをする」という動作をさせることを、「イベント駆動」といいます。今のサンプルのようなのは、ページのロードが終わったというイベントに反応して何かをした、と言い直せます。他にもWebブラウザ上で起こるイベントはいろいろあって、マウスボタンが押されたとき、要素の上にマウスカーソルが乗った時、キーボードが押されたとき、単に時間がたった時、と、様々なタイミングで「イベント」が起こっていて、それに反応するプログラムを書けるようになっています。

このwindow.onloadという書き方は、それなりに実用的に使えますが、ひとつ弱点があり、人によっては他の方法を好んで使うかもしれません。弱点というのは、window.onloadには関数をひとつしかセットできないとう点です。つまり、下のような書き方をしたときに問題になります。

<script>
window.onload = do_something;
window.onload = do_another_something;
</script>

このままだと、do_another_somethingだけが実行対象となり、その前に書いたdo_something関数は実行予約からは外れてしまいます。自分ひとりがJavaScriptを書くのなら、このふたつの仕事をさらに別の関数としてまとめてしまってそれを指定すればいいですし、別に大きな問題にはなりません。例えば下の通り。

<script>
function big_handler() {
  do_something();
  do_another_something();
}
window.onload = big_handler;
</script>

ですが、すでに誰かが書いたJavaScriptをそのページでは使用済で、さらに別の動作を付け足そうとしているときは、すでにどんなイベントに仕事が割り当て済みなものか、簡単に把握ができません。window.onloadイベントを気ままに書き換えてしまうと、すでに実現していたある機能が消えてしまうこともあるでしょう。

window.onloadを使うのは、実は少し旧式のやりかたなのです。addEventListenerというものを使えば上のような問題も起こさずにさらにスマートな書き方ができるのですが、某IEとの互換性について少し余計なことを考慮しなければなりませんし、この場ではこれ以上書きません。

ということで、JavaScriptを実用的に使うひとつの例として、ページ内容の一部をHTML直書きでなくJavaScriptに任せることについて、何回かに分けてざっと書きました。

JavaScriptの実用例(4)

JavaScriptで、document.writeを使ってページ内にコンテンツを追加することは、そこそこ便利ですが、気になることもあります。今まで、JavaScriptはページとは別に外部スクリプトとして使うのがいいということを示してきましたが、これのロードに時間がかかるときは、少し困ったことになります。

ページの途中に外部スクリプトのロード(読み込み)が指示されていて、その外部スクリプトを実際にWebサーバーから取得するのに5秒くらい時間がかかるとすると、その間、ページ表示が途中で止まります。わざわざ遅いWebサーバーを準備することもできませんから簡単にデモで示すことはできませんが、これを読んでいるかたも、割と経験はあるんじゃないでしょうか。典型的には、いくつかアフィリエイトや広告の外部コンテンツを埋め込んでいるようなサイトによくあります。広告って、たくさんのサイトに表示させる必要があるものですから、広告を配信するWebサーバーはすごく高い負荷に対応しなきゃいけないんだと思います。でも対応しきれなくて、サイトの表示全体が遅くなってしまう原因になっているんでしょう。

document.writeのように「今表示しようとしている場所」にHTMLを書き出すのじゃなくて、ほぼ全部のHTMLが表示され終わったあとで、決まった場所にあらためてHTML(の一部)を放り込むようなことができれば、上の原因からくる遅さは解消できます。広告などの表示には相変わらず時間がかかったとしても、メインのコンテンツが早く表示できるのならそっちのほうがいいですね。別に広告でなくても、そもそも負荷の高いWebサイトで外部スクリプトの提供も重くなりがち、というときも同様です。

それには、innerHTMLというものを使います。これはHTMLの構成要素ごとに持っているプロパティのようなもので、あとで値を設定しなおすと、実際の表示内容にも影響を与えることができるんです。たとえばこんなHTMLがあるとしましょう。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>page sample</title>
</head>
<body>
<div id="add1"></div>
<h1>なんとかかんとかのページです!</h1>
<p>なんとかかんとか・・・</p>

<script>
//上まで表示させてから、ここで何かする
</script>

</body>
</html>

スクリプトが実行されるタイミングでは、もうひととおりのコンテンツは表示されています。このタイミングでdivタグの中(今はからっぽ)に何か内容を放り込みたいな、というときに、下のように書きます。

<script>
//上まですでに表示されている。ここで何かする
var a = document.getElementById('add1');
a.innerHTML = '<table border="1"><tr><td bgcolor="yellow">AD here!</td></tr></table>';
</script>

(実際のサンプル)

上の例ではJavaScriptは外部化していませんが、実際のサンプルでは外部化しました。動作内容は変わりません。
内容を放り込んでおくために置いておくタグは、divにすることが多いです。なんの飾りもないブロック要素ですから、表示上のクセがなくていいのでしょう。また、そのタグにはid要素を定義しておくのがふつうです。ここではadd1という名前にしましたが、なんでもいいです。

そのタグが表す要素(DOMっていうんですが、別に知らなくてもいいです)を、document.getElementByIdっていう書き方で取得することができます。ここでは、aっていう変数がid="add1"に該当する要素を指し示すようにしました。あとは、a.innerHTMLっていうプロパティが、中身のHTMLを操作するための手掛かりです。好きなHTMLを文字列として突っ込めば、即座にその内容が実際の画面にも反映されます。

今回の例では決まったHTMLを設定しただけですが、この内容が、今までに見たことがある、カレンダーに反応して内容の変わるものだったり、占いみたいなものだったりしても、要領は同じです。

この手のスクリプトは、ページの最終部近くで実行させる必要があります。ページの最初で実行したら、まだその後の内容が表示されていないのですから、「idがadd1の何か」がまだ存在していないことになって、期待した動作になりませんからね。

ここらへんに注意すると、ページの内容をスクリプトで操作するという仕事が、割と安定してできるようになるでしょう。

JavaScriptで目次を自動生成する

FAQコーナーみたいなコンテンツを作っていて、内容は整備されてきたけど、目次も作らなきゃ、というときの話。

FAQの一問ずつは、h2タグで見出し、pタグで内容、といった感じだったとする。下みたいな。

<h2>質問1です。云々</h2>
<p>それへの回答は云々。</p>

<h2>質問2です。云々</h2>
<p>それへの回答は云々。</p>

ドキュメントの中のすべてのh2タグを集めて、それぞれその直前にリンク用のアンカータグを作って埋め込み、ページの初めにはそこへジャンプするaタグをリスト状に並べればいいわけだから…というわけで、下のようなコードを書いた。うまくいった。

// TOC auto generator
var generate_toc = function() {
  // 目次投入場所
  var toc = document.getElementById('toc');
  // 見出しを集める
  var headings = document.getElementsByTagName('h2');
  cn = [];
  cn.push('<ul>');
  for (var i=0;i<headings.length;i++) {
    var h = headings[i];
    // アンカータグを作って
    var d = document.createElement('a');
    var aname = 'a'+i;
    d.name = aname;
    // 各h2タグの直前に突っ込む
    h.parentNode.insertBefore(d, h);
    // 目次からそのアンカーにリンクを張る
    var s = '<li><a href="#' + aname + '">'+h.innerHTML+'</a></li>';
    cn.push(s);
  }
  cn.push('</ul>');
  toc.innerHTML = cn.join("");
}
generate_toc();

目次を表示させたい場所には、id=toc の空のdivタグを置いておくこと。generate_tocを呼び出すのは、bodyのロードイベントを捕まえて行うほうが多分適切。まあ、ページの終わりで呼び出してもちゃんと動くようだけど。

JavaScriptの実用例(3)

JavaScriptが、プログラム言語としてなにかまともな動作をし、それに従って面白い内容がdocument.writeするようにできると、JavaScriptを使う価値はちょっと上がります。前の回までは、お決まりの内容を書き出してくれるだけでしたからね。

たとえば、日によって違う内容を表示してくれるなんてのはどうでしょう。下のようなHTMLと外部スクリプトがひとつの例です。JavaScriptのくわしい書き方にはこの記事では触れませんが、なんとなくの雰囲気だけでも。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>日替わりメッセージのひながた</title>
</head>
<body>
<script src="./sample3.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
// これを sample3.js とします
var d = new Date();
var dd = d.getDate();
if (dd == 20) {
  document.write('給料日だ!');
} else {
  document.write('給料日がまだ来ない…');
}
document.close();

(サンプル)

こうすると、毎月20日だけは、アクセスしたときに「給料日だ!」という表示がページ内にあらわれ、それ以外は残念な表示が出てきます。JavaScriptはカレンダーを扱う機能を持っていますから、こんなことが可能なわけです。もうちょっと工夫すれば、日替わりメッセージなんかにも作り直すことができるでしょう。

または、下のようなのはどうでしょう。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>占いサービスのひながた</title>
</head>
<body>
<script src="./sample4.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
// これを sample4.js とします
var r = Math.random()
if (r < 0.2) {
  document.write('今日は大吉だ!');
} else if (r < 0.8) {
  document.write('今日はそこそこの日だ!');
} else {
  document.write('今日はもうだめだ!');
}
document.close();

これは簡単な占い機能です。JavaScriptは乱数を扱うことができますから、このスクリプトが実行されたときにまず0.0から1.0までの範囲を取る乱数を作り、それの値から判断して、5分の1の確率で大吉、5分の1の確率で凶、残りの確率で無難なメッセージを出すようなものにしてみました。もうちょっと豪華にいじりたくなるかもしれませんね。それもスクリプトがうまくなればいろいろできます。

ここで改めて確認ですが、これらのスクリプトはサーバー上ではなくてクライアント上、つまりお手元のWebブラウザ上で実行されます。だから、今日の日付に反応していろいろと起こるようなスクリプトは、手元のPCの時間に反応するわけです。わざと時間設定を間違えてみてから同じスクリプトを実行して確かめると、よくわかるはずですよ。

ところで、こういった方法だと、クライアント側ないしJavaScript側で知らない情報をもとにした表示ってのはできないことになります。例えば、施設の開館時刻と閉館時刻を毎日ページの一部分に表示したいときは、JavaScriptがクライアント側に渡ってしまってからいくら頑張っても、もとになる情報を知らないのだからそんなことはできません。(まあ、後に紹介するかもしれない、ちょっと高度な方法で可能にはなるんですけど。)

こういうときの解決策のひとつとして、JavaScriptを毎日だれかが作り変えてサーバーにアップする、というのもアリですが、そのうち手間がいやになってくるでしょう。

もうひとつの解決策としては、サーバー側で何かスケジュール実行できるようなプログラムをセットして、そのプログラム自身が定期的に新しいJavaScriptを生成する、という仕組みをつくることです。このプログラムは、JavaScriptでなくても構いません。ブラウザ上じゃなくて、サーバー上で動くんですからね。

例。たとえばこのプログラムはpythonで書いています。あと、部分的に疑似コードですので、実際には動作しません。

# JavaScriptを自動生成するプログラム。毎日午前1時に実行されること。
from datetime import datetime, timedelta

# データベースとかから、今日の開館時間情報を得る疑似コード
(open_today, close_today) = get_schedule(datetime.today())
# 同様に、翌日の開館時間情報を得る疑似コード
(open_tomorrow, close_tomorrow) = get_schedule(datetime.today() + timedelta(1))

script = """
document.write('本日の開館時刻は %s、閉館時刻は %s です。');
document.write('翌日の開館時刻は %s、閉館時刻は %s です。');
document.close();
""" % (open_today, close_today, open_tomorrow, close_tomorrow)

# JavaScriptの書き出し
open('/some/path/schedule_include.js', 'w').write(script)

できあがるJavaScriptは固定の内容を出力するだけのものなんですが、それ自身が毎日違うものに入れ替わるんですから、これでもいいわけです。サーバー側は、例えばデータベースなんかを持っていて、毎日何を出せばいいかという情報を知っているわけですから、それをJavaScriptに託してブラウザに送り届けるというイメージになりますね。

f:id:yamatt2:20131025210754j:plain

これを利用するHTMLは、まあそれほど今までと変わりませんし、実際に動くサンプルもありませんから、省略します。

この方法は、ある程度サーバー管理の権限がある人に限られるんですが、条件にあてはまれば、使えるときがあるでしょう。

JavaScriptの実用例(2)

前回、HTML文書の中にJavaScriptを混在させて、その実行結果がHTMLの一部になって表示に使われるという話をしました。

document.writeで出力する内容は、HTMLのタグが混じっていても大丈夫です。だから、下のようなものを書いても期待通りに動きますよ。Aタグの書き方は知っているという前提で、そこは詳しく説明しませんが。

<html>
<body>
hello
<script>
document.write('<a href="http://w3c.org/">world</a>');
</script>
how do yo do
</body>
</html>

(実際のサンプル)

でも、実際のところ、これだけでは大して役に立ちません。document.writeで決まった文字列を出力させるくらいなら、最初から全部HTMLで書いておけばよかっただけですからね。

このJavaScriptの部分を、別のファイルとして独立させてしまうと、ちょっとは役に立てられそうな気がしてきます。たとえば直前の例なら、下のような二つのファイルに分けてしまうんです。

<html>
<body>
hello
<script src="./sample2.js"></script>
how do yo do
</body>
</html>
// これを sample2.js とします
document.write('<a href="http://w3c.org/">world</a>');

ひとつめにはHTMLだけ、ふたつめにはJavaScriptだけ書かれています。そしてHTMLの途中には、「ここにはsample2.jsっていう外部スクリプトを読み込むよ」っていう意味のscriptタグが書いてあります。Webブラウザの上でHTMLのほうを表示させると、内部的にJavaScriptも指定位置に読み込まれて、その内容が実行されるというわけです。

実行結果は直前のと同じですが、一応見ておきましょう。(実際のサンプル)

もしもHTMLが割と大きなもので、毎日ちょっとだけ決まって更新される部分があるとします。たとえば何かの公共機関のページでも扱っていて、本日の開館・閉館予定時刻なんかをトップページの決まった位置に表示したくなったときなんかどうでしょう。制約条件として、トップページ自体は、PHPのようなものでなく、素のHTMLだとします。(トップページで、開館・閉館時間以外にろくな変化がないってのも例としてはおかしいんですが…)

そんな場合の対応策のひとつとして、HTML内の、新たに表示を足したい部分にscriptタグを書き足します。そして、それが読み込む外部JavaScriptには、例えば下のような命令が書かれているようにするわけです。

document.write('本日の閉館時間は、午後4時30分です。');

直す部分が大きなHTMLファイルでなく、とても小さいサイズのJavaScriptだけで済むわけですから、少し気楽になるでしょう? 大きなHTMLファイルを操作ミスで壊してしまうのは怖いですから、そこらへんも安心感が増します。ページ全体をPHPみたいなサーバーサイド生成のものに変更する必要も、ひとまずはなくなりました。

f:id:yamatt2:20131022211408j:plain

ところで、直前のJavaScriptの例は、日本語が混じっています。日本語をこうして扱うことは全く問題ありませんが、JavaScriptのファイルエンコーディングがちゃんと把握されているか、そこは少し注意が必要です。下のように、例えばsample3.jsという外部スクリプトを使おうとして、それがUTF-8エンコードされている場合は、明示的に下のように書くのが適切です。

<script src="./sample3.js" charset="utf-8"></script>

適切…といえば、今までの例で、単純に書こうとしていくつか適切さを犠牲にした部分がありましたので、そこは改めて書いておきます。

ひとつは、HTMLをもう少し丁寧に書いたほうがいい件。ちゃんとHTML宣言とかmetaタグとかtitleタグとかを書き足しておきましょう。文字のエンコーディングも、UTF8ならUTF8とはっきり宣言しておかなくてはいけません。

もうひとつは、scriptタグは、スクリプトの内容がJavaScriptであることを本来は明示しなければいけないこと。省略しちゃってもたいていは大丈夫なんですが、これも正しくは、type="text/javascript" という属性をちゃんとつけておくべきです。

もうひとつは、document.writeしたあとは、本来、document.closeで書き出し終了を宣言しなくてはいけない、とされている件。省略しちゃってもたいていは問題なく動くのですが、余計なトラブルで悩まないように、これも書き足しておくといいらしいです。だからJavaScriptを外部から読み込んで実行するHTMLと、そのJavaScriptのセットは、下のようにするのがより適切です。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>page sample</title>
</head>
<body>
hello
<script src="./sample2.js" type="text/javascript" charset="utf-8"></script>
how do yo do
</body>
</html>
// これを sample2.js とします
document.write('<a href="http://w3c.org/">world</a>');
document.close();

ちょっと七面倒な雰囲気になっていますが、本質はさっきまでの単純なやつと変わりません。いきなりこれ見ると、目がくらんでどこが重要かわかんなくなっちゃいそうでしたから。

さて、JavaScriptファイルだけをまめに更新することにしてちょっと楽できる、ということが実現できると、やがて次のような望みに育っていきます。すなわち、毎日お決まりの内容に更新されるような部分だったら、JavaScriptの内容に工夫を加えて、手で毎回更新するまでもなく、もっと自動的に賢い動作をするようにできないか、ということです。

JavaScriptは「プログラム言語」なんですから、当然そういったことがいろいろできますよ。

(つづく)