WP-Clumulus(3D タグクラウドを表示する Flash)を実装した後、ブラウザが IE(特に IE6)の場合、それ以前には出ていなかったスクリプトエラーが出るのに気がつきました。
スクリプトエラーは、外部スクリプトファイル recaptcha_ajax.js, blog.js, widget.js に定義されているメソッド等を参照できないというもので、そのため (1) Recaptcha の表示、(2) コメントの書き込み、(3) AMPL フィルターの起動、(4) Widget の移動、編集、削除ができませんでした。
いろいろと調べた結果、上記の外部スクリプトファイルを定義する script タグには defer="defer" 属性が追加されており、これと Flash Player 起動との関連で不具合が起きていることが分かりました。
defer="defer" 属性が追加されていると、当該スクリプトファイルの取得・解析を待たずに後続の HTML コードの解析・レンダリングが進められるそうです。その後 Flash Player が起動されると何かの不具合が起こり、IE のスクリプトエンジンが当該スクリプトファイルを取り込めなくなり(または解析できなくなり?)、それに定義されているメソッドを参照できなくなるようです。
対応策は、(a) Flash Player を起動しない、(b) defer="defer" 属性を削除する、(c) Flash Player を起動した後で defer="defer" 属性付の script タグを読むようスクリプトの順序を変更する・・・のいずれかになります。
検討の結果、(a) 案は 3D タグクラウドの実装を諦めるということなので問題外、(b) 案の defer="defer" 属性の削除は IE でレンダリングの遅れが目立つようになるので NG ということで、結局 (c) 案の対応を取りました。
recaptcha_ajax.js に対しては、RecaptchaControl.cs の RenderContents メソッドを書き換えました。問題のスクリプトのみ RegisterStartupScript メソッドを使用してページの最後に書き込むようにしました。コードは以下のとおりです。なお、この変更は reCaptcha を実装しなければ不要です。
protected override void RenderContents(HtmlTextWriter output)
{
output.AddAttribute(HtmlTextWriterAttribute.Id, "spnCaptchaIncorrect");
output.AddAttribute(HtmlTextWriterAttribute.Style, "color:Red;display:none;");
output.RenderBeginTag("span");
output.WriteLine("The captcha text was not valid. Please try again.");
output.RenderEndTag();
output.AddAttribute(HtmlTextWriterAttribute.Id, "recaptcha_placeholder");
output.RenderBeginTag(HtmlTextWriterTag.Div);
output.RenderEndTag();
string csname = "ReCaptchaEnablingScript";
Type cstype = this.GetType();
ClientScriptManager cs = Page.ClientScript;
if (!cs.IsStartupScriptRegistered(cstype, csname))
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<script type=\"text/javascript\"" +
"src=\"http://api.recaptcha.net/js/recaptcha_ajax.js\" defer=\"defer\"></script>");
sb.AppendLine("<script type=\"text/javascript\">");
sb.AppendLine("//<![CDATA[");
sb.AppendLine(" function showRecaptcha() {");
sb.AppendLine(" Recaptcha.create('" + publicKey + "', 'recaptcha_placeholder', {");
sb.AppendLine(" theme: '" + Theme + "',");
sb.AppendLine(" tabindex: " + TabIndex.ToString());
sb.AppendLine(" })");
sb.AppendLine(" }");
sb.AppendLine(" var rc_oldonload = window.onload;");
sb.AppendLine(" if (typeof window.onload != 'function') {");
sb.AppendLine(" window.onload = showRecaptcha;");
sb.AppendLine(" }");
sb.AppendLine(" else {");
sb.AppendLine(" window.onload = function() {");
sb.AppendLine(" rc_oldonload();");
sb.AppendLine(" showRecaptcha();");
sb.AppendLine(" }");
sb.AppendLine(" }");
sb.AppendLine("//]]>");
sb.AppendLine("</script>");
cs.RegisterStartupScript(cstype, csname, sb.ToString(), false);
}
}
blog.js, widget.js に対しては、widget.ascx, widget.ascx.cs を書き換えました。Flash 起動スクリプトを、タグクラウドをレンダリングする HTML コードの中に埋め込むように変更しました。コードは以下のとおりです。なお、これは 3D タグクラウドを実装するには必須です。
widget.ascx
<%@ Control Language="C#"
AutoEventWireup="true"
CodeFile="widget.ascx.cs"
Inherits="widgets_Tag_cloud_widget" %>
<div id="wpcumulusflashcontent">
If you see this Flash Player (Ver. 10 or better)
and/or JavaScript are/is not available in your PC.
</div>
<asp:Literal id="Literal1" runat="server"></asp:Literal>
<ul runat="server" id="ulTags" />
widget.ascx.cs
public override void LoadWidget()
{
string root = BlogEngine.Core.Utils.AbsoluteWebRoot.ToString();
StringBuilder sb = new StringBuilder();
sb.Append("<tags>");
foreach (string key in WeightedList.Keys)
{
string path = "?tag=/" + Utils.RemoveIllegalCharacters(key);
HtmlGenericControl li = new HtmlGenericControl("li");
li.InnerHtml = string.Format(LINK,
Utils.RelativeWebRoot + path, WeightedList[key],
"Tag: " + key, key);
ulTags.Controls.Add(li);
string size = "10";
switch (WeightedList[key])
{
case "biggest":
size = "13";
break;
case "big":
size = "12";
break;
case "medium":
size = "11";
break;
case "small":
size = "10";
break;
case "smallest":
size = "9";
break;
default:
size = "10";
break;
}
sb.Append(String.Format("<a href='{0}' style='{1}'>{2}</a>", root + path, size, key));
}
sb.Append("</tags>");
StringBuilder cs = new StringBuilder();
cs.AppendLine("<script type=\"text/javascript\">");
cs.AppendLine("//<![CDATA[");
cs.AppendLine("var so = new SWFObject(\"/BlogEngine/tagcloudUnicode.swf\", \"tagcloud\", \"180\", \"170\", \"10\", \"#ffffff\");");
cs.AppendLine("so.addParam(\"wmode\", \"transparent\");");
cs.AppendLine("so.addVariable(\"mode\", \"tags\");");
cs.AppendLine("so.addVariable(\"tcolor\", \"0x333333\");");
cs.AppendLine("so.addVariable(\"tcolor2\", \"0x333333\");");
cs.AppendLine("so.addVariable(\"hicolor\", \"0xff0000\");");
cs.AppendLine("so.addVariable(\"tspeed\", \"100\");");
cs.AppendLine("so.addVariable(\"tagcloud\", \"" + sb.ToString() + "\");");
cs.AppendLine("so.write(\"wpcumulusflashcontent\");");
cs.AppendLine("//]]>");
cs.AppendLine("</script>");
Literal1.Text = cs.ToString();
}
これで問題はすべて片付いたので、パラメータ設定の為のコントロールパネルを追加するまでは、上記コードが最終版・・・と思いたいです。(笑)
------------------ 2010/8/5 追記 ------------------
RecaptchaControl.cs の RenderContents メソッドですが、以下のように空白を追加してください。
protected override void RenderContents(HtmlTextWriter output)
{
・・・中略・・・
// /javascript\"" → /javascript\" " としてください。
sb.AppendLine("<script type=\"text/javascript\" " +
"/ src=\"http://api.recaptcha.net/js/recaptcha_ajax.js\" defer=\"defer\"></script>");
・・・後略・・・
空白なしでも動きますが、W3C Markup Validation Service でエラーがでます。