WebSurfer's Home

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

Lightbox Plugin

by WebSurfer 2011年6月19日 18:23

jQuery 版の Lightbox plugin を実装してみました。基本的には バージョン 1.6.1 で実装したもの と同じですが、記事に書き込むスクリプトを簡略化しました。

以下の画像はダウンロードしたサンプルに含まれていたもので、サンプルと同様に、次の画像、前の画像を連続して表示できます。

gallery という id を持つ div タグの中に、a タグで囲った img 要素を 5 個並べて表示しています。jQuery のセレクタ $('#gallery a') で gallery の中にある a タグを探し、それに対して lightBox() というスクリプトで href 属性に指定した画像ファイルを Lightbox 中に表示するようにしています。


湘南

左の画像は、上の gallery という id を持つ div タグの外にあり、単独で表示される(上の画像と連続して表示されない)ようにしたものです。

a タグで rel="lightbox"(任意で可)として、$('a[rel^=lightbox]') という属性セレクタで rel 要素に lightbox という文字列を含む a タグを探し、それに対して lightBox() というスクリプトで href 属性に指定した画像ファイルを Lightbox 中に表示するようにしています。

BlogEngine.NET へのスクリプトファイルと css ファイルの指定の追加は、以下の Extension を用いました。マスターページに直接書き込む方が簡単ですが、その場合はすべてのテーマのマスターページに書かなければならず、スマートではないので。バージョン 1.6.1 のものとは少々異なります。Lightbox を起動するスクリプトの大半を Extension で RegisterClientScriptBlock メソッドを使用して自動的に書き込まれるようにしました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BlogEngine.Core.Web.Controls;
using BlogEngine.Core;
using System.Web.UI.HtmlControls;

[Extension("Enable jQuery Lightbox plugin 0.5",
"1.0",
"<a target=\"_blank\" href=\"http://surferonwww.info/Default.aspx\">WebSurfer</a>")]
public class Lightbox
{
  private string extensionName = "LightboxPlugin";
  private static string scriptsFolder = "lightbox/script";
  private static string lightboxScriptFilename = 
    "jquery.lightbox-0.5.pack.js";
  private static string stylesFolder = "lightbox/css";
  private static string cssFilename = 
    "jquery.lightbox-0.5.css";
  private static string imageFolder = 
    Utils.RelativeWebRoot + "lightbox/images";

  public Lightbox()
  {
    BlogEngine.Core.Post.Serving +=
      new EventHandler<ServingEventArgs>(EnableLightbox);
  }

  private void EnableLightbox(object sender, ServingEventArgs e)
  {
    HttpContext context = HttpContext.Current;
    if (context.CurrentHandler is System.Web.UI.Page)
    {
      if (context.Items[extensionName] == null)
      {
        System.Web.UI.Page page =
          (System.Web.UI.Page)context.CurrentHandler;

        page.Header.Controls.Add(
          JavaScriptInclude(scriptsFolder +
            "/" + lightboxScriptFilename));

        HtmlLink lightboxCss = new HtmlLink();
        lightboxCss.Attributes["type"] = "text/css";
        lightboxCss.Attributes["rel"] = "stylesheet";
        lightboxCss.Attributes["href"] =
          Utils.RelativeWebRoot + stylesFolder +
          "/" + cssFilename;
        page.Header.Controls.Add(lightboxCss);

        string csname = "LightboxEnablingScript";
        Type cstype = this.GetType();
        System.Web.UI.ClientScriptManager csm = 
          page.ClientScript;
        if (!csm.IsClientScriptBlockRegistered(cstype, csname))
        {
          System.Text.StringBuilder sb = 
            new System.Text.StringBuilder();
          sb.AppendLine(
            "function EnableLightbox(jQueryObject) {");
          sb.AppendLine("jQueryObject.lightBox({");
          sb.AppendLine("imageLoading: '" + imageFolder + 
            "/lightbox-ico-loading.gif',");
          sb.AppendLine("imageBtnClose: '" + imageFolder + 
            "/lightbox-btn-close.gif',");
          sb.AppendLine("imageBtnPrev: '" + imageFolder + 
            "/lightbox-btn-prev.gif',");
          sb.AppendLine("imageBtnNext: '" + imageFolder + 
            "/lightbox-btn-next.gif',");
          sb.AppendLine("imageBlank: '" + imageFolder + 
            "/lightbox-blank.gif'");
          sb.AppendLine("});");
          sb.AppendLine("}");

          csm.RegisterClientScriptBlock(
            cstype, csname, sb.ToString(), true);
        }

        context.Items[extensionName] = 1;
      }
    }
  }

  private HtmlGenericControl JavaScriptInclude(string url)
  {
    HtmlGenericControl script = 
      new HtmlGenericControl("script");
    script.Attributes["type"] = "text/javascript";
    script.Attributes["src"] = ResolveScriptUrl(url);
    return script;
  }

  private string ResolveScriptUrl(string url)
  {
    return Utils.RelativeWebRoot + "js.axd?path="
      + Utils.RelativeWebRoot + url;
  }
}

自分でブログの記事中に書き込まなければならないスクリプトは以下のとおりです。これはバージョン 1.6.1 と比べて簡略化しました。それでも、今回の例で使った gallery や lightbox という名前を、ブログの記事を書くときに自由に指定できるようにしています。

<script type="text/javascript">
//<![CDATA[
$(function () {
  EnableLightbox($('#gallery a'));
  EnableLightbox($('a[rel^=lightbox]'));
});
//]]>
</script>

------------- 2011/7/3 追記 -------------

IE6, IE7, IE8 では Lightbox が動かないので調査したところ、BlogEngine.NET 2.0 に実装されている SyntaxHighlighter 3.0.83 の shCore.js が取り込まれると、jQuery.js の解析がうまくいかず、Lightbox2 のスクリプトから jQuery.js 内に定義されているメソッドか変数を参照できないことが問題であることがわかりました。

shCore.js と jquery.lightbox-0.5.pack.js を定義するスクリプトの順序が問題という話(shCore.js を先にしないとダメとのこと)がありましたので、変えてみましたが、効果はなかったです。また、jquery.js のバージョンを最新(これを書いている時点で 1.6.1)に変更してみましたが、これも効果はなかったです。

たぶん IE のパーサーなどの IE 内部の問題なので、調べても原因も解決策も分からないだろうと思い、これ以上の原因究明は止めました。

IE6, IE7, IE8 のパーサーが jquery.js をうまく解釈できていないということは、Lightbox 以外でも潜在的に問題があるかもしれないということなので、少なくとも BlogEngine.NET 1.6.1 では問題のなかった SyntaxHighlighter 2.0.320 を使うことにしました。

その結果、IE6, IE7, IE8 でも Lightbox は表示されるようになりました(IE7 は IETester ですが)。でも、Chrome, Opera では、Lightbox 問題なく表示されるものの、バックグラウンドの表示が変です。引き続き調査中です。

------------- 2011/10/18 追記 -------------

Chrome, Opera で、バックグラウンドの表示が変だったのは、CSS を BlogEngine.NET 標準のものから、ブログ1で使っているものに変えたら問題がなくなりました。結局なにが原因だったのか分かりません。(汗)

Tags: ,

BlogEngine.NET 2.0

Cumulus

by WebSurfer 2011年6月18日 20:48

タグクラウドが 3D 空間で回転する WordPress のプラグイン WP-Cumulus を BlogEmgine.NET 2.0 にも実装してみました。

バージョン 1.6.1 では defer 属性が追加されているスクリプト定義ありましたが、バージョン 2.0 ではなくなったので、Flash 起動用のスクリプトを RegisterStartupScript メソッドを用いて html コードの一番最後に書き出すように変更しました。

(注)defer 属性のあるスクリプト定義を読み込んだ後で Flash を起動すると(正確には innerHTML を書き換えると)、IE の場合はその defer 属性つきのスクリプトの読み込み(解析?)に失敗します。詳しくは先のブログの記事 WP-Cumulus(4) および MSDN フォーラムの記事を参照してください。

右のサイドバーの Tag cloud に表示されているはずですが、いかがでしょうか。

Tags:

BlogEngine.NET 2.0

スパムコメントの表示

by WebSurfer 2011年6月17日 22:48

スパムコメントはいかなる場合も一般閲覧者の目に触れないようにしたいというのが普通だと思います。

しかしながら、バージョン 2.0 ではコントロールパネルで「コメント確認後に公開」にチェックを入れておかないと、自動モデレーションでスパムに分類されたコメントを含め、すべてのコメントが公開されてしまいます。

また、管理者が閲覧した場合は、スパムを含めてすべてのコメントが表示されますが、同じスパムコメントが 2 回づつ表示されてしまうという不具合があります。

上記の不具合を解消して、コメントの表示が期待通りになるよう、User controls/CommentView.ascx.cs の OnLoad メソッドの一部を以下のように変更しました。

if (this.NestingSupported)
{
  // コメントをネストして表示するオプションを選ぶと以下が
  // 実行される。その場合は、期待通り、スパムに分類された
  // コメントは一般閲覧者には表示されないし、管理者に対し
  // て同じスパムが 2 回表示されるということもない。
  if (this.Post != null)
  {
    this.AddNestedComments(
      path, 
      this.Post.NestedComments, 
      this.phComments, 
      canViewUnpublishedPosts);
  }
}
else
{
  // コメントをネストして表示しない場合は以下が実行される。
  // その場合「コメント確認後に公開」にチェックしないと:
  // 1) 一般閲覧者にスパムコメントが表示されてしまう。
  // 2) 管理者にはスパムコメントが 2 回表示されてしまう。
                    
  //foreach (var comment in
  //  this.Post.Comments.Where(
  //    comment => comment.Email != "pingback" && 
  //      comment.Email != "trackback"))
  //{
  //  if (comment.IsApproved)
  //  {
  //    this.CommentCounter++;
  //  }

  //  if (!comment.IsApproved && 
  //    BlogSettings.Instance.EnableCommentsModeration)
  //  {
  //    continue;
  //  }

  //  var control = (CommentViewBase)this.LoadControl(path);
  //  control.Comment = comment;
  //  control.Post = this.Post;
  //  this.phComments.Controls.Add(control);
  //}

  // Add unapproved comments
  //if (canViewUnpublishedPosts)
  //{
  //  foreach (var comment in this.Post.Comments)
  //  {
  //    if (comment.Email == "pingback" || 
  //      comment.Email == "trackback")
  //    {
  //            continue;
  //        }

  //        if (comment.IsApproved)
  //        {
  //            continue;
  //        }

  //        var control = (CommentViewBase)this.LoadControl(path);
  //        control.Comment = comment;
  //        control.Post = this.Post;
  //        this.phComments.Controls.Add(control);
  //    }
  //}

  // AddNestedComments と同じ内容(再帰呼び出しを除く)とすれ
  // ば期待した結果となる。
  foreach (Comment comment in this.Post.Comments)
  {
    if ((!comment.IsApproved && 
      BlogSettings.Instance.EnableCommentsModeration) &&
      (comment.IsApproved || !canViewUnpublishedPosts))
    {
      continue;
    }

    if (comment.IsSpam && !canViewUnpublishedPosts)
    {
      continue;
    }

    if (comment.Email == "pingback" || 
      comment.Email == "trackback")
    {
      continue;
    }

    var control = (CommentViewBase)this.LoadControl(path);
    control.Comment = comment;
    control.Post = this.Post;
    this.phComments.Controls.Add(control);

    if (comment.IsApproved)
    {
      this.CommentCounter++;
    }
  }
}

Tags:

BlogEngine.NET 2.0

About this blog

ここブログ2は趣味など日常のトピックス、ブログ1 は ASP.NET Web アプリ開発関係のトピックスになっています。

Calendar

<<  2018年6月  >>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar