Thickbox extension

Jan 21, 2009 at 5:39 AM
Edited Jan 21, 2009 at 6:10 AM
Hi, I made an extension for thickbox, because all the extensions on the frontpage for lightbox style effects are dead links or don't work. It's pretty basic, it really just adds the necessary files to the post and page header, so you can use thickbox for single images.

How to install it
1. Place the thickbox.cs extension in App_code/Extensions/
2. Download thickbox.css, and loadingAnimation.gif from http://jquery.com/demo/thickbox/
3. Copy the thickbox.js from below
4. Place the 2 downloaded files and the thickbox.js into /plugins/thickbox - you must create this path or make your own path and just change it in thickbox.cs
5. Forgot to add - get the latest version of JQuery and place it in /js/jquery.js (if you want to change this, look in the extension file)
6. Test it out - use the samples at http://jquery.com/demo/thickbox/ to test it out

Ex:
<a href="/image.axd?picture=2008%2f12%2fsome-image.png" "image caption or title" class="thickbox">
<img src="/image.axd?picture=2008%2f12%2ftsome-image.png" alt="Single Image"/>
</a>

Some things that could be improved
- JQuery is added to header in this extension (probably shouldn't be)
- Add path in admin settings
- some other stuff :)

Thickbox.cs  [extension]
using System;
using BlogEngine.Core;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using BlogEngine.Core.Web.Controls;

/// <summary>
/// Links the files required to run thickbox in posts and pages
/// </summary>
[Extension("Thickbox", "1.4", "Kenpachi")]
public class Thickbox
{
    #region Private members
    private const string jqueryPath = "js/jquery.js";
    private const string thickBoxFolder = "plugins/thickbox/";
    private const string thickBoxScript = "thickbox.js";
    private const string thickBoxCSS = "thickbox.css";

    static protected ExtensionSettings _settings = null;
    
    #endregion

    /// <summary>
    /// Default constructor called on application start up from Global.asax to initialize extension
    /// </summary>
    public Thickbox()
    {
        // subscribe for post serving event
        Post.Serving += new EventHandler<ServingEventArgs>(Post_Serving);
        BlogEngine.Core.Page.Serving += new EventHandler<ServingEventArgs>(Page_Serving);
    }

    /// <summary>
    /// An event that handles ServingEventArgs
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Post_Serving(object sender, ServingEventArgs e)
    {
        if (e.Location == ServingLocation.SinglePost)
        {
            AddThickBox();
        }
    }

    /// <summary>
    /// An event that handles ServingEventArgs
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Page_Serving(object sender, ServingEventArgs e)
    {
        if (e.Location == ServingLocation.SinglePage)
        {
            AddThickBox();
        }
    }


    /// <summary>
    /// Adds thickbox script and css file to posts, and pages
    /// </summary>
    private void AddThickBox()
    {
        System.Web.UI.Page currentPage = (System.Web.UI.Page)HttpContext.Current.CurrentHandler;

        HtmlGenericControl jquery = new HtmlGenericControl("script");
        jquery.Attributes["type"] = "text/javascript";
        jquery.Attributes["src"] = Utils.RelativeWebRoot + jqueryPath;
        currentPage.Page.Header.Controls.Add(jquery);

        addLineBreak();

        HtmlGenericControl jqueryNoConflict = new HtmlGenericControl("script");
        jqueryNoConflict.Attributes["type"] = "text/javascript";
        jqueryNoConflict.InnerHtml = "$j = jQuery.noConflict();";
        currentPage.Page.Header.Controls.Add(jqueryNoConflict);

        addLineBreak();

        HtmlGenericControl script = new HtmlGenericControl("script");
        script.Attributes["type"] = "text/javascript";
        script.Attributes["src"] = Utils.RelativeWebRoot + thickBoxFolder + thickBoxScript;
        currentPage.Page.Header.Controls.Add(script);

        addLineBreak();

        HtmlLink link = new HtmlLink();
        link.Attributes["type"] = "text/css";
        link.Attributes["href"] = Utils.RelativeWebRoot + thickBoxFolder + thickBoxCSS;
        link.Attributes["rel"] = "stylesheet";
        link.Attributes["media"] = "all";
        currentPage.Page.Header.Controls.Add(link);

        addLineBreak();   
    }


    /// <summary>
    /// Adds line break
    /// </summary>
    private void addLineBreak()
    {
        System.Web.UI.Page currentPage = (System.Web.UI.Page)HttpContext.Current.CurrentHandler;

        LiteralControl newline = new LiteralControl(Environment.NewLine);
        currentPage.Page.Header.Controls.Add(newline);
    }
}



[thickbox.js]
/*
 * Thickbox 3.1 - One Box To Rule Them All.
 * By Cody Lindley (http://www.codylindley.com)
 * Copyright (c) 2007 cody lindley
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/
          
var tb_pathToImage = "/plugins/thickbox/loadingAnimation.gif";

/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/

//on page load call tb_init
$j(document).ready(function(){   
    tb_init('a.thickbox, area.thickbox, input.thickbox');//pass where to apply thickbox
    imgLoader = new Image();// preload image
    imgLoader.src = tb_pathToImage;
});

//add thickbox to href & area elements that have a class of .thickbox
function tb_init(domChunk){
    $j(domChunk).click(function(){
    var t = this.title || this.name || null;
    var a = this.href || this.alt;
    var g = this.rel || false;
    tb_show(t,a,g);
    this.blur();
    return false;
    });
}

function tb_show(caption, url, imageGroup) {//function called when the user clicks on a thickbox link

    try {
        if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
            $j("body","html").css({height: "100%", width: "100%"});
            $j("html").css("overflow","hidden");
            if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6
                $j("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");
                $j("#TB_overlay").click(tb_remove);
            }
        }else{//all others
            if(document.getElementById("TB_overlay") === null){
                $j("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");
                $j("#TB_overlay").click(tb_remove);
            }
        }
        
        if(tb_detectMacXFF()){
            $j("#TB_overlay").addClass("TB_overlayMacFFBGHack");//use png overlay so hide flash
        }else{
            $j("#TB_overlay").addClass("TB_overlayBG");//use background and opacity
        }
        
        if(caption===null){caption="";}
        $j("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page
        $j('#TB_load').show();//show loader
        
       
       var baseURL = url;
       
       
       var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;
       var urlType = baseURL.toLowerCase().match(urlString);

        if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp'){//code to show images
                
            TB_PrevCaption = "";
            TB_PrevURL = "";
            TB_PrevHTML = "";
            TB_NextCaption = "";
            TB_NextURL = "";
            TB_NextHTML = "";
            TB_imageCount = "";
            TB_FoundURL = false;
            if(imageGroup){
                TB_TempArray = $j("a[@rel="+imageGroup+"]").get();
                for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {
                    var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);
                        if (!(TB_TempArray[TB_Counter].href == url)) {                        
                            if (TB_FoundURL) {
                                TB_NextCaption = TB_TempArray[TB_Counter].title;
                                TB_NextURL = TB_TempArray[TB_Counter].href;
                                TB_NextHTML = "<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Next &gt;</a></span>";
                            } else {
                                TB_PrevCaption = TB_TempArray[TB_Counter].title;
                                TB_PrevURL = TB_TempArray[TB_Counter].href;
                                TB_PrevHTML = "<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Prev</a></span>";
                            }
                        } else {
                            TB_FoundURL = true;
                            TB_imageCount = "Image " + (TB_Counter + 1) +" of "+ (TB_TempArray.length);                                            
                        }
                }
            }

            imgPreloader = new Image();
            imgPreloader.onload = function(){        
            imgPreloader.onload = null;
                
            // Resizing large images - orginal by Christian Montoya edited by me.
            var pagesize = tb_getPageSize();
            var x = pagesize[0] - 150;
            var y = pagesize[1] - 150;
            var imageWidth = imgPreloader.width;
            var imageHeight = imgPreloader.height;
            if (imageWidth > x) {
                imageHeight = imageHeight * (x / imageWidth);
                imageWidth = x;
                if (imageHeight > y) {
                    imageWidth = imageWidth * (y / imageHeight);
                    imageHeight = y;
                }
            } else if (imageHeight > y) {
                imageWidth = imageWidth * (y / imageHeight);
                imageHeight = y;
                if (imageWidth > x) {
                    imageHeight = imageHeight * (x / imageWidth);
                    imageWidth = x;
                }
            }
            // End Resizing
            
            TB_WIDTH = imageWidth + 30;
            TB_HEIGHT = imageHeight + 60;
            $j("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div>");         
            
            $j("#TB_closeWindowButton").click(tb_remove);
            
            if (!(TB_PrevHTML === "")) {
                function goPrev(){
                    if($j(document).unbind("click",goPrev)){$j(document).unbind("click",goPrev);}
                    $j("#TB_window").remove();
                    $j("body").append("<div id='TB_window'></div>");
                    tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);
                    return false;    
                }
                $j("#TB_prev").click(goPrev);
            }
            
            if (!(TB_NextHTML === "")) {        
                function goNext(){
                    $j("#TB_window").remove();
                    $j("body").append("<div id='TB_window'></div>");
                    tb_show(TB_NextCaption, TB_NextURL, imageGroup);                
                    return false;    
                }
                $j("#TB_next").click(goNext);
                
            }

            document.onkeydown = function(e){     
                if (e == null) { // ie
                    keycode = event.keyCode;
                } else { // mozilla
                    keycode = e.which;
                }
                if(keycode == 27){ // close
                    tb_remove();
                } else if(keycode == 190){ // display previous image
                    if(!(TB_NextHTML == "")){
                        document.onkeydown = "";
                        goNext();
                    }
                } else if(keycode == 188){ // display next image
                    if(!(TB_PrevHTML == "")){
                        document.onkeydown = "";
                        goPrev();
                    }
                }    
            };
            
            tb_position();
            $j("#TB_load").remove();
            $j("#TB_ImageOff").click(tb_remove);
            $j("#TB_window").css({display:"block"}); //for safari using css instead of show
            };
            
            imgPreloader.src = url;
        }else{//code to show html
            
            var queryString = url.replace(/^[^\?]+\??/,'');
            var params = tb_parseQuery( queryString );

            TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no paramaters were added to URL
            TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no paramaters were added to URL
            ajaxContentW = TB_WIDTH - 30;
            ajaxContentH = TB_HEIGHT - 45;
            
            if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window        
                    urlNoQuery = url.split('TB_');
                    $j("#TB_iframeContent").remove();
                    if(params['modal'] != "true"){//iframe no modal
                        $j("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton' title='Close'>close</a> or Esc Key</div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;' > </iframe>");
                    }else{//iframe modal
                    $j("#TB_overlay").unbind();
                        $j("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;'> </iframe>");
                    }
            }else{// not an iframe, ajax
                    if($j("#TB_window").css("display") != "block"){
                        if(params['modal'] != "true"){//ajax no modal
                        $j("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'>close</a> or Esc Key</div></div><div id='TB_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");
                        }else{//ajax modal
                        $j("#TB_overlay").unbind();
                        $j("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");    
                        }
                    }else{//this means the window is already up, we are just loading new content via ajax
                        $j("#TB_ajaxContent")[0].style.width = ajaxContentW +"px";
                        $j("#TB_ajaxContent")[0].style.height = ajaxContentH +"px";
                        $j("#TB_ajaxContent")[0].scrollTop = 0;
                        $j("#TB_ajaxWindowTitle").html(caption);
                    }
            }
                    
            $j("#TB_closeWindowButton").click(tb_remove);
            
                if(url.indexOf('TB_inline') != -1){    
                    $j("#TB_ajaxContent").append($j('#' + params['inlineId']).children());
                    $j("#TB_window").unload(function () {
                        $j('#' + params['inlineId']).append( $j("#TB_ajaxContent").children() ); // move elements back when you're finished
                    });
                    tb_position();
                    $j("#TB_load").remove();
                    $j("#TB_window").css({display:"block"});
                }else if(url.indexOf('TB_iframe') != -1){
                    tb_position();
                    if($.browser.safari){//safari needs help because it will not fire iframe onload
                        $j("#TB_load").remove();
                        $j("#TB_window").css({display:"block"});
                    }
                }else{
                    $j("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()),function(){//to do a post change this load method
                        tb_position();
                        $j("#TB_load").remove();
                        tb_init("#TB_ajaxContent a.thickbox");
                        $j("#TB_window").css({display:"block"});
                    });
                }
            
        }

        if(!params['modal']){
            document.onkeyup = function(e){     
                if (e == null) { // ie
                    keycode = event.keyCode;
                } else { // mozilla
                    keycode = e.which;
                }
                if(keycode == 27){ // close
                    tb_remove();
                }    
            };
        }
        
    } catch(e) {
        //nothing here
    }
}

//helper functions below
function tb_showIframe(){
    $j("#TB_load").remove();
    $j("#TB_window").css({display:"block"});
}

function tb_remove() {
     $j("#TB_imageOff").unbind("click");
    $j("#TB_closeWindowButton").unbind("click");
    $j("#TB_window").fadeOut("fast",function(){$j('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});
    $j("#TB_load").remove();
    if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
        $j("body","html").css({height: "auto", width: "auto"});
        $j("html").css("overflow","");
    }
    document.onkeydown = "";
    document.onkeyup = "";
    return false;
}

function tb_position() {
$j("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'});
    if ( !(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
        $j("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});
    }
}

function tb_parseQuery ( query ) {
   var Params = {};
   if ( ! query ) {return Params;}// return empty object
   var Pairs = query.split(/[;&]/);
   for ( var i = 0; i < Pairs.length; i++ ) {
      var KeyVal = Pairs[i].split('=');
      if ( ! KeyVal || KeyVal.length != 2 ) {continue;}
      var key = unescape( KeyVal[0] );
      var val = unescape( KeyVal[1] );
      val = val.replace(/\+/g, ' ');
      Params[key] = val;
   }
   return Params;
}

function tb_getPageSize(){
    var de = document.documentElement;
    var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
    var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
    arrayPageSize = [w,h];
    return arrayPageSize;
}

function tb_detectMacXFF() {
  var userAgent = navigator.userAgent.toLowerCase();
  if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
    return true;
  }
}








Jun 21, 2009 at 4:12 PM

Hi,

 I really appreciate how you wrote an extension for ThickBox! Thank you! I'm having some trouble getting it to work and followed the exact directions you gave above. Do I need to add anything to envoke jQuery or ThickBox either in the body or header of my page? I noticed that you have to do that if you add ThickBox through from their website http://jquery.com/demo/thickbox and wasn't sure how if the extension worked the same way. 

 

Thanks again,

 

Justin