Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Всплывающее меню для одностраничного портала

Источник: realcoding.net

Введение


Недавно решил изучить ASP.NET и одновременно создать что-нибудь полезное, посложнее «Hello, world!». Первое знакомство с ASP.NET у меня началось с IBuySpy. Довольно быстро разобравшись с этим Shared Source проектом, я начал его перекраивать под свои нужды. В итоге осталось довольно мало оригинального кода, кроме части ядра (ибо, зачем изобретать велосипед? :)). Кроме всего прочего, хотелось сделать больше функциональности, например, всплывающее меню. В сети много примеров всяких всплывающих менюшек, в том числе и исходников Open Source. Но они, как правило, сложны и не очень подходили под мои нужды. Поэтому я решил написать простое меню в виде пользовательского элемента и предложить Вам результаты своего творчества. В результате должно получиться это:



1. Реализация базы данных


Начнем с написания базы данных. Для этой статьи я немного переделал таблицу Tabs из IBuySpy:

CREATE TABLE [Tabs]
  (
              [
TabID] [int] IDENTITY (1, 1) NOT NULL,
              [
TabOrder] [int] NOT NULL,
              [
TabName] [nvarchar] (50) NOT NULL,
              [
ParentTab] [int] NOT NULL
 
) ON [PRIMARY]
 
GO

TabID – идентификатор закладки,

TabOrder – порядковый номер закладки,

TabName – имя закладки,

ParentTab – указывает на идентификатор родительской закладки или имеет -1, если это верхний уровень меню.

Также необходимо написать пару процедур. Одну для составления списка меню из закладок (Tabs):

CREATE PROCEDURE GetMenuItems
 
AS
 
SELECT   
      TabID
,
      
TabOrder,
      
TabName
  FROM
      Tabs
  WHERE
      ParentTab
= -1
  ORDER BY
      TabOrder
  GO

И еще одну для получения подменю для текущей закладки:

CREATE PROCEDURE GetSubMenuItems
 
(
      @
ParentTab int
 
)
  AS
 
SELECT   
      TabID
,
      
TabOrder,
      
TabName
  FROM
      Tabs
  WHERE
      ParentTab
= @ParentTab
  ORDER BY
      TabOrder
  GO

Надеюсь, тут все ясно. В принципе, можно обойтись только второй процедурой, передавая ей в качестве параметра -1 для заглавного меню. Но для большей простоты и наглядности оставим все как есть.

В качестве примера наполним таблицу следующими значениями:



На этом наша работа с SQL Server закончена, переходим к кодированию проекта.

2. Кодирование пользовательского элемента


Создадим для сего произведения новый проект. Он будет состоять из простой формы с таблицей для тестирования, класса для доступа к данным и собственно пользовательского элемента.

Для доступа к данным из базы создадим свой класс DataSource. Вот его код:

using System;
 
using System.Configuration;
 
using System.Data;
 
using System.Data.SqlClient;
 
namespace Daenur.TabList
 
{
   
/// <summary>
    /// Summary description for DataSource.
    /// </summary>
   
public class DataSource
   
{
      
public SqlDataReader GetMenuItems()
      {
       
// создаем соединение (connectionString берем из Web.config)
       
SqlConnection myConnection = new SqlConnection(ConfigurationSettings.AppSettings[connectionString]);
       
SqlCommand myCommand = new SqlCommand(GetMenuItems, myConnection);
       
myCommand.CommandType = CommandType.StoredProcedure;// и получаем данные
       
myConnection.Open();
       
SqlDataReader reader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
        return
reader;
      }
      
public SqlDataReader GetSubMenuItems(int parentTab)
      {
       
// создаем соединение (connectionString берем из Web.config)
       
SqlConnection myConnection = new SqlConnection(ConfigurationSettings.AppSettings[connectionString]);
       
SqlCommand myCommand = new SqlCommand(GetSubMenuItems, myConnection);
       
// добавляем параметр - № родительской закладки
       
SqlParameter parameterParentTab = new SqlParameter(@ParentTab, SqlDbType.Int, 4);
       
parameterParentTab.Value = parentTab;
       
myCommand.Parameters.Add(parameterParentTab);
       
myCommand.CommandType = CommandType.StoredProcedure;
       
// и получаем данные
       
myConnection.Open();
       
SqlDataReader reader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
        return
reader;
      }
    }
  }

Примечание: для тех, кто не знает, как использовать Web.config для хранения строки соединения, приведу пример:

<appSettings>
    <!--
строка соединения с базой -->
    <
add key=ConnectionString value=server=localhost;database=TabList;uid=<Ваш_логин>;password=<Ваш_пароль>; />
  </
appSettings>

Теперь создадим в проекте новый пользовательский элемент управления и назовем его TabList. В файле TabList.ascx напишем следующее:

<%@ Control Language=c# AutoEventWireup=false Codebehind=TabList.ascx.cs Inherits=Daenur.TabList.TabList
TargetSchema=http://schemas.microsoft.com/intellisense/ie5%>
  <
table id=menuTable height=* cellSpacing=0 cellPadding=0 width=* border=1 runat=server>
  </
table>
  <
script language=javascript type=text/javascript>
  var
currentSubMenu = null;
  var
currentSubMenuNum = 0;
  var
closeTimer = null;
  function
openSubMenu(num)
  {
    var
subMenu = document.getElementById(TabList_subMenu + num);
    if (
subMenu != null)
    {
      
cancelCloseTime();
      
subMenu.style.display=;
      if ((
currentSubMenu != null) && (currentSubMenuNum != num))
      {
       
currentSubMenu.style.display=none;
      }
      
currentSubMenu = subMenu;
      
currentSubMenuNum = num;
    }
  }
  function
closeTime()
  {
   
closeTimer = window.setTimeout(closeMenu, 1000);
  }
  function
cancelCloseTime()
  {
    if (
closeTimer != null)
    {
      
window.clearTimeout(closeTimer);
      
closeTimer = null;
    }
  }
  function
closeMenu()
  {
    if (
currentSubMenu != null)
    {
      
currentSubMenu.style.display=none;
      
currentSubMenu = null;
      
currentSubMenuNum = 0;
    }
  }
 
document.onclick = closeMenu;
 
</script>

Пока сам элемент это пустая таблица, которая будет наполняться данными из базы и автоматически создавать структуру меню при загрузке страницы. Скрипт здесь нужен для показа или скрытия подменю. При наведении курсора на пункт меню его подменю появляется, а при клике на форме или просто после покидания пункта меню курсором – исчезает.

Файл с кодом (TabList.cs) выглядит так:

namespace Daenur.TabList
 
{
   
using System;
   
using System.Data;
   
using System.Data.SqlClient;
   
using System.Web;
   
using System.Web.UI;
   
using System.Web.UI.HtmlControls;
   
/// <summary>
    /// Summary description for TabList.
    /// </summary>
    // Направление меню (горизонтальное или вертикальное)
   
public enum repeatDirection{Horizontal = 0, Vertical};
   
public abstract class TabList : System.Web.UI.UserControl
   
{
      
protected System.Web.UI.HtmlControls.HtmlTable menuTable;
      
private DataSource data = new DataSource();// источник данных
      
public repeatDirection RepeatDirection; // направление меню
      
private void Page_Load(object sender, System.EventArgs e)
      {
       
// Put user code to initialize the page here
       
DataBind();
      }
      
public override void DataBind()
      {
      
// получаем все закладки
       
SqlDataReader menuItems = data.GetMenuItems();// если меню горизонтальное
       
if (RepeatDirection == repeatDirection.Horizontal)
        {
         
// то формируем строку в нашей таблице
         
HtmlTableRow tr = new HtmlTableRow();
         
tr.ID = menu;
         
tr.Attributes.Add(runat, server);
          while (
menuItems.Read())
          {
            
HtmlTableCell td = new HtmlTableCell();
            
td.ID = menuItem + menuItems[TabOrder];
            
// создаем код закладки - ссылки
            // (здесь: onmouseout и onmouseover - события, обработчики которых находятся в скрипте)
            
string HtmlText = @<nobr> &nbsp; <a onmouseout=closeTime() onmouseover=openSubMenu( +
   
menuItems[TabOrder] + @) href= + menuItems[TabOrder] + @> Tab +
   
menuItems[TabOrder] + </a> &nbsp; </nobr>;
            
td.Controls.Add(new LiteralControl(HtmlText));
            
// для каждой закладки создаем свою таблицу - подменю
            
td.Controls.Add(SubMenu((int) menuItems[TabOrder]));
            
tr.Controls.Add(td);
          }
         
menuTable.Controls.Add(tr);
        }
        else
// RepeatDirection.Vertical
       
{
         
// иначе формируем столбец
          // (все остальное аналогично)
         
while (menuItems.Read())
          {
            
HtmlTableRow tr = new HtmlTableRow();
            
tr.ID = menu;
            
tr.Attributes.Add(runat, server);
            
HtmlTableCell td = new HtmlTableCell();
            
td.ID = menuItem + menuItems[TabOrder];
            
string HtmlText = @&nbsp; <a onmouseout=closeTime() onmouseover=openSubMenu( +
   
menuItems[TabOrder] + @) href= + menuItems[TabOrder] + @> Tab +
   
menuItems[TabOrder] + </a> &nbsp;;
            
td.Controls.Add(new LiteralControl(HtmlText));
            
td.Controls.Add(SubMenu((int) menuItems[TabOrder]));
            
tr.Controls.Add(td);
            
menuTable.Controls.Add(tr);
          }
        }
      }
      
/// <summary>
      ///   Функция, создающая подменю для нужной закладки
      /// </summary>
      
private HtmlTable SubMenu(int tabOrder)
      {
       
// получаем все закладки для подменю
       
SqlDataReader subMenuItems = data.GetSubMenuItems(tabOrder);
       
// создаем таблицу подменю
       
HtmlTable tbl = new HtmlTable();
       
tbl.ID = subMenu + tabOrder.ToString();
       
tbl.Style.Add(display, none);// скрыта по умолчанию
       
tbl.Style.Add(position, absolute);// появляется поверх всего
  //    tbl.Style.Add(filter, alpha (opacity=75)); // прозрачность
       
tbl.Attributes.Add(cellSpacing, 0);
       
tbl.Attributes.Add(cellPadding, 0);
       
tbl.Attributes.Add(width, 160px);
       
tbl.Attributes.Add(border, 1);
       
tbl.Attributes.Add(bgcolor, white);
       
// назначаем обработчики событий
       
tbl.Attributes.Add(onmouseover, cancelCloseTime());// при наведении курсора
       
tbl.Attributes.Add(onmouseout, closeTime());// при выходе за пределы подменю
        // формируем столбец, состоящий из ссылок
       
while (subMenuItems.Read())
        {
         
HtmlTableRow tr = new HtmlTableRow();
         
HtmlTableCell td = new HtmlTableCell();
         
td.InnerHtml = @&nbsp; <a href= + tabOrder + - + subMenuItems[TabOrder] + @> SubTab
   
tabOrder + - + subMenuItems[TabOrder] + </a> &nbsp;;
         
tr.Cells.Add(td);
         
tbl.Controls.Add(tr);
        }
        return
tbl;// возвращаем готовое подменю
      
}
      
#region Web Form Designer generated code
      
override protected void OnInit(EventArgs e)
      {
         
//
        // CODEGEN: This call is required by the ASP.NET Web Form Designer.
        //
       
InitializeComponent();
       
base.OnInit(e);
      }
      
/// <summary>
      /// Required method for Designer support - do not modify
      /// the contents of this method with the code editor.
      /// </summary>
      
private void InitializeComponent()
      {
       
this.Load += new System.EventHandler(this.Page_Load);
      }
      
#endregion
   
}
  }

Для тестирования нашего меню необходима HTML страница, содержащая наш элемент. Вот HTML код основной формы:

<%@ Register TagPrefix=TabListControl TagName=TabList Src=TabList.ascx %>
  <%@
Page language=c# Codebehind=Default.aspx.cs AutoEventWireup=false Inherits=Daenur.TabList.DefaultForm %>
  <!
DOCTYPE HTML PUBLIC -//W3C//DTD HTML 4.0 Transitional//EN >
  <
HTML>
   <
HEAD>
    <
title>DefaultForm</title>
   </
HEAD>
   <
body MS_POSITIONING=GridLayout>
    <
TABLE height=523 cellSpacing=0 cellPadding=0 width=174 border=0 ms_2d_layout=TRUE>
     <
TR vAlign=top>
      <
TD width=174 height=523>
       <
form id=DefaultForm name=DefaultForm action=Default.aspx method=post>
        <
TABLE height=157 cellSpacing=0 cellPadding=0 width=511 border=0 ms_2d_layout=TRUE>
         <
TR vAlign=top>
          <
TD width=10 height=15></TD>
          <
TD width=501></TD>
         </
TR>
         <
TR vAlign=top>
          <
TD height=142></TD>
          <
TD>
           <
table height=141 cellSpacing=0 cellPadding=0 width=500>
            <
tr>
             <
td width=20></td>
             <
td width=*>
               <
TABLISTCONTROL:TABLIST id=TabList runat=server RepeatDirection=Horizontal></TABLISTCONTROL:TABLIST>
             </
td>
             <
td width=20></td>
            </
tr>
            <
tr>
             <
td width=20></td>
             <
td width=*></td>
             <
td width=20>
             </
td>
            </
tr>
           </
table>
          </
TD>
         </
TR>
        </
TABLE>
       </
form>
      </
TD>
     </
TR>
    </
TABLE>
   </
body>
  </
HTML>

Здесь все просто. Мы создали на форме таблицу и в одну из ее ячеек поместили наш элемент TabList.

Таким образом, получаем само меню в виде таблицы со строкой или столбцом элементов в зависимости от заданного направления и скрытые таблицы – подменю. Видимыми их делает выполнение скрипта при наведении курсора.

Кстати, чтобы поменять направление меню на горизонтальное, достаточно исправить строку в файле Default.aspx:

RepeatDirection=Horizontal на RepeatDirection=Vertical

В результате:



Заключение


Как видите, все довольно просто (а Вы как хотели :)). Я показал, как можно расширить функциональность одностраничного портала, похожего на IBuySpy. Извиняюсь за возможные недочеты. В этом примере показана только суть. Остальное Вы сможете легко реализовать сами. Например, можно прикрутить сюда какую-нибудь графику или просто добавить новые свойства вроде цвета фона. Успехов в изучении новых технологий!



Похожие статьи:
- Интерпретация строковых выражений как функций
- Стиль против дизайна
- Введение в технологию AJAX
- Сложные графики и диаграммы в ASP.NET. Часть пятая – интерактивность.
- Сила параметров XmlElement в Web-методах ASP.NET
- Путеводитель по обмену ссылками
- Частичная проверка правильности ввода данных.
- Postback и Query String - совместить несовместимое
- Секреты правильной раскрутки сайтов
- Средства безопасности ASP.NET. Аутентификация
- Новое в ASP.NET 2. Профили пользователей
- Ожидание выполнения длительного процесса в ASP.NET
- Сайты доноры - источники траффика


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |

Контакты
Редакция:
[0.002]