Всем привет! Пишу компонент и потихоньку осваиваю mootools. При создании своего контекстного меню обнаружились две проблемы: 1) Следом за моим меню открывается системное, и заслоняет моё. 2) Не могу понять, как создать событие (что-то вроде onblur), чтобы меню закрывалось после клика где-то за его пределами. Код прилагаю. Код (PHP): //показать window.addEvent('domready', function(){ $ES('a','editcell').addEvent('mousedown', function(event){ //нажата кнопка мыши if(event.button==2) //код кнопки- 2 (правая) $('ddmenu2').setStyles({top: event.pageY+"px", left: event.pageX+"px", display:'block'}); //задать координаты и вывести. ddmenu2 - идентификатор блока меню return false; //вроде бы это должно блокировать системное меню? }); }); //скрыть. Тут была попытка создать onblur, но она не удалась window.addEvent('domready', function(){ //скрыть меню, если был клик за его пределами $('ddmenu2').addEvent('blur', function(){$('ddmenu2').setStyles({display:'none'});}); }); Наверняка здесь есть спецы по mootools. Буду благодарен за любую подсказку.
onBlur - насколько мне известно - это получение фокуса. Вам нужно узнать на каком элементы было совершено событие "клик". и если это не ddmenu2, то скрыть его.
Спасибо, буду знать. Эта проблема отпала - знакомый помог адаптировать ContextMenu к mootools 1.1. Но есть другая: у меня на странице DOM создается динамически, и когда инициализируется класс меню, то он не учитывает элементы, которые появляются позже, и ContextMenu для них не срабатывает. Как лучше выйти из положения? Есть специальное событие? P.s. с тултипами получилось просто: Код (PHP): JTooltips = new Tips($$('.hasTip'), { maxTitleChars: 50, fixed: false}); //это после рендеринга страницы, JTooltips+= new Tips($$('.hasTip'), { maxTitleChars: 50, fixed: false}); //это после создания новых элементов. А с ContextMenu так не прокатило: белиберда вышла.
Дело в том, что вы используете событие domready для навешивания других обработчиков, т.е. после того как страница полностью загрузилась и все дом-элементы известны js навешивает описанные Вами обработчики. Т.о. в результате работы аякса или любого другого скрипта, который добавляет дом-элементы, вновь созданные дом-элементы не будут иметь никаких обработчиков. Вот небольшой пример Код (CODE): window.addEvent('domready', function(){ //добавляем элемент в дом $("div0").addEvent('click', function()) { $(this).set('html', '<div id="div1">bla bla bla</div>') } myEvents(); // вешаем на новый элемент обработчик }); function myEvents() { $("div1").addEvent('click', function()) { alert('Hi'); } } Т.е. после того, как мы добавили новые элементы, на них нужно по вешать обработчики.
Да, я знаю, в чем проблема. Но не понимаю, как её решить, т.е. как правильно переопределить классы, которые вешают события, при изменении дерева. Когда я переопределяю в конце функции, которая добавляет элементы Код (PHP): context = null; context = new ContextMenu({ targets: '.contextElement', menu: 'contextmenu', actions: { copy: function(element,ref) { alert(element.id); return false; } }, offsets: { x:0, y:0 } }); то пункты меню при клике (функция copy) срабатывают дважды - alert выводит сначала ID родителя, а потом самого элемента. А если включить все дочерние элементы в HTML-код, то выводится только ID элемена, из чего я дклаю вывод, что переопределяю класс как-то не так...
а зачем вы его определяете два раза ? если событие вам нужно только после того как загрузиться меню ?
Сейчас поясню. На странице есть некий список категорий (UL). К каждой из них привязаны некие операции, которые прописаны в контекстном меню. По дабл-клику подгружается содержимое категории, и создается новый вложенный UL (вложенность не ограничена). То есть, контекстное меню используется и для статичных элементов списка и для подгружаемых.
ну тогда Вам нужно при создании нового дочернего элемента записывать экземпляр класса в новую переменную, например context1, context2 ... contextN . соответственно у вас и target будет меняться на дочерние элементы.
Тогда такой вопрос: как создать переменную с уникальным именем? Сорри, если вопрос нубийский, но я правда не знаю Да, и еще. Там ведь по идее надо создавать класс только для дочерних элементов, для которых обработчиков пока нет, чтобы не получился говнокод, забивающий память? Верно говорю?
так....во первых - в последней версии плагина, при нажатии левой кнопкой мыши за пределами меню - меню исчезает. во вторых - я не до конца понял суть вопроса - вы создаете динамически элементы и потом хотите повешать на них контекстное меню ?
1) Так и есть. Просто сначала я хотел написать свой сценарий, а потом взял готовый плагин. Оттуда и вопрос был 2) Именно так.
Код (html): <div id="editcell"> <ul> <li class="caregory"> <a class="hasTip contextElement" id="category1" title="Категория::Тестовая категория">Категория</a> </li> <li class="caregory"> <a class="hasTip contextElement" id="category2" title="Лайнтекс::Тестовая категория">Лайнтекс</a> </li> <li class="caregory"> <a class="hasTip contextElement" id="category3" title="Венера::Тестовая категория">Венера</a> </li> </ul> </div> <ul id="contextmenu"> <li><a href="#edit" class="edit">Изменить</a></li> <li class="separator"><a href="#cut" class="cut">Вырезать</a></li> <li><a href="#copy" class="copy">Копировать</a></li> <li><a href="#paste" class="paste">Вставить</a></li> <li><a href="#delete" class="delete">Удалить</a></li> <li class="separator"><a href="#quit" class="quit">Отмена</a></li> </ul> А это скрипт, который им управляет Код (CODE): function createItem(where,html,id,tip){ var newLi = new Element ('li',{'class' : 'caregory'}); var newA = new Element ('a',{'class' : 'hasTip contextElement','id' : id,'title' : tip}); newA.appendText(html); newLi.appendChild(newA); where.appendChild(newLi); } function removeItem(element){ element.parentNode.removeChild(element); $ES('a','editcell').addEvent('click', selectCategory); $ES('a','editcell').addEvent('dblclick', openCategory); } window.addEvent('domready', function(){ JTooltips = new Tips($$('.hasTip'), { maxTitleChars: 50, fixed: false}); } ); window.addEvent('domready', function(){ $ES('a','editcell').addEvent('click', selectCategory); }); window.addEvent('domready', function(){ $ES('a','editcell').addEvent('dblclick', openCategory); }); window.addEvent('domready', function() { //create a context menu context = new ContextMenu({ targets: '.contextElement', menu: 'contextmenu', actions: { copy: function(element,ref) { alert(element.id); return false; } }, offsets: { x:0, y:0 } }); }); function selectCategory(){ var thisUL = this.parentNode; if(thisUL.hasClass('selected')){ thisUL.removeClass('selected'); }else{ thisUL.addClass('selected'); } return false; } function openCategory(){ var thisUL = this.parentNode; if(thisUL.hasClass('open')){ thisUL.removeClass('open'); removeItem(thisUL.getElementsByTagName('UL')[0]); }else{ thisUL.addClass('open'); var newUl = new Element ('ul'); createItem(newUl,'createItem','createItem1','createItem1::Succesfull'); createItem(newUl,'createItem2','createItem2','createItem2::Succesfull'); createItem(newUl,'createItem3','createItem3','createItem3::Succesfull'); thisUL.appendChild(newUl); $ES('a','editcell').addEvent('click', selectCategory); $ES('a','editcell').addEvent('dblclick', openCategory); JTooltips+= new Tips(newUl.getElementsByClassName('hasTip'), { maxTitleChars: 50, fixed: false}); //create a context menu context = null; context = new ContextMenu({ targets: '.contextElement', menu: 'contextmenu', actions: { copy: function(element,ref) { alert(element.id); return false; } }, offsets: { x:0, y:0 } }); } return false; }
Наверно, придется забить на mootools и на плагин и написать свой обработчик. Этот в опере не работает вообще никак
у Вас в <div id="editcell"> ... </div> динамически создаются элементы списка и на них вы хотите повешать контекстное меню ?
Ага. Вот так: Код (html): <div id="editcell"> <ul> <li class="caregory"> <a class="hasTip contextElement" id="category1" title="Категория::Тестовая категория">Категория</a> <ul> <li class="caregory"> <a class="hasTip contextElement" id="newcategory1" title="Новая1::Тестовая категория">Новая1</a> </li> <li class="caregory"> <a class="hasTip contextElement" id="newcategory2" title="Новая2::Тестовая категория">Новая2</a> </li> <li class="caregory"> <a class="hasTip contextElement" id="newcategory3" title="Новая3::Тестовая категория">Новая3</a> </li> </ul> </li> <li class="caregory"> <a class="hasTip contextElement" id="category2" title="Лайнтекс::Тестовая категория">Лайнтекс</a> </li> <li class="caregory"> <a class="hasTip contextElement" id="category3" title="Венера::Тестовая категория">Венера</a> </li> </ul> </div>
Ну да, типа того. А верно или нет, становится понятно, когда функция, прикрепленная к пунктк меню, работает не с искомым элементом, а с каким-нибудь другим. Например, когда вешал на copy function(element, ref){ alert(element.id); return false; } то выводилась целая куча ID и при этом страница несколько раз перезагружалась ))