[Решено. Кому интересно - могу выложить код] Как временно запретить событие onclick дочернего элемента? (JavaScript)

Модератор: Модераторы разделов

Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

[Решено. Кому интересно - могу выложить код] Как временно запретить событие onclick дочернего элемента?

Сообщение eddy »

Может, кто-нибудь занимался подобным? Мне нужна контекстная справка. После активации режима справки при щелчке на любом элементе должна вызываться функция, рисующая div с подсказкой. При этом, естественно, нужно отменить действие по умолчанию для этого элемента. Но проблема в том, что событие onclick передается от дочернего элемента к родительскому, т.е. сначала выполняется onclick для элемента, по которому мы щелкаем.
Для временной отмены такого действия я сделал "велосипед"

Код: Выделить всё

function startHelp(evt){
   evt.stopPropagation();
   evt.preventDefault();
   document.body.style.cursor = "help";
   document.body.onclick = Help;
   document.body.onmouseover = stoponclick;
}

function Help(evt){
   evt.stopPropagation();
   evt.preventDefault();
   document.body.onclick = '';
   document.body.style.cursor = "default";
   document.body.onmouseover = '';
   alert('id='+evt.target.id+' name='+evt.target.name);
}

var oldclc, oldmout;
function stoponclick(evt){
   var obj = evt.target;
   if(obj == document.body) return;
   oldclc = obj.onclick;
   oldmout = obj.onmouseout;
   obj.onclick = Help;
   obj.onmouseout = releaseonclick;
   obj.style.cursor = "help";
}
function releaseonclick(evt){
   var obj = evt.target;
   obj.onmouseout = oldmout;
   obj.onclick = oldclc;
   obj.style.cursor = "default";
}

Действие отменяется, но при щелчке на элементах вроде checkbox'а и пр. все равно сначала происходит активация этого элемента (которая, правда, после вызова функции отменяется). Возможно ли сделать какое-нибудь элегантное решение?

И вдогонку еще вопрос: есть у меня элементы, к примеру

Код: Выделить всё

<input type='checkbox' name='mask' value='8' OnChange='chkvals();' id='Moth'>прочее<br>

id относится только к checkbox'у, но не к тексту "прочее". Можно ли без дополнительных div'ов или span'ов сделать так, чтобы и текст имел id checkbox'а, к которому он относится (ИМХО, это вполне логично)?
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: [Решено. Кому интересно - могу выложить код] Как временно запретить событие onclick дочернего элемента?

Сообщение serzh-z »

eddy
eddy писал(а):
03.06.2010 16:21
Но проблема в том, что событие onclick передается от дочернего элемента к родительскому
Это зависит от браузера: в IE события распространяются в одну сторону, в нормальных браузерах - в другую.

Нормальным решение было бы в Help() проверять режим - если справка уже отображена - ничего больше не делать или же скрывать старую справку и отображрать справку для нового элемента.

Можно при отображении контейнера со справкой, предварительно подкладывать под него другой контейнер (с z-index больше 0 и меньше z-index контейнера тултипа) с прозрачным контентом, который будет перехватывать и игнорировать все клики (и не только их - события выделения текста и прочее).
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: [Решено. Кому интересно - могу выложить код] Как временно запретить событие onclick дочернего элемента?

Сообщение eddy »

Ничего не понимаю с этим java script: теперь никакие "галочки" при нажатии на них не отмечаются, подсказка выдается.
Но! Стоит мне добавить строку удаления уже отображенной подсказки при повторном нажатии на ссылку "справка", как ничего не работает (курсор меняет форму, но подсказки нет), если же я эти строки удаляю (здесь они закомментированы), все работает. Причем ни один из тестовых alert'ов не появляется.

Код: Выделить всё

function helptip(evt){
/*    var tmp = document.getElementById('helptip');
    if(typeof(tmp) != "undefined"){
        document.body.removeChild(tmp);
        alert(typeof(tmp));
    }
    else alert('do');*/
    tipobj = document.createElement("DIV");
    tipobj.id = 'helptip';
    tipobj.onclick = rmtip;
    tipobj.className = "tooltip";
    document.body.appendChild(tipobj);
    tipobj.innerHTML = helpgen(evt);
    releaseonclick(evt);
    positiontip(evt);
}

Чудеса в решете :(
В общем, сейчас у меня вот что (пока вместо подсказки отображается только id и name элемента, по которому щелкнули):

Код: Выделить всё

var tipobj;
function startHelp(evt){
    evt.stopPropagation();
    evt.preventDefault();
    document.body.style.cursor = "help";
    document.body.onclick = Help;
    document.body.onmouseover = stoponclick;
}
function Help(evt){
    evt.stopPropagation();
    evt.preventDefault();
    document.body.onclick = '';
    document.body.style.cursor = "default";
    document.body.onmouseover = '';
    helptip(evt);
}
var oldclc, oldmout;
function stoponclick(evt){
    var obj = evt.target;
    if(obj == document.body) return;
    oldclc = obj.onclick;
    oldmout = obj.onmouseout;
    obj.onclick = Help;
    obj.onmouseout = releaseonclick;
    obj.style.cursor = "help";
}
function releaseonclick(evt){
    var obj = evt.target;
    obj.onmouseout = oldmout;
    obj.onclick = oldclc;
    obj.style.cursor = "default";
}
function helptip(evt){
    tipobj = document.createElement("DIV");
    tipobj.id = 'helptip';
    tipobj.onclick = rmtip;
    tipobj.className = "tooltip";
    document.body.appendChild(tipobj);
    tipobj.innerHTML = helpgen(evt);
    releaseonclick(evt);
    positiontip(evt);
}

function helpgen(evt){
    var objid = evt.target.id, objname = evt.target.name;
    return ("id="+objid+" name="+objname);
}

function positiontip(e){
    var wd = tipobj.offsetWidth, ht = tipobj.offsetHeight;
    var curX = e.clientX + 25;
    var curY = e.clientY - ht/2;
    var btmedge = document.body.clientHeight - curY - 15;
    var rightedge = document.body.clientWidth - curX - 15;
    if(rightedge < wd) curX -= wd+50;
    if(btmedge < ht) curY -= ht-btmedge+15;
    if(curY < 15) curY = 15;
    tipobj.style.left = curX+"px";
    tipobj.style.top = curY+"px";
}

function rmtip(evt){
    document.body.removeChild(evt.target);
}


И остается вопрос про текст к checkbox'ам и radio: неужели каждую надпись придется в свой span оформлять?

P.S. В принципе, можно проверять id и name элемента, и, если ни того, ни другого нет - идти вверх по иерархии.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали: