Как заставить мою функцию JavaScript остановиться после нахождения первого родителя с определенным классом? - PullRequest
1 голос
/ 27 февраля 2011

В настоящее время я создаю движок Drag-and-Drop в JavaScript.В настоящее время я работаю над созданием «границ» для некоторых «перетаскиваемых» объектов.Перетаскиваемый объект имеет границы, если его родитель (или родитель родительского т. Д.) Имеет класс .bound.Функция, которую я использую, чтобы выяснить, ограничен ли перетаскиваемый объект (Да, эта функция также создает перетаскиваемый объект.):

function makeObj(e) {
    obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    var curleft = curtop = 0;
    if (e.offsetParent) {
        do {
            curleft += e.offsetLeft;
            curtop += e.offsetTop;
            //alert(e.id + ":" + e.innerHTML);
            if(~e.className.search(/bound/)) {
                obj.boundX = curleft - obj.element.offsetLeft;
                obj.boundY = curtop - obj.element.offsetTop;
                return obj;
            }

        } while (e = e.offsetParent);
    }

    return obj;
}

Для пояснения: эта функция ДЕЛАЕТ перетаскиваемый объект.Моя проблема заключается в петлях.Циклы не находят первый родительский узел с классом .bound.

Этот html "должен" влиять на функцию:

<div id="center" class="bound">
    <h1>Hello World! <hr /></h1>
    <div id="box" class="bound">
        <p class="drag square" id="one"> One </p>
        <p class="drag square" id="two"> Two </p>
    </div>
</div>

Столько, сколько этот html:

<div id="center"> <!-- Difference is here -->
    <h1>Hello World! <hr /></h1>
    <div id="box" class="bound">
        <p class="drag square" id="one"> One </p>
        <p class="drag square" id="two"> Two </p>
    </div>
</div>

Однако первый html влияет на циклы (и как ведут себя объекты перетаскивания), и я не знаю почему.

PS Функция немного нарушена.Мне не удалось установить «правильное» значение для obj.boundX и obj.boundY без использования этого подчиненного (потому что это делает parentNode связанным элементом независимо от класса):

function makeBoundlessObj(e) {
    obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    return obj;
}

Я будуопубликуйте весь движок ниже (и ссылку jsfiddle) на всякий случай, если это будет полезно:

http://jsfiddle.net/Upvdm/1/

// JavaScript Document

var dragObj;

document.addEventListener("mousedown", down, false);

function down(event) {
    if(~event.target.className.search(/drag/)) {
        dragObj = makeObj(event.target);
        dragObj.element.style.zIndex="100";
        document.addEventListener("mousemove", freeMovement, false);
    }
}

function freeMovement(event) {

    if (typeof(dragObj.element.mouseup) == "undefined")
        document.addEventListener("mouseup", drop, false);
    //Prevents redundantly adding the same event handler repeatedly

dragObj.element.style.left = Math.max(0, Math.min(event.clientX - dragObj.posX, dragObj.boundX)) + "px";
    dragObj.element.style.top = Math.max(0, Math.min(event.clientY - dragObj.posY, dragObj.boundY)) + "px";
}

function drop() {
    dragObj.element.style.zIndex="1";

    document.removeEventListener("mousemove", freeMovement, false);
    document.removeEventListener("mouseup", drop, false);
    //alert("DEBUG_DROP");
}

function makeBoundlessObj(e) {
    obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    return obj;
}

function makeObj(e) {
    obj = new Object();
    obj.element = e;

    obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
    obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

    obj.posX = event.clientX - e.offsetLeft;
    obj.posY = event.clientY - e.offsetTop;

    var curleft = curtop = 0;
    if (e.offsetParent) {
        do {
            curleft += e.offsetLeft;
            curtop += e.offsetTop;
            //alert(e.id + ":" + e.innerHTML);
            if(~e.className.search(/bound/)) {
                obj.boundX = curleft - obj.element.offsetLeft;
                obj.boundY = curtop - obj.element.offsetTop;
                return obj;
            }

        } while (e = e.offsetParent);
    }

    return obj;
}

function findPos(obj) { // Donated by `lwburk` on StackOverflow
    var curleft = curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
}

В случае, если проблема не была ясна: моя функция JavaScript makeObj()неправильно установлены boundX и boundY, потому что элементы с классом .bound влияют на функцию, когда их не должно быть.

Спасибо всем за чтение и помощь!

1 Ответ

2 голосов
/ 27 февраля 2011

Насколько я могу судить, цикл работает так, как вы хотите.Это - это поиск первого элемента, помеченного классом bound.Проблема, с которой вы сталкиваетесь, связана с position:relative, который поставляется вместе с классом bound.

Рассмотрим следующий HTML-код:

<div id="center" style="position:relative">
    <h1>Hello World! <hr /></h1>
    <div id="box" class="bound" >
        <p class="drag square" id="one"> One </p>
        <p class="drag square" id="two"> Two </p>
    </div>
</div>

Он функционирует идентично вашему первомуMsgstr "HTML (тот, где центр помечен классом bound).

Здесь важно отметить, что пометка элемента с помощью position:relative или position:absolute заставляет дочерние элементы видеть его верхний левый угол как (0,0).В CSS дочерние элементы обращаются к своему первому предку, который отмечен относительной или абсолютной позицией.Элементы, которые не помечены как таковые, не рассматриваются ребенком как имеющие верхний левый угол в (0,0).

. Проблема в том, что вы используете offsetLeft и offsetTop требуемогопредел (ближайший предок с классом bound; в данном случае box), который изменяется, когда ближайший предок этого элемента помечен относительными / абсолютными изменениями.В первом случае ближайший предок center ... во втором случае это документ.В первом случае makeObj возвращает (0, 22).Во втором возвращается (108,82).

Если вы не делаете это как академическое упражнение или увлекательный проект, подумайте об использовании существующей библиотеки DnD, такой как поставляемая с Dojo: http://docs.dojocampus.org/dojo/dnd

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...