Thursday 18 November 2010

Showing Tooltip with an Image on mouse over of a GridView Column

This post is a continuation of Showing Tooltip on GridView column series. The previous post of this series can be find here.  (But there is no dependency between each posts)

Sometime back I got an assignment to show the image on each grid row mouse over for a particular column.

For example: In Product grid, I have list of Product details. I have a zoom image at the last column of each row. If the user mouse over the image, I required showing tooltip in which the image of the product required to show. I have record details where one column contains the URL of the image.

Here is a simple implementation of how to show the image in tooltip when mouse over on one of grid column:

I have the Product Records in XML format for simplicity. The XML content is:
<?xml version="1.0" encoding="UTF-8" ?>

<Products>

  <Product ProductID = "1" ProductName = "Chai" SupplierName = "Exotic Liquids" CategoryName = "Beverages" QuantityPerUnit = "10 boxes x 20 bags" UnitPrice = "18.00" Discontinued = "0" Image="Images\microsoft-wireless-mouse-5000.jpg" />
  <Product ProductID = "2" ProductName = "Chang" SupplierName = "Exotic Liquids" CategoryName = "Beverages" QuantityPerUnit = "24 - 12 oz bottles" UnitPrice = "19.00" Discontinued = "0" Image="Images\mouse.jpg" />
  <Product ProductID = "3" ProductName = "Aniseed Syrup" SupplierName = "Exotic Liquids" CategoryName = "Condiments" QuantityPerUnit = "12 - 550 ml bottles" UnitPrice = "10.00" Discontinued = "0" Image="Images\rt.jpg" />
  <Product ProductID = "4" ProductName = "Chef Anton's Cajun Seasoning" SupplierName = "New Orleans Cajun Delights" CategoryName = "Condiments" QuantityPerUnit = "48 - 6 oz jars" UnitPrice = "22.00" Discontinued = "0" Image="Images\Wireless-Mouse.jpg" />
  <Product ProductID = "5" ProductName = "Chef Anton's Gumbo Mix" SupplierName = "New Orleans Cajun Delights" CategoryName = "Condiments" QuantityPerUnit = "36 boxes" UnitPrice = "21.35" Discontinued = "1" Image="Images\both440.jpg" />
  <Product ProductID = "6" ProductName = "Grandma's Boysenberry Spread" SupplierName = "Grandma Kelly's Homestead" CategoryName = "Condiments" QuantityPerUnit = "12 - 8 oz jars" UnitPrice = "25.00" Discontinued = "0" Image="Images\13usb400.jpg" />
  <Product ProductID = "7" ProductName = "Uncle Bob's Organic Dried Pears" SupplierName = "Grandma Kelly's Homestead" CategoryName = "Produce" QuantityPerUnit = "12 - 1 lb pkgs." UnitPrice = "30.00" Discontinued = "0" Image="Images\13idekit360.jpg" />
  <Product ProductID = "8" ProductName = "Northwoods Cranberry Sauce" SupplierName = "Grandma Kelly's Homestead" CategoryName = "Condiments" QuantityPerUnit = "12 - 12 oz jars" UnitPrice = "40.00" Discontinued = "0" Image="Images\1394conns440.jpg" />
  <Product ProductID = "9" ProductName = "Mishi Kobe Niku" SupplierName = "Tokyo Traders" CategoryName = "Meat/Poultry" QuantityPerUnit = "18 - 500 g pkgs." UnitPrice = "97.00" Discontinued = "1" Image="Images\mainphoto3549.jpg" />
  <Product ProductID = "10" ProductName = "Ikura" SupplierName = "Tokyo Traders" CategoryName = "Seafood" QuantityPerUnit = "12 - 200 ml jars" UnitPrice = "31.00" Discontinued = "0" Image="Images\2XnF.jpg" />

</Products>
The Products in the XML are taken from Northwind database and the Image files are for example only to show how it works.

Next is.. You required to add one column on the Grid View, if the user hover the mouse the image will show in tooltip.
<asp:GridView ID="grdViewProducts" runat="server" 
    AllowPaging="True" AutoGenerateColumns="False" TabIndex="1"
    DataKeyNames="ProductID" Width="100%" DataSourceID="XmlDataSource1" 
    ShowFooter="True" CellPadding="4" ForeColor="#333333" GridLines="None" >
    <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="Product ID" />
        <asp:BoundField DataField="ProductName" HeaderText="Product Name" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" />
        <asp:BoundField DataField="QuantityPerUnit" HeaderText="Quantity Per Unit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" />
        <asp:TemplateField HeaderText="Photo">
            <ItemStyle Width="10%" HorizontalAlign="Center" />
            <ItemTemplate>
                <img id="imgPhoto" src="Images/zoom_icon.png" 
                    onmouseover="ShowToolTipImage(this.alt);" 
                    onmouseout="HideTooTipImage()" 
                    onmousemove="MoveToolTipImage()"
                    alt="<%# Eval("Image") %>" 
                    width="25px" height="25px" 
                    title="<%# Eval("ProductName") %>" 
                    style="cursor:hand" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
    <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
    <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
    <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
    <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
    <EditRowStyle BackColor="#999999" />
    <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
</asp:GridView>
<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="Data/Products.xml"></asp:XmlDataSource>
Here I added an img html element which is calling three javascript functions mouseover, mouseout and onmousemove. I am setting the path of the image (or the url of the image) in the alt property. This is important because, from the alt property only the javascript will get the url of image to show it in tooltip. You can even pass this value as parameter in the javascript directly.

Next… You required to add a Javascript on you page (or any javascript file which referenced on the page) where you want to show tool top. The Javascript would be follows:
// Declare General Variables 
var sTooTipId = 'divTooTip';
var sToolTipPlacement = "Left"; // Right, Left

// For Hiding tool tip
function HideTooTipImage() { 

  // Get the Div element which was created dynamically on ShowToolTipImage function
  var divTip = document.getElementById(sTooTipId); 

  if (divTip) {

    while (divTip.childNodes.length > 0)
      // Remove all child content which are added inside on the Div content
      divTip.removeChild(divTip.childNodes[0]); 

  }

  // Invisible th Div (which removed all child content)
  divTip.style.visibility = "hidden"; 

}
function MoveToolTipImage() {

    // Verify if the Div content already present?
    if (document.getElementById(sTooTipId)) {
    
        // Get the Div content which was invisible on HideTooTipImage function
        var newDiv = document.getElementById(sTooTipId);

        // Getting the cursor X position
        var CurX = (window.Event) ? e.pageX :
        event.clientX + (document.documentElement.scrollLeft ?
        document.documentElement.scrollLeft : document.body.scrollLeft);

        // Getting the cursor Y position
        var CurY = (window.Event) ? e.pageY :
        event.clientY + (document.documentElement.scrollTop ?
        document.documentElement.scrollTop : document.body.scrollTop);

        // positioning the div. Here values 17, 12 are to set the div properly little above the cursor, you can modify if required.
        if (sToolTipPlacement == "Right")
            newDiv.style.left = (CurX + 17) + "px";
        else // Left
            newDiv.style.left = (CurX - (parseInt(newDiv.style.width) + 17)) + "px";

        // Portion of Image hide by browser top
        if ((CurY - (parseInt(newDiv.style.height) + 12)) < 0)
            // Showing below the Zoom Image
            newDiv.style.top = CurY + "px";
        else
            // Showing above the Zoom Image
            newDiv.style.top = (CurY - (parseInt(newDiv.style.height) + 12)) + "px";

        // Finally visibling the div which has the image
        newDiv.style.visibility = "visible"; 
    }
}
// For showing tool tip
function ShowToolTipImage(url) { 

    // Verify if the Div content already present?
    if (!document.getElementById(sTooTipId)) {
    
        // If not create a new Div element
        var newDiv = document.createElement("div");
        // Set the id for the Div element to refer further
        newDiv.setAttribute("id", sTooTipId);

        // Add it to the page
        document.body.appendChild(newDiv); 
        
    }
    else
        // Get the Div content which was invisible on HideTooTipImage function
        var newDiv = document.getElementById(sTooTipId);

    // Create an html image element
    var NewImg = document.createElement("img");
    
    // Here the url is the path of the image which was stored in the xml file (in Image column). 
    // This was passed from image icon from the alt property.
    NewImg.setAttribute("src", url);
    // Setting the style - if u required set what style you required
    NewImg.style.width = "100%";
    NewImg.style.height = "100%";
    // Adding the image element to div created
    newDiv.appendChild(NewImg);

    // Here I am setting the style for example purpose, you can modify what you required. 
    // You can even set the css class also.
    newDiv.style.zIndex = 2; 
    newDiv.style.padding = "3px";
    newDiv.style.backgroundColor = "Gray";
    newDiv.style.border = "solid 1px blue";
    newDiv.style.width = "140px";
    newDiv.style.height = "100px";

    // Absolute make the div floating on the screen.
    newDiv.style.position = "absolute"; 

    // Getting the cursor X position
    var CurX = (window.Event) ? e.pageX :
        event.clientX + (document.documentElement.scrollLeft ?
        document.documentElement.scrollLeft : document.body.scrollLeft);

    // Getting the cursor Y position
    var CurY = (window.Event) ? e.pageY :
        event.clientY + (document.documentElement.scrollTop ?
        document.documentElement.scrollTop : document.body.scrollTop);

    // positioning the div. Here values 17, 12 are to set the div properly little above the cursor, you can modify if required.
    newDiv.style.left = (CurX - (parseInt(newDiv.style.width) + 17)) + "px";
    // Portion of Image hide by browser top
    if ((CurY - (parseInt(newDiv.style.height) + 12)) < 0)
        // Showing below the Zoom Image
        newDiv.style.top = CurY + "px";
    else
        // Showing above the Zoom Image
        newDiv.style.top = (CurY - (parseInt(newDiv.style.height) + 12)) + "px";

    // Finally visibling the div which has the image
    newDiv.style.visibility = "visible"; 
}
Here there are three function added in the Javascript 

  • ShowToolTipImage(url) - Here the url is coming from the alt property of the image which actually has the url of the image.
  • HideToolTipImage() - To hide the tooltip when mouse is out of the icon
  • MoveToolTipImage(url) - It will give a nice UI, which will adjust the position near to cursor when you move on the icon
The description of the code is given on the code for understanding more.  The url parameter could be a file relative path stored in the application folder or any http/https url also. But if you are giving http/https url, make sure the image can be accessed directly from the url with no access issue.

If you run the project, you must be getting the image as tooltip in each and every row.

The output of the code is shown below.



Ok…. Incase if the image stored in database table, how to show it in the page as tooltip. Here is the post which concentrates on this issue.

2 Responses to “Showing Tooltip with an Image on mouse over of a GridView Column”

  • Julio says:
    9 July 2013 at 02:32

    when i view may page in the browser i get the following error:

    'e' is undefined

    That error occurs on the following line:
    var CurX = (window.Event) ? e.pageX :

    Please let me know the cause of the error.

  • Anonymous says:
    4 January 2018 at 19:20

    To Julio.
    We are 6 years later but this is a browser compatibility issue.
    The code runs pretty well forcing IE7 mode with in section.

Post a Comment