|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionTeamLive (the project I have been working on recently) blends Asp.net, Ajax and Silverlight in a number of places and I was interested to see how far I could push the html/Silverlight blend - the lightbox seemed like a good component for my experiment. For those of you wondering, a Lightbox is an effect that fades the page in the background to show you new content in the foreground. This article isn't intended to be a Silverlight tutorial, if you are new to this technology then I recommend reading some of the beginners tutorials before using this code. BackgroundTeamLive blends Asp.net, Ajax and Silverlight in a number of places. E.g. during a multi-file upload we adjust the OBJECT's styles giving it more screen space for displaying the progress bars. One of the controls I have been working on for the next iteration of TeamLive is a lightbox to help users navigate their image grids. Some of the requirements for the lightbox:
DemoIf you have Silverlight 2 installed visit http://www.devprocess.com and click one of the images... Back? I hope you saw something like this: If you just got an ugly window.open then you don't have Silverlight 2. Using the CodeFirstly, the A similar technique is used by the modal popup overlay (see the ModalPopup on the AjaxControlToolkit: http://www.asp.net/AJAX/AjaxControlToolkit/Samples/ModalPopup/ModalPopup.aspx) /// <summary>
/// PageBlanket covers a page with a partially transparent div
/// to prevent users interacting with the page - can be used to simulate a modal
/// dialog
/// </summary>
public class PageBlanket
{
HtmlElement _blanket = null;
/// <summary>
/// Lazy initialization on first call
/// </summary>
private void Initialize()
{
if (_blanket == null)
{
//create a div that will take up the whole page and cover the content underneath
_blanket = HtmlPage.Document.CreateElement("div");
HtmlPage.Document.Body.AppendChild(_blanket);
_blanket.SetStyleAttribute("position", "fixed");
_blanket.SetStyleAttribute("top", "0px");
_blanket.SetStyleAttribute("left", "0px");
_blanket.SetStyleAttribute("height", "100%");
_blanket.SetStyleAttribute("width", "100%");
_blanket.SetStyleAttribute("backgroundColor", "#808080");
_blanket.SetStyleAttribute("filter", "alpha(opacity=50)");
_blanket.SetStyleAttribute("opacity", "0.5");
_blanket.SetStyleAttribute("z-index", "3");
_blanket.SetStyleAttribute("display", "none");
}
}
/// <summary>
/// Show the blanket and cover the page
/// </summary>
public void Show()
{
//just in case not init'ed
Initialize();
//clear display attribute to show the blanket
_blanket.SetStyleAttribute("display", "");
}
/// <summary>
/// Hide the blanket again
/// </summary>
public void Hide()
{
//hide the blanket
_blanket.SetStyleAttribute("display", "none");
}
}
Page blanket creates a div, sets the style, jams it in the page, and toggles the display style to show/hide the div. This effectively disables the page while we do the Silverlight stuff. Dynamically showing/hiding the Silverlight control turned out to be harder. Firefox gets upset if you start moving the control around, changing zIndex, altering display style dynamically. I was getting working code in IE7 and “Trying to get unsupported property on scriptable plugin object!” errors in Firefox. The solution I found (works on IE7, Firefox2 and Safari (not tested on anything else yet)) was to set a small Width and Height (yeah, yeah - I know). I make sure I set the style of the object at the start (changing position and zIndex dynamically in the C# screwed up the scriptableobject): The lightbox codeNote it positions the lightbox in the center of the screen. Originally the code positioned the lightbox over the item that launched it - but it never looked quite right so I tried centering the lightbox. I’m not sure it’s much better in the center - so I’m waiting for inspiration. using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Windows.Media.Imaging;
namespace dpLightbox
{
[ScriptableType]
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
Loaded += new RoutedEventHandler(Page_Loaded);
//keep the lightbox in the center if page is resized
HtmlPage.Window.AttachEvent("onresize", new EventHandler(Window_Resize));
}
void Window_Resize(object sender, EventArgs e)
{
PositionToCenter();
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
//register for javascript control
HtmlPage.RegisterScriptableObject("LightboxController", this);
//the close button
bClose.MouseEnter += new MouseEventHandler(bClose_MouseEnter);
bClose.MouseLeave += new MouseEventHandler(bClose_MouseLeave);
bClose.MouseLeftButtonUp += new MouseButtonEventHandler(bClose_MouseLeftButtonUp);
}
bool closing = false;
/// <summary>
/// Close the lightbox
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void bClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
closing = true;
rCloseGlow.Opacity = 0.0;
sbLightbox.Completed += new EventHandler(sbLightbox_Completed);
sbLightbox.AutoReverse = true;
sbLightbox.Stop();
sbLightbox.Begin();
sbLightbox.Seek(new TimeSpan(0, 0, 0, 0, 500));
}
void sbLightbox_Completed(object sender, EventArgs e)
{
if (closing)
{
_blanket.Hide();
Width = 0;
Height = 0;
HtmlPage.Plugin.SetStyleAttribute("width", "1px");
HtmlPage.Plugin.SetStyleAttribute("height", "1px");
}
closing = false;
}
void bClose_MouseLeave(object sender, MouseEventArgs e)
{
rCloseGlow.Opacity = 0.0;
}
void bClose_MouseEnter(object sender, MouseEventArgs e)
{
rCloseGlow.Opacity = 1.0;
}
double paddingTop = 55;
double padding = 25;
PageBlanket _blanket = new PageBlanket();
[ScriptableMember]
public void showLightbox(string imgTitle, string imgSrc, double imgWidth, double imgHeight)
{
_blanket.Show();
txtTitle.Text = imgTitle;
imgMain.Source = new BitmapImage(new Uri(imgSrc, UriKind.RelativeOrAbsolute));
imgMain.ImageFailed += new ExceptionRoutedEventHandler(imgMain_ImageFailed);
//setup the lightbox size
double dWidth = imgWidth + (padding * 2);
double dHeight = imgHeight + (padding + paddingTop);
Width = dWidth;
Height = dHeight;
kfWidth.Value = dWidth;
kfHeight.Value = dHeight;
HtmlPage.Plugin.SetStyleAttribute("height", Height.ToString() + "px");
HtmlPage.Plugin.SetStyleAttribute("width", Width.ToString() + "px");
sbLightbox.Stop();
sbLightbox.Seek(new TimeSpan(0));
sbLightbox.AutoReverse = false;
sbLightbox.Begin();
HtmlPage.Plugin.SetStyleAttribute("display", "");
PositionToCenter();
}
void imgMain_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
//the developer needs to decide what should happen here
//empty lightbox? don't show the lightbox?
}
private void PositionToCenter()
{
Size clientBounds = BrowserHelper.GetClientBounds();
Point ptScrollPos = BrowserHelper.GetScrollPosition();
double dTop = ptScrollPos.Y + ((clientBounds.Height - Height) / 2);
double dLeft = ptScrollPos.X + ((clientBounds.Width - Width) / 2);
HtmlPage.Plugin.SetStyleAttribute("top", dTop.ToString() + "px");
HtmlPage.Plugin.SetStyleAttribute("left", dLeft.ToString() + "px");
}
}
}
Using the lightboxIn your aspx: <asp:Silverlight ID="slLb" runat="server" Source="~/ClientBin/dpLightbox.xap" Version="2.0" Width="1px" Height="1px" PluginBackground="Transparent" Windowless="true" style="position:absolute;z-index:4;"> <PluginNotInstalledTemplate></PluginNotInstalledTemplate> </asp:Silverlight> The PluginNotInstalledTemplate gets rid of the install Silverlight 2 prompt when Silverlight 2 isn’t installed - which is nice as the Lightbox isn’t essential functionality. Put this bit of Javascript in the head to simplify usage. This gets the Silverlight xap to show the lightbox or (shudder) a window.open if Silverlight 2 isn’t there. <script type="text/javascript">
function lightbox(imgTitle,imgSrc,imgWidth,imgHeight)
{
var lbContent=document.getElementById("slLb").Content;
if(lbContent!=null)
{
lbContent.LightboxController.showLightbox(imgTitle,imgSrc,imgWidth,imgHeight);
}
else
{
window.open(imgSrc,"noSilverlight","menubar=no,toolbar=no,height="+imgHeight+",width="+imgWidth);
}
}
</script>
Showing a lightbox - to show a lightbox call the function above. <a href="javascript:lightbox('TeamLive designer',
'http://www.devprocess.com/App_Themes/Default/lb_designer.jpg',600,296);">
<img src="App_Themes/default/designer.jpg" class="photosmall"
width="264" height="130" alt="Screenshot from devProcess TeamLive" />
</a>
TeamLiveYou can keep up to date with any updates (I will also try to make them here) at our blog: TeamLive Blog History28 April 08, Article submitted
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||