calendar_viewer で表示した複数の記事中に comment プラグインが使われていると、フォーム中の "msg" および "name" に設定された id が重複してしまい、XHTML 1.1 invalid になってしまう。
calendar_viewer.inc.php 160行付近
// $limit_page の件数までインクルード $tmp = max($limit_base, 0); // Skip minus while ($tmp < $limit_page) { if (! isset($pagelist[$tmp])) break; $page = $pagelist[$tmp]; $get['page'] = $post['page'] = $vars['page'] = $page;
$vars['page'] にインクルードする記事名をセットしている。
comment.inc.php 90行付近
function plugin_comment_convert() { global $vars, $digest, $_btn_comment, $_btn_name, $_msg_comment; static $numbers = array(); static $comment_cols = PLUGIN_COMMENT_SIZE_MSG; if (PKWK_READONLY) return ''; // Show nothing if (! isset($numbers[$vars['page']])) $numbers[$vars['page']] = 0; $comment_no = $numbers[$vars['page']]++;
$vars['page'] をキーにして$comment_noをセットしている。
$comment_no はその後 id の生成に利用している。
comment.inc.php の挙動は、同一ページ内に複数の #comment があっても id が被らないようにしている。
calendar_viewer を使用すると、親ページ内に複数の子ページが存在するイメージとなり、子ページ内での整合性は保たれるものの、子ページ間での競合が避けられない。
label要素(に限らず、(x)htmlすべて)におけるid属性は、(x)html文書内で一意で無ければならない。
calendar_viewer.inc.phpは1つの(x)html文書内に複数のページ(wiki)を表示しようとする。
comment.inc.phpにおける$comment_no変数は、(x)html文書内での表示位置/順序に係わらず、ページ(wiki)内での出現順で普遍の一意の値で無ければならない。
管理の基準となる対象が違う二つの要素を一つの変数で管理しようとしているところに問題がある。
input要素中の id は、label要素との紐付けのためだけに使われており、プログラム的には何ら意味の無い値である。
commentプラグインにて、idの生成にはページ名に拠らず出現回数のみを拠り所にする変数を新設して、それを使うように修正することでこの問題は解決できる。
comment.inc.php
function plugin_comment_convert() { global $vars, $digest, $_btn_comment, $_btn_name, $_msg_comment; static $numbers = array(); + static $commentnums = 0; static $comment_cols = PLUGIN_COMMENT_SIZE_MSG; if (PKWK_READONLY) return ''; // Show nothing if (! isset($numbers[$vars['page']])) $numbers[$vars['page']] = 0; $comment_no = $numbers[$vars['page']]++; + $commentnums++; $options = func_num_args() ? func_get_args() : array(); if (in_array('noname', $options)) { - $nametags = '<label for="_p_comment_comment_' . $comment_no . '">' . + $nametags = '<label for="_p_comment_comment_' . $commentnums . '">' . $_msg_comment . '</label>'; } else { - $nametags = '<label for="_p_comment_name_' . $comment_no . '">' . + $nametags = '<label for="_p_comment_name_' . $commentnums . '">' . $_btn_name . '</label>' . '<input type="text" name="name" id="_p_comment_name_' . - $comment_no . '" size="' . PLUGIN_COMMENT_SIZE_NAME . + $commentnums . '" size="' . PLUGIN_COMMENT_SIZE_NAME . '" />' . "\n"; } (中略) <input type="hidden" name="digest" value="$digest" /> $nametags - <input type="text" name="msg" id="_p_comment_comment_{$comment_no}" size="$comment_cols" /> + <input type="text" name="msg" id="_p_comment_comment_{$commentnums}" size="$comment_cols" /> <input type="submit" name="comment" value="$_btn_comment" />
そもそもlabel要素が不要ではないか。
label要素は、input要素の type="radio" や type="checkbox" 等でユーザビリティの向上を図る目的で使われるのだが、type="text" ではそれほどユーザビリティの向上には貢献しない。
そこで、label要素を廃止して、id 自体を不要にしてしまうことで問題の解決を図る。
comment.inc.php
function plugin_comment_convert() { global $vars, $digest, $_btn_comment, $_btn_name, $_msg_comment; static $numbers = array(); static $comment_cols = PLUGIN_COMMENT_SIZE_MSG; if (PKWK_READONLY) return ''; // Show nothing if (! isset($numbers[$vars['page']])) $numbers[$vars['page']] = 0; $comment_no = $numbers[$vars['page']]++; $options = func_num_args() ? func_get_args() : array(); if (in_array('noname', $options)) { - $nametags = '<label for="_p_comment_comment_' . $comment_no . '">' . - $_msg_comment . '</label>'; + $nametags = $_msg_comment; } else { - $nametags = '<label for="_p_comment_name_' . $comment_no . '">' . - $_btn_name . '</label>' . - '<input type="text" name="name" id="_p_comment_name_' . - $comment_no . '" size="' . PLUGIN_COMMENT_SIZE_NAME . + $nametags = $_btn_name . '<input type="text" name="name" size="' . PLUGIN_COMMENT_SIZE_NAME . '" />' . "\n"; } (中略) <input type="hidden" name="digest" value="$digest" /> $nametags - <input type="text" name="msg" id="_p_comment_comment_{$comment_no}" size="$comment_cols" /> + <input type="text" name="msg" size="$comment_cols" /> <input type="submit" name="comment" value="$_btn_comment" />
PukiWikiで label 要素を使用しているソースは、comment.inc.php を除いて14個ある。
以下未調査
--- <input type="text" name="msg" id="_p_comment_comment_{$comment_no}" size="$comment_cols" /> +++ <input type="text" name="msg" size="$comment_cols" />
<label for="_p_comment_name_0">お名前: </label><input type="text" name="name" id="_p_comment_name_0" size="15" />こういう感じで。
お名前: <input type="text" name="name" size="15" />こうするのが妥当でしょうかね。現にpcommentなんかはlabel要素使っていませんし -- Makichan 2007-10-11 (木) 20:28:05