2010 年 6 月の中ごろから、WordPress のプラグイン WP-Cumulus(3D 空間をくるくる回る Flash を使った Tag Cloud)の BlogEngine.NET 1.6.1 への移植を試みていました。
先の ポスト で書きましたパラメータ設定機能の追加で、何とか普通に使えるレベルになったと思います。ここで、備忘録として、移植のために今まで BlogEngine.NET 1.6.1 に手を加えた内容をまとめて書いておきます。
この先、致命的な問題は出ないと期待して、しばらくコードの変更は凍結して、実用に耐えうるか試験したいと思います。もし、このブログを見て、試験するのを手伝ってあげようという奇特な方がおられましたら嬉しいです。その場合はメニューバーの「コンタクト」から連絡ください。
手を加えたのは、widget\Tag cloud フォルダの中にある widget.ascx, widget.ascx.cs, edit.ascx, edit.ascx.cs の 4 つのファイルのみです。以下、それぞれのファイルに手を加えた概要です。
widget.ascx
まず、3D Tag Cloud (Flash) 表示用に HTML の div タグと、ASP.NET サーバーコントロールの Literal を既存のコードに追加します。部分的なコードですが、以下のような感じです。
・・・前略・・・
<asp:Panel ID="panel3dTagCloud" runat="server">
<div id="wpcumulusflashcontent">
<p>If you see the icon blow, Flash Player and/or
JavaScript are/is not available in your PC.
・・・中略・・・
</p>
</div>
<asp:Literal id="Literal1" runat="server"></asp:Literal>
</asp:Panel>
・・・後略・・・
追加した Literal には、Flash 起動用の JavaScript が書き出されるようになっています。その操作はサーバー側で、コードビハインド (widget.ascx.cs) に定義されたプログラムにより行われます。もう少し具体的に書くと、サーバー側で DB に保存されたパラメータ設定値と Tag 情報(名前、リンク先など)を取得し、それを元に SWFObject 1.4 を使った JavaScript を組み立てて、Literal に書き出します。
ブラウザは、サーバーから送信された div タグと JavaScript を含む HTML コードを受け取ります。そうすると、今度はブラウザ側で JavaScript が動き、SWFObject 1.4 が div タグの innerHTML を書き換えて Flash を表示します。
上記に加えて、ASP.NET サーバーコントロールの Panel を用いて、3D + Standard, 3D only, Standard only の 3 種類の表示を切り替えられるようにしています。
widget.ascx.cs
まず、追加した 9 つのパラメータについて、DB から設定値を取得するためのプロパティを widgets_Tag_cloud_widget クラスに追加します。これはオリジナルのコードに含まれていた MinimumPosts プロパティを参考にしました。具体的には以下のような感じです(一例のみ。他に 8 つ必要)。
private string _tagCloudStyle = "0";
private string TagCloudStyle
{
get
{
StringDictionary settings = GetSettings();
if (settings.ContainsKey("tagcloudstyle"))
{
return settings["tagcloudstyle"];
}
else
{
return _tagCloudStyle;
}
}
}
パラメータ設定値は DB のテーブル be_DataStoreSettings に保存されています(SQL Server 使用の場合)。それをプロパティに含まれる GetSettings メソッドで取得するようになっています。DB から取得した設定値は Cache に保存され、Cache にデータがあればそれを返すので、GetSettings が呼ばれるたびに DB にアクセスするという無駄は出ないように考慮されています。
次に、LoadWidget メソッドに以下の追加・変更を加えます。
-
RegisterClientScriptBlock メソッドを使って、外部スクリプトファイル SWFObject.js を参照する script 定義を HTML コードに書き出すためのコードを追加。
-
widget.ascx の Literal に Flash 起動用の JavaScript を書き出すコードを追加。上記で追加したプロパティを使ってパラメータ設定値を取得し、既存の WeightedList プロパティを使って Tag 情報を取得し、それらをベースに SWFObject 1.4 を使った Flash 起動用の JavaScript の文字列を動的に組み立てて、Literal.Text に設定します。
-
表示方法を切り替えるため、widget.ascx に追加した 2 つの Panel の Visible プロパティの true/false を設定するコードを追加。表示方法は 3D + Standard, 3D only, standard only の 3 種類から選択可です。
LoadWidget メソッド全体のコードは以下のとおりです。
public override void LoadWidget()
{
string root = Utils.AbsoluteWebRoot.ToString();
StringBuilder sb, cs;
if (TagCloudStyle == "0" || TagCloudStyle == "1")
{
// 3D + Standard または 3D only の場合
string csname = "3dTagCloudEnablingScript";
Type cstype = this.GetType();
ClientScriptManager csm = Page.ClientScript;
if (!csm.IsClientScriptBlockRegistered(cstype, csname))
{
string script = "<script type=\"text/javascript\" src=\"" +
Utils.RelativeWebRoot + "swfobject.js\"></script>";
csm.RegisterClientScriptBlock(cstype, csname, script, false);
}
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 = "12";
switch (WeightedList[key])
{
case "biggest":
size = "18";
break;
case "big":
size = "16";
break;
case "medium":
size = "14";
break;
case "small":
size = "12";
break;
case "smallest":
size = "10";
break;
default:
size = "12";
break;
}
sb.Append(String.Format("<a href='{0}' style='{1}'>{2}</a>",
root + path, size, key));
}
sb.Append("</tags>");
cs = new StringBuilder();
cs.AppendLine("<script type=\"text/javascript\">");
cs.AppendLine("//<![CDATA[");
cs.AppendLine("var so = new SWFObject(\"" +
Utils.RelativeWebRoot + FlushFileName +
"\", \"tagcloud\", \"" + TagCloudWidth + "\", \"" +
TagCloudHeight + "\", \"10\", \"#ffffff\");");
cs.AppendLine("so.addParam(\"wmode\", \"transparent\");");
cs.AppendLine("so.addVariable(\"mode\", \"tags\");");
cs.AppendLine("so.addVariable(\"distr\", \"" +
((TagDistribution == "0") ? "true" : "false") + "\");");
cs.AppendLine("so.addVariable(\"tcolor\", \"" + TagColor1 + "\");");
cs.AppendLine("so.addVariable(\"tcolor2\", \"" + TagColor2 + "\");");
cs.AppendLine("so.addVariable(\"hicolor\", \"" + TagMouseoverColor + "\");");
cs.AppendLine("so.addVariable(\"tspeed\", \"" + TagRotationSpeed + "\");");
cs.AppendLine("so.addVariable(\"tagcloud\", \"" + sb.ToString() + "\");");
cs.AppendLine("so.write(\"wpcumulusflashcontent\");");
cs.AppendLine("//]]>");
cs.AppendLine("</script>");
Literal1.Text = cs.ToString();
}
else
{
// Standard only の場合
foreach (string key in WeightedList.Keys)
{
HtmlGenericControl li = new HtmlGenericControl("li");
li.InnerHtml = string.Format(LINK,
Utils.RelativeWebRoot + "?tag=/" + Utils.RemoveIllegalCharacters(key),
WeightedList[key],
"Tag: " + key,
key);
ulTags.Controls.Add(li);
}
}
if (TagCloudStyle == "0")
{
panel3dTagCloud.Visible = true;
panelStdTagCloud.Visible = true;
}
else if (TagCloudStyle == "1")
{
panel3dTagCloud.Visible = true;
panelStdTagCloud.Visible = false;
}
else
{
panel3dTagCloud.Visible = false;
panelStdTagCloud.Visible = true;
}
}
長くなりすぎましたので、edit.ascx, edit.ascx.cs については別のポストに分けます。