О насБлогКонтакты
Технологии22 августа 2001 г. 6 мин 127Обновлено: 22 июня 2026 г.

DHTML-меню в казнете 2001 года: выпадающая навигация без перезагрузки

AunimedaAunimeda
📋 Содержание

К 2001 году казнет вырос. Алматинские компании уже понимали разницу между сайтом-визиткой и профессиональным веб-присутствием. Одним из маркеров «серьёзного» сайта стало выпадающее навигационное меню - наведи курсор на раздел, и подразделы появляются сами, без перезагрузки.

В казахстанских веб-студиях DHTML (Dynamic HTML) осваивали по статьям на JavaScript.ru, Forum.Web.de и книгам Дмитрия Котерова. Реализовать меню, которое работало одновременно в IE5 и Netscape 6, было задачей не тривиальной.


Как это работало: абсолютное позиционирование + display:none

Принцип: подменю - это обычные <div> с position: absolute и display: none. JavaScript показывал их при onmouseover на родительской ссылке и скрывал при onmouseout. Сложность: между ссылкой и подменю - пустой пиксель, который вызывал onmouseout до того, как мышь попадала в меню.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Навигация DHTML - Алматы, 2001</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<style type="text/css">

body { font-family: Arial, Helvetica, sans-serif; font-size: 13px;
       margin: 0; padding: 0; }

/* Навигационная панель */
#nav {
    width: 100%;
    background-color: #003399;
    height: 30px;
    position: relative;
}

.nav-item { position: relative; float: left; }

.nav-item > a {
    display: block;
    padding: 6px 16px;
    color: #ffffff;
    text-decoration: none;
    font-weight: bold;
    font-size: 12px;
    height: 18px;
    line-height: 18px;
}

.nav-item > a:hover { background-color: #0055CC; }

/* Подменю */
.sub {
    position: absolute;
    top: 30px;
    left: 0;
    width: 180px;
    background-color: #FFFFFF;
    border: 1px solid #003399;
    border-top: 3px solid #003399;
    display: none;
    z-index: 200;
}

.sub a {
    display: block;
    padding: 6px 12px;
    color: #333333;
    text-decoration: none;
    font-size: 12px;
    border-bottom: 1px dotted #cccccc;
}

.sub a:hover { background-color: #EEF3FF; color: #003399; }

/* Фиксируем высоту страницы для демонстрации */
.content { padding: 20px; }

</style>
</head>
<body>

<div id="nav">

  <div class="nav-item">
    <a href="about.asp"
       onmouseover="openSub('sub-about')"
       onmouseout="closeSub('sub-about')">О компании &#9660;</a>
    <div class="sub" id="sub-about"
         onmouseover="keepSub('sub-about')"
         onmouseout="closeSub('sub-about')">
      <a href="about/history.asp">История компании</a>
      <a href="about/team.asp">Руководство</a>
      <a href="about/partners.asp">Партнёры</a>
      <a href="about/licenses.asp">Лицензии</a>
    </div>
  </div>

  <div class="nav-item">
    <a href="services.asp"
       onmouseover="openSub('sub-services')"
       onmouseout="closeSub('sub-services')">Услуги &#9660;</a>
    <div class="sub" id="sub-services"
         onmouseover="keepSub('sub-services')"
         onmouseout="closeSub('sub-services')">
      <a href="services/audit.asp">Аудит</a>
      <a href="services/consulting.asp">Консалтинг</a>
      <a href="services/outsourcing.asp">Аутсорсинг</a>
    </div>
  </div>

  <div class="nav-item">
    <a href="contacts.asp"
       onmouseover="openSub('sub-contacts')"
       onmouseout="closeSub('sub-contacts')">Контакты &#9660;</a>
    <div class="sub" id="sub-contacts"
         onmouseover="keepSub('sub-contacts')"
         onmouseout="closeSub('sub-contacts')">
      <a href="contacts/almaty.asp">Алматы (гл. офис)</a>
      <a href="contacts/astana.asp">Астана</a>
      <a href="contacts/form.asp">Написать нам</a>
    </div>
  </div>

</div>

<div class="content">
  <h2>Добро пожаловать</h2>
  <p>Наведите курсор на пункты меню выше.</p>

  <!-- Тестовый select для проверки z-index проблемы IE5 -->
  <select>
    <option>Тест z-index (IE5 баг)</option>
    <option>Астана</option>
    <option>Алматы</option>
  </select>
</div>

<script type="text/javascript">
// DHTML-меню для казнета, 2001 год
// Тестировалось в IE 5.0/5.5 и Netscape 6.1

var timers = {};   // таймеры задержки закрытия

// Открыть подменю
function openSub(id) {
    closeAll();
    var el = document.getElementById(id);
    if (el) el.style.display = 'block';
    cancelClose(id);

    // Создать iframe-shim для IE5 (z-index поверх select)
    createShim(el);
}

// Держать подменю открытым (мышь вошла в него)
function keepSub(id) {
    cancelClose(id);
}

// Запланировать закрытие с задержкой
function closeSub(id) {
    if (timers[id]) clearTimeout(timers[id]);
    timers[id] = setTimeout(function() {
        var el = document.getElementById(id);
        if (el) {
            el.style.display = 'none';
            removeShim(el);
        }
        timers[id] = null;
    }, 300);
    // 300 мс - протестировано на казахстанских офисных машинах 2001 года.
    // Трекболы и старые мыши требовали не меньше 250-300 мс.
}

function cancelClose(id) {
    if (timers[id]) { clearTimeout(timers[id]); timers[id] = null; }
}

function closeAll() {
    var divs = document.getElementsByTagName('div');
    for (var i = 0; i < divs.length; i++) {
        if (divs[i].className === 'sub') {
            divs[i].style.display = 'none';
        }
    }
}

// ---- IE5 iframe shim ----
// Без него подменю уходит ПОД select-элементы в IE5/IE6
// В Netscape 6 эта проблема отсутствует

var shims = {};

function createShim(menuEl) {
    if (!menuEl) return;
    if (!document.createElement) return;  // старые браузеры - пропустить

    var shimId = 'shim_' + menuEl.id;
    if (shims[shimId]) {
        shims[shimId].style.display = 'block';
        return;
    }

    var shim = document.createElement('iframe');
    shim.id            = shimId;
    shim.src           = 'about:blank';
    shim.scrolling     = 'no';
    shim.frameBorder   = '0';
    shim.style.position = 'absolute';
    shim.style.border   = 'none';
    shim.style.zIndex   = '199';  // под меню (200), над select

    // Позиционируем и размещаем поверх того же места
    shim.style.left   = menuEl.style.left   || '0px';
    shim.style.top    = menuEl.style.top    || '30px';
    shim.style.width  = '180px';
    shim.style.height = '150px';  // примерная высота подменю

    // Прозрачность для IE
    if (shim.style.filter !== undefined) {
        shim.style.filter = 'alpha(opacity=0)';
    }

    menuEl.parentNode.insertBefore(shim, menuEl);
    shims[shimId] = shim;
}

function removeShim(menuEl) {
    if (!menuEl) return;
    var shimId = 'shim_' + menuEl.id;
    if (shims[shimId]) {
        shims[shimId].style.display = 'none';
    }
}

// Закрывать меню при клике в любом месте страницы
document.onclick = function() { closeAll(); };
</script>

</body>
</html>

Проблемы с z-index: специфика IE5 в казнете

В IE5 абсолютно позиционированные блоки всегда отображались ПОД элементами <select>. Это был баг именно Microsoft IE - в Netscape 6 всё работало правильно. Но аудитория казнета в 2001 году использовала IE5 как основной браузер.

// Диагностика проблемы в консоли:
// Если меню уходит под select - нужен iframe shim

// Простой тест: есть ли в IE активный z-index баг?
var isIE = document.all && !window.opera;
// document.all - IE-специфичный объект
// window.opera - Netscape/Opera наличие
if (isIE) {
    // В IE5/6 применяем шим
    // В Netscape 6 - z-index работает корректно
}

Именно из-за этого бага казахстанские разработчики 2001 года нередко делали сайты без <select> на страницах с навигационным меню - или ставили <select> в нижней части страницы вдали от навбара.


DHTML и кодировка windows-1251

Одна тонкость: текст в JavaScript-строках через DHTML должен был быть в той же кодировке, что и страница. Для казнета 2001 года - windows-1251:

<!-- Страница в windows-1251 -->
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">

<script type="text/javascript">
// Строки в коде тоже windows-1251 - кириллица работает
var menuLabels = ['О компании', 'Услуги', 'Контакты'];
// showStatus() с кириллицей тоже работал в IE5 windows-1251
</script>

Если JavaScript-файл был в KOI8-R, а страница в windows-1251 - кириллица в статусной строке и тултипах превращалась в кракозябры. Проблема, которую начинающие разработчики в Алматы 2001 года встречали регулярно.


Наследие DHTML в современной казахстанской веб-разработке

К 2005 году jQuery убрал необходимость писать этот код вручную. К 2010 году - CSS3-переходы, :hover на блочных элементах и чистый CSS-дропдаун стали стандартом. К 2020 году - React-компоненты.

Но паттерн не изменился: setTimeout на 300 мс перед закрытием меню используют современные библиотеки UI-компонентов. Проблема z-index исчезла в браузерах примерно в 2007-2008 году - сразу после выхода IE7, исправившего этот баг. Инлайновые обработчики событий уступили место addEventListener. Суть осталась прежней.

Те, кто писал DHTML в казнете в 2001 году, получили фундаментальное понимание того, как браузер рендерит DOM и обрабатывает события. Этот фундамент не устарел - он остаётся основой фронтенд-разработки в 2026 году.

Читайте также

Казнет в 2002: первые корпоративные сайты Казахстана - IE5, Netscape и dial-up реалииaunimeda
Технологии

Казнет в 2002: первые корпоративные сайты Казахстана - IE5, Netscape и dial-up реалии

В 2002 году казахстанский интернет насчитывал около 200 тысяч пользователей. Иметь корпоративный сайт - было признаком солидности. Сделать его - означало работать с IE5, Netscape 4, кодировкой windows-1251 и картинками не тяжелее 15 КБ. Вот как это было.

Classic ASP и первые системы авторизации в казнете (2000)aunimeda
Технологии

Classic ASP и первые системы авторизации в казнете (2000)

В 2000 году корпоративные сайты Казахстана переходили от статического HTML к динамическим приложениям. Компании, работавшие с Windows-серверами, выбирали ASP. Первая задача - система входа с сессиями и SQL Server. Полный код и реалии разработки в Алматы 2000 года.

Java-апплеты в казнете 1999 года: когда интерактивность стоила минут загрузкиaunimeda
Технологии

Java-апплеты в казнете 1999 года: когда интерактивность стоила минут загрузки

В 1999 году Java-апплеты были самым продвинутым способом сделать сайт интерактивным. На dial-up 33 кбит/с ждать загрузки JVM 30-60 секунд - обычное дело. Мы это делали. Вот код и честный разбор: что работало, что нет, и почему Flash всё равно выиграл.

Нужна IT-разработка для вашего бизнеса?

Разрабатываем сайты, мобильные приложения и AI-решения для бизнеса в Казахстане. Бесплатная консультация.

Получить консультацию Все статьи