<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; JavaScript: Выпадающее меню]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=1005</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=1005&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «JavaScript: Выпадающее меню».]]></description>
		<lastBuildDate>Sat, 29 Dec 2007 21:00:28 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[JavaScript: Выпадающее меню]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=7504#p7504</link>
			<description><![CDATA[<p>Пример простого выпадающего меню, можно настроить (переписать) под разные цели и задачи.<br />Меню работает в различных популярных браузерах (IE, Opera, FireFox).<br /></p><div class="codebox"><pre><code>&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot;&gt;
// Объявление глобальных переменных
var DOM = (typeof(document.getElementById)!=&#039;undefined&#039;);
var menu_div, _menu_a, div_i = null;

var js =
{
    // addEvent - функция добавления события 
    /* Пример вызова: js.addEvent(document,&#039;click&#039;,menu.check);
    document - объект, которому назначается событие
    click - название события
    menu.check - имя функции (ВАЖНО: при использовании конструкции вроде js.addEvent(document,&#039;click&#039;,function(){alert(&#039;сообщение&#039;)});) - это событие не удаляется!!!
    */
    addEvent: function(el, evname, func){
        if(el.attachEvent) // IE
            el.attachEvent(&#039;on&#039; + evname, func);
        else if(el.addEventListener) // Gecko / W3C
            el.addEventListener(evname, func, false);
        else
            el[&#039;on&#039; + evname] = func;
    },
    
    // addEvent - функция удаления события
    // Пример вызова: аналогично предыдущей функции (если необходимо удалить созданное событие - объект, имя события и имя функции должны совпадать)
    removeEvent: function(el, evname, func){
        if(el.detachEvent) // IE
            el.detachEvent(&#039;on&#039; + evname, func);
        else if(el.removeEventListener) // Gecko / W3C
            el.removeEventListener(evname, func, false);
        else
            el[&#039;on&#039; + evname] = null;
    },
    
    /* Функция получения коодринат местоположения объекта на странице (el - объект, который анализируем)
    функция возвращает ассоциативный массив со значениями положения объекта
        Элементы массива:
        &#039;top&#039; - расстояние в пикселях от верхнего края объекта до верхней точки документа
        &#039;left&#039; - расстояние в пикселях от левого края объекта до левого края документа
        &#039;right&#039; - расстояние в пикселях от нижнего края объекта до верхней точки документа
        &#039;bottom&#039; - расстояние в пикселях от правого края объекта до левого края документа
         */
    GetRealPos: function(el){
        if(!el || !el.offsetParent)
            return false;
        var res=Array();
        res[&#039;left&#039;] = el.offsetLeft;
        res[&#039;top&#039;] = el.offsetTop;
        var objParent = el.offsetParent;
        while(objParent.tagName != &#039;BODY&#039;){
            res[&#039;left&#039;] += objParent.offsetLeft;
            res[&#039;top&#039;] += objParent.offsetTop;
            objParent = objParent.offsetParent;
        }
        res[&#039;right&#039;] = res[&#039;left&#039;] + el.offsetWidth;
        res[&#039;bottom&#039;] = res[&#039;top&#039;] + el.offsetHeight;
        
        return res;
    }
}

// Объект выпадающего меню.
var menu =
{
    // Метод show - вызывает меню
    /* Получает параметры:
    obj - необходимо передавать объект, относительно которого будет рисоваться меню
    arr - массив определённой структуры:
        в данном случае [[&#039;иконка&#039;,&#039;название пункта&#039;,&#039;ссылка&#039;],[&#039;иконка&#039;,&#039;название пункта&#039;,&#039;ссылка&#039;]]
    Пример вызова: onClick=&quot;menu.show(this,[[&#039;images/open.gif&#039;,&#039;Просмотр&#039;,&#039;/menu/#open&#039;],[&#039;images/child.gif&#039;,&#039;Создать подкатегорию&#039;,&#039;/menu/#child&#039;]])&quot;
    */
    show: function(obj,arr){
        if(div_i)div_i.className = &#039;menu_img&#039;;
        menu_div = document.getElementById(&#039;menu&#039;);
        _menu_a = document.getElementById(&#039;menu_a&#039;);
        if(!arr){_menu_a.innerHTML = &#039;&#039;;}
        div_i = obj;
        div_i.className = &#039;menu_img_hover&#039;;
        pos = js.GetRealPos(obj);
        _menu = menu_div;
        _menu.style.top = pos.top + 9;
        _menu.style.left = pos.left + 28;
        if(arr){
            _menu_a.innerHTML = menu.initFunc(arr);
        }
        else{return;}
        _menu_pos = js.GetRealPos(_menu);        
        _menu.style.display = &#039;block&#039;;
        js.addEvent(document,&#039;click&#039;,menu.check);
        js.addEvent(document,&#039;keypress&#039;,menu.press);        
    },
    
    hide: function(){
        menu_div.style.display = &#039;none&#039;;
        div_i.className = &#039;menu_img&#039;;
        js.removeEvent(document, &#039;click&#039;, menu.check);
        js.removeEvent(document, &#039;keypress&#039;, menu.press);
    },
    
    /* Метод initFunc - описывает правила для обработки массива и генерации html кода - описывается отображение пунктов меню
    Этот метод не вызывается извне объекта menu
    Получает параметры:
    arr - массив определённой структуры:
        в данном случае [[&#039;иконка&#039;,&#039;название пункта&#039;,&#039;ссылка&#039;],[&#039;иконка&#039;,&#039;название пункта&#039;,&#039;ссылка&#039;]]
    */
    initFunc: function(arr){
        var html = &#039;&lt;table&gt;&#039;;
        for(i in arr){
            im = &quot;gray_pic.gif&quot;;
            // Условие определяет какую картинку использовать, в зависимости от того, какой это пункт - первый или последний
            if(arr.length!=1){
                if(i==0){im = &quot;s_menu_f.gif&quot;;}
                else if(parseInt(i)+1==arr.length){im = &quot;s_menu_l.gif&quot;;}
            }
            else{
                im = &quot;s_menu.gif&quot;;
            }
            // Здесь в переменную html добавлется по одной строке, соответственно здесь и настраивается вид пунктов меню
            html += &#039;&lt;tr&gt;&lt;td height=&quot;30&quot;&gt;&lt;img src=&quot;&#039;+arr[i][0]+&#039;&quot; style=&quot;margin:0px 6px 7px 9px&quot; alt=&quot;&quot;&gt;&lt;img src=&quot;images/&#039;+im+&#039;&quot; class=&quot;s_im&quot; alt=&quot;&quot;&gt;&lt;/td&gt;&lt;td valign=&quot;middle&quot;&gt;&lt;a class=&quot;menu_a&quot; href=&quot;&#039;+arr[i][2]+&#039;&quot;&gt;&#039;+arr[i][1]+&#039;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&#039;;
        }
        html += &#039;&lt;/table&gt;&#039;;
        return html;
    },
    
    // Метод press - скрывает меню при нажатии определённой клавиши, в данном случае - Esc
    press: function(e){
        if(!e) e = window.event;
        if(!e) return;
        if(e.keyCode == 27)
            menu.hide();
    },
    
    // Метод check - проверяет - нужно ли скрывать меню или нет.
    // В данном случае метод вызывается при кликании мышью, если координаты &quot;клика&quot; не совпадают с координатами меню и каких-либо объектов, то меню закрывается!
    check: function(e){
        if(!div_i)
            return;
        var x = e.clientX + document.body.scrollLeft;
        var y = e.clientY + document.body.scrollTop;
        /*menu_button region*/
        if(div_i){
            var pos = js.GetRealPos(div_i);
            if(x &gt;= pos[&#039;left&#039;] &amp;&amp; x &lt;= pos[&#039;right&#039;] &amp;&amp; y &gt;= pos[&#039;top&#039;] &amp;&amp; y &lt;= pos[&#039;bottom&#039;])
                return;
        }
        /*menu region*/
        if(_menu){
            var pos = js.GetRealPos(_menu);
            if(x &gt;= pos[&#039;left&#039;] &amp;&amp; x &lt;= pos[&#039;right&#039;] &amp;&amp; y &gt;= pos[&#039;top&#039;] &amp;&amp; y &lt;= pos[&#039;bottom&#039;])
                return;
        }
        menu.hide();
    },
    
    // Методы over и out - используются в данном случае для определения имени css класса, который нужно присвоить картинке, используется в частных случаях.
    over: function(){
        if(!div_i)
            return;
        div_i.className = &#039;menu_img_hover&#039;;
    },
    
    out: function(obj){
        if(!obj)
            return;
        _menu = menu_div;
        if(!_menu || obj!=div_i){obj.className = &#039;menu_img&#039;;}
        else{
            if(_menu.style.display != &#039;block&#039;){obj.className = &#039;menu_img&#039;;}
        }
    }
}
&lt;/script&gt;</code></pre></div><p>Пример использования меню можно посмотреть <a href="http://shotman0.xost.ru/example/">здесь</a> или во вложении этого поста.</p><p>Недостатки:<br />- Если не будет работать javascript - ссылки не будут видны (поэтому многие меню основаны на заранее описанных списках LI);<br />- Для создания многоуровнего меню необходимо дописывать методы, добавлять новые, т.е. скрипт не предусматривает изначально многоуровневые выпадающие меню.</p>]]></description>
			<author><![CDATA[null@example.com (Санёк)]]></author>
			<pubDate>Sat, 29 Dec 2007 21:00:28 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=7504#p7504</guid>
		</item>
	</channel>
</rss>
