Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: для новичков > Drag'n'drop slider не успевает за мышью


Автор: goldmember 27.2.2010, 13:45
Обработчик onmousemove прицеплен на img небольшого размера. (действие-изменяет ширину родительского дива) Посмотреть пример можно на ofis.ru/?devel-mode. Соотвестсвенно при резком движении мыши над img соскакивает mousemove и mouseup (В осле тянется, причём как будто с разгоном))). И ещё есть маленький косячок в Опере(здесь как то была тема про косяк с лисой событий mousemove (якобы лиса mouseup игнорит)), дык вот то же самое только работает везде кроме оперы (Прилепить решение к своему примеру не смог).Привожу код(Библиотеки не использую и не хочу)
Код

var isIE=0;isOp=0;isFF=0;
var verBr=navigator.userAgent;
if (verBr.indexOf("Opera")!=-1)
isOp=1;
else
{
if (verBr.indexOf("MSIE")!=-1)
isIE=1;
else isFF=1;
}

var offX;
var knobWidth=9;

function pageInit(){
        var allEl=document.getElementsByTagName('IMG');
        var allSlide=document.getElementsByTagName('TABLE');
        for(var i=0;i<allEl.length;i++){
            allEl[i].onmousedown=handleMouseDown;
        }
        for(var i=0;i<allSlide.length;i++){
            allSlide[i].onclick=sliderClick;        
        }
}


function fixEvent(e) {
    e = e || window.event
    if ( e.pageX == null && e.clientX != null ) {
       var html = document.documentElement
       var body = document.body
       e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0)
       e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0)
    }
    if (!e.which && e.button) {
        e.which = e.button & 1 ? 1 : ( e.button & 2 ? 3 : ( e.button & 4 ? 2 : 0 ) )
    }
       return e
}

function handleMouseDown(e){
        e=fixEvent(e)
        if(e.which!=1) return;
        var movableObject=getMovableObject(this);
        if(movableObject){
            var elem=getParent(movableObject,"TD")
            offX=offsetPosition(movableObject.parentNode);
            if((movableObject.id=="lBegun")||(movableObject.id=="lBegun1"))    
                opposeX=offsetPosition(elem.nextSibling.nextSibling.firstChild.firstChild)
            else
                opposeX=offsetPosition(elem.previousSibling.previousSibling.firstChild.firstChild)
        }
            movableObject.onmousemove=handleMouseMove;
            movableObject.onmouseup=handleMouseUp;
            e.preventDefault();
        return false;
}
        
function handleMouseMove(e){
        var event=fixEvent(e);
        if(event.which!=1) return;
        var movableObject=getMovableObject(this);
        if(movableObject){
            if((movableObject.id!="rBegun")&&(movableObject.id!="rBegun1")){
                if(event.pageX<offsetPosition(movableObject.parentNode)) return false;
                    if (event.pageX>opposeX-4)
                        movableObject.parentNode.style.width=movableObject.parentNode.offsetWidth+"px";    
                    else
                        movableObject.parentNode.style.width=((event.pageX-offX)+Math.ceil(knobWidth/2))+"px";
                if(movableObject.id=="lBegun")
                    document.getElementById('minsq').value=offsetPosition(movableObject)-offsetPosition(movableObject.parentNode);
                else 
                    document.getElementById('minco').value=offsetPosition(movableObject)-offsetPosition(movableObject.parentNode);
            }
            else{
                var tab=document.getElementById('forslide2');
                var tab1=document.getElementById('forslide1');
                var offRight=offsetPosition(tab)+tab.offsetWidth;
                var offRight1=offsetPosition(tab1)+tab1.offsetWidth;
                if(movableObject.id=="rBegun"){
                    if(offRight1<event.pageX) return false;
                    document.getElementById('maxsq').value=offRight1+event.pageX;
                        if(event.pageX<opposeX+knobWidth+4)
                            movableObject.parentNode.style.width=movableObject.parentNode.offsetWidth+"px";
                        else
                            movableObject.parentNode.style.width=(offRight1-event.pageX+Math.ceil(knobWidth/2))+"px"
                }
                else{
                    if((offRight<event.pageX)) return false;
                        if(event.pageX<opposeX+knobWidth+4)
                            movableObject.parentNode.style.width=movableObject.parentNode.offsetWidth+"px";
                        else        
                            movableObject.parentNode.style.width=(offRight-event.pageX+Math.ceil(knobWidth/2))+"px";
                    document.getElementById('maxco').value=offRight+event.pageX;
                }
            }
        }    
        event.preventDefault();
        return false;
}

function handleMouseUp(){
    var movableObject=getMovableObject(this);
    if(movableObject)
        movableObject.onmousemove=null;    
    return false;
}    

function sliderClick(e){
    var event=fixEvent(e);
    var slider=getSlideObject(this);
    if(slider){
        var beg1=document.getElementById('lBegun');
        var beg2=document.getElementById('rBegun');
        var beg3=document.getElementById('lBegun1');
        var beg4=document.getElementById('rBegun1');
        if(slider.id=="forslide2"){
        var right1=offsetPosition(slider)+slider.offsetWidth;
        if((event.clientX-offsetPosition(beg3))<(offsetPosition(beg4)-event.clientX)){
          beg3.parentNode.style.width = (event.clientX-offsetPosition(slider)+Math.round(knobWidth/2))+"px";
          document.getElementById("minco").value=(offsetPosition(beg3)-offsetPosition(slider)+Math.round(knobWidth/2))
        }          
        else{
           beg4.parentNode.style.width = (right1-event.clientX+Math.round(knobWidth/2))+"px";
           document.getElementById("maxco").value=(right1+offsetPosition(beg4)+Math.round(knobWidth/2))
           }
        } 
        if(slider.id=="forslide1"){
        var right=offsetPosition(slider)+slider.offsetWidth;
        if((event.clientX-offsetPosition(beg1))<(offsetPosition(beg2)-event.clientX)){
          beg1.parentNode.style.width = (event.clientX-offsetPosition(slider)+Math.round(knobWidth/2))+"px"; 
          document.getElementById("minsq").value=(offsetPosition(beg1)-offsetPosition(slider)+Math.round(knobWidth/2))
          }
        else{
           beg2.parentNode.style.width = (right-event.clientX+Math.round(knobWidth/2))+"px";
           document.getElementById("maxsq").value=(right+offsetPosition(beg2)+Math.round(knobWidth/2))
           }
        } 
    }
}

function offsetPosition(elem){
    var offsetLeft=0;
    do{
        offsetLeft+=elem.offsetLeft;
    }
    while(elem=elem.offsetParent);
    return offsetLeft;
}
function getMovableObject(object){
    if (object.tagName == "BODY") return null;
    if(object.className=="knob") return object;
    return getMovableObject(object.parentNode);
}
function getSlideObject(object){
    if (object.tagName == "BODY") return null;
    if(object.className=="polzun") return object;
    return getSlideObject(object.parentNode);
}
function getParent(obj, parentTagName) {
    return (obj.tagName==parentTagName)?obj:getParent(obj.parentNode, parentTagName);
}
function getChild(obj,childTagName){
    return(obj.TagName==childTagName)?obj:getChild(obj.firstChild,childTagName);
}
window.onload=pageInit;


Автор: Sartorius 27.2.2010, 13:57
http://webdevelopersjournal.com/articles/jsevents2/jsevents2.html

Автор: goldmember 27.2.2010, 14:09
Изначально хотел без захвата мыши определять при mousedown на картинке mousemove и mouseup на корневой таблице слайдера, но что то не получается(мешает if(movableObject)) Извините, а основные моменты mouse capture на великом и могучем можно услышать?

Автор: mxt 27.2.2010, 18:40
вешай обработчик mousemove и mouseup на корневой элемент. 

Автор: Sartorius 27.2.2010, 18:44
Что бы захватить мышь делаем setCapture() объекту, что бы отпустить releaseCapture()
Пока мышка захвачена все события преходят захватившиму объекту, так что даже если курсор выйдет за границы объекта mouseLeave не будет. Захват для перетаскивания делаем по mouseDown, релиз по mouseUp. Как то так.

Автор: goldmember 28.2.2010, 10:06
Слышал, что при потере фокуса окном mouse capture (скролл и.т.п) начинает шалить(или это только в ослике?). А если вешать события на корневой элемент, то потом просто с детьми работать? Без определения целевого элемента ?

Автор: mxt 28.2.2010, 16:31
Цитата(goldmember @  28.2.2010,  10:06 Найти цитируемый пост)
Слышал, что при потере фокуса окном mouse capture (скролл и.т.п) начинает шалить(или это только в ослике?). А если вешать события на корневой элемент, то потом просто с детьми работать? Без определения целевого элемента ? 

вешать не все же события, при mousedown просто запоминать какой элемент сейчас перетаскивают.
а вот остальные уже на корневой)

Автор: goldmember 1.3.2010, 10:26
Гы, дошло. Я не мог повесить нек. события на корневой элемент, потому что область видимости внешней переменной во внутренней функции не работает если внутреннюю функцию только объявлять во внешней, а не описывать(описывать потом....). Всем огромная благодарность...  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)