WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

WP-Cumulus(4)

by WebSurfer 2010年6月24日 23:00

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 でエラーがでます。

Tags: , ,

BlogEngine.NET

reCaptcha が動かなくなりました

by WebSurfer 2010年6月20日 13:22

先のエントリ WP-Cumulus(3) で書きましたように、Widget の Tagcloud に WP-Cumulus を導入しましたが、その後 reCaptcha が表示されなくなっているのに気がつきました。

調べてみると、reCaptcha を表示するための JavaScript で、「'Recaptcha' は宣言されていません。」というエラーが出ています。

Widget の Tagcloud の WP-Cumulus を動かすため、Flash Player を起動する JavaScript を追加しましたが(詳しくは WP-Cumulus(3) を参照)、原因はどうやらこれと reCaptcha を起動するするスクリプトとの相性のようです。

WP-Cumulus の Flash Player 用の JavaScript を、reCaptcha 用の JavaScript より先に起動すれば問題はないのですが、逆だとダメでした(Widget の Tagcloud に WP-Cumulus を表示しようとすると、どうしても逆になってしまいます)。

タイミングの問題かと思って、setTimeout を使って reCaptcha 用の JavaScript の起動を遅らせてみたんですが、同じ結果でした。

BlogEngine の App_Code\Extensions\Recaptcha\RecaptchaControl.cs の中で、reCaptcha 本家のサイトからスクリプトをダウンロードしてくる設定になっています(下記参照)。"宣言されていません" というエラーになる Recaptcha はその中に定義されています。

<script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js" defer="defer">

理由は全く不明ですが、recaptcha_ajax.js をダウンロードしてローカルに置いて、ローカルのファイルを参照するように変更したら、エラーは出なくなりました。

具体的には、RecaptchaControl.cs の中の RenderContents メソッドで、以下のように変更しました。

//output.AddAttribute("src", "http://api.recaptcha.net/js/recaptcha_ajax.js");
output.AddAttribute("src", "/BlogEngine/recaptcha_ajax.js");

本当にこれだけで問題解決になっているかイマイチ疑問ですが(汗)、とりあえずこのまま様子を見るつもりです。

***************** 2010/6/23 追記 *****************

やっぱり上記の処置では問題解決になっていませんでした。(涙)

reCaptcha を管理している google のサイトによると、recaptcha_ajax.js をダウンロードして自サーバーに置くのは、"Caching the reCAPTCHA javascript increases the risk that we might accidentally break your site in an upgrade." という理由で好ましくないとのことです。やむを得ず元に戻して、reCaptcha のサーバーからダウンロードするようにしました。

でもそうすると、IE ではスクリプトエラーが出て reCaptcha が動かなくなってしまいます。script タグから defer 属性を削除するとエラーを回避できるので、そうしてみましたが、今度は表示の遅れが目立つようになってしまいました。その問題を解決するため(defer 属性をつけたままでもスクリプトエラーが出ないようにするため)、問題のスクリプトの位置を HTML コードの最後の方になるように変更しました。そのため、2010/6/23 現在、コードは上記とは異なりますのでご注意ください。詳しい話は後日別途ポストします。

Tags: ,

BlogEngine.NET

WP-Cumulus(3)

by WebSurfer 2010年6月19日 15:35

Widget の Tagcloud の中にタグが 3D 空間で回転する WordPress のプラグイン WP-Cumulus を実装しました。

結局、日本語に対応していない Ver. 1.23 の tagcloud.swf を使うのはやめて、WP-Cumulus 作者が試験のために作った Unicode Support 版(詳しくは先のエントリ WP-Cumulus(2) を参照)を使いました。

サイズ、色その他のパラメーター設定は \widgets\Tag cloud\widget.ascx.cs の中にハードコーディングしました。本当はコントロールパネルのようなものを作るといいのですが、とっても面倒だったのでとりあえず今回はやめました。(笑)

その内容は以下の通りで、private const string LINK2 を追加して LoadWidge メソッドの中を書き換えています。これに加えて、widget.ascx に div タグの追加が必要です(id="wpcumulusflashcontent" としています)。

private const string LINK2 = "<a href='{0}' style='{1}'>{2}</a> ";

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(LINK2, root + path, size, key));
  }

  sb.Append("</tags>");
  string tagcloud = sb.ToString();
  String csname = "WpCumulusScript";
  Type cstype = this.GetType();
  ClientScriptManager cs = Page.ClientScript;

  if (!cs.IsClientScriptBlockRegistered(cstype, csname))
  {
    StringBuilder cstext = new StringBuilder();
    cstext.AppendLine("var flashobject = new SWFObject(\"/BlogEngine/tagcloudUnicode.swf\", \"tagcloud\", \"180\", \"170\", \"10\", \"#ffffff\");");
    cstext.AppendLine("flashobject.addParam(\"wmode\", \"transparent\");");
    cstext.AppendLine("flashobject.addVariable(\"tcolor\", \"0x333333\");");
    cstext.AppendLine("flashobject.addVariable(\"tcolor2\", \"0x333333\");");
    cstext.AppendLine("flashobject.addVariable(\"hicolor\", \"0xff0000\");");
    cstext.AppendLine("flashobject.addVariable(\"tspeed\", \"100\");");
    cstext.AppendLine("flashobject.addVariable(\"tagcloud\", \"" + tagcloud + "\");");
    cstext.AppendLine("flashobject.write(\"wpcumulusflashcontent\");");
    cs.RegisterStartupScript(cstype, csname, cstext.ToString(), true);
  }
}

一応動いていますが、使っている tagcloud.swf(上記コードではオリジナル版を区別するために名前を tagcloudUnicode.swf に変えています)は作者によると "highly experimental swf version" だそうですので予期せぬ問題が出るかもしれません。しばらく様子を見ていきたいと思っています。

***************** 2010/6/23 追記 *****************

3D タグクラウド追加後、スクリプトエラーのため (1) コメントが書き込めない、(2) AMPL フィルターが起動できないという問題が IE で発生しました(この後のエントリ reCaptcha が動かなくなりました で書いたのとは別のスクリプトエラーです)。

そのスクリプトエラーを避けるため、Tag cloud 起動用のスクリプトをページの終わりに埋め込むのはやめて(上記のコードがそうなっています)、Tag cloud をレンダリングする HTML コードの中に埋め込むように変更しました。2010/6/23 現在、コードは上記とは異なりますのでご注意ください。詳しい話は後日別途ポストします。

Tags: , ,

BlogEngine.NET

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  2018年5月  >>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar