Avatar billede kjeldsted Novice
07. januar 2013 - 00:05 Der er 6 kommentarer og
1 løsning

Flyt objekter

Hej.

Jeg ville lige høre engang om hvordan følgende vil kunne løses på en optimal og holdbar måde, uden at jeg ender med at overbelaste hukommelsen og hvad der nu ellers skal tages hensyn til.

Jeg har en HTML opbygning der fx. kunne være som følger (fra et test dokument jeg har liggende)

    <div id="overallContainer">
        <div class="spaces" id="space1">
            <div class="bokse" id="boks1"> 1</div>
        </div>
        <div class="spaces" id="space2">
            <div class="bokse" id="boks2"> 2</div>
        </div>
        <div class="spaces" id="space3">
            <div class="bokse" id="boks3"> 3</div>
        </div>
    </div>


Det skal da lige tilføjes at listen sagtens kan indeholde 50 elementer, så de tre er blot fordi 50 ville fylde lidt meget i et spm her på siden.

Det jeg ønsker nu er at kunne flytte rundt på dem. Dynamisk, via JS. Altså så jeg fx. flytter boks 3 op på boks 1's plads, hvorved resten af rækken skubbes med. Altså så vi ender med:


    <div id="overallContainer">
        <div class="spaces" id="space1">
            <div class="bokse" id="boks3"> 1</div>
        </div>
        <div class="spaces" id="space2">
            <div class="bokse" id="boks1"> 2</div>
        </div>
        <div class="spaces" id="space3">
            <div class="bokse" id="boks2"> 3</div>
        </div>
    </div>


Space DIV'et vil altid indeholde ét DIV med en boks. Boks DIV'et vil være varierende i indhold.

Men nogle forslag til hvordan jeg skal tænke det. Og altså ikke blot så det sådan nogenlunde virker, men så at det virker optimalt.

Ps. Hvis det er idiotisk med opbygningen af HTML'en så bare sig til. Den kan sagtens ændres hvis det ville lette og optimere arbejdet med JS.
Avatar billede olebole Juniormester
07. januar 2013 - 02:51 #1
<ole>

Hvis du kan ændre strukturen, så du udelader dine 'placeholders', bliver løsningen en del enklere. I så fald er her et hurtigt skud fra hoften, du kan bruge til inspiration:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
body {
    margin: 0;
    padding: 0;
    font: 12px verdana, arial, sans-serif;
}
.overallContainer {
    position: relative;
    width: 140px;
    padding: 0 2px;
    border: 2px solid #666;
    list-style: none;
}
.overallContainer * {
    cursor: move;
}
.overallContainer .bokse {
    padding: 4px 15px;
    margin: 1px 0;
    border: 1px solid #ccc;
}
.wide {
    width: 200px;
}
.wide .bokse {
    padding: 2px 25px;
    margin: 2px 0;
    border: 1px solid #ccc;
}
</style>
<script type="text/javascript">
// Hide form global scope
(function(W) { // W refers to the window object
    var dragEnabled = false,
    elmDrag = null,
    elmClone = null,
    elmParent = null,
    pos = 0,
    maxTopPos = 0;
   
    // Helper to find a parent element with a specific className
    function findParent(elm, className, elmBoundary) {
        while (elm!==elmBoundary) {
            if (elm.className===className) return elm;
            elm = elm.parentNode;
        }
        return null;
    }
    // Create a semi transparent box to drag. Called on mousedown.
    function createClone() {
        elmClone = document.createElement("div");
        elmClone.style.cssText = "position:absolute;left:2px;right:2px;background:#09f;opacity:0.3";
    }
   
    // Event handlers
    function dragMove(e) {
        if (!dragEnabled) return;
        var newTop = e.clientY-pos;
        elmClone.style.top = (newTop<0 ? 0 : (newTop>maxTopPos ? maxTopPos : newTop)) + "px";
    }
    function dragUp() {
        if (!dragEnabled) return;
        elmDrag.style.opacity = 1;
        var cloneTop = elmClone.offsetTop;
        elmParent.removeChild(elmClone);
        if (cloneTop<1) { // First
            elmParent.insertBefore(elmDrag, elmParent.firstChild);
        } else {
            var a = elmParent.childNodes;
            for (var i=a.length-1; i>=0; i--) {
                if (a[i].nodeName.toLowerCase()!=="div") continue;
                if (a[i].offsetTop<cloneTop) {
                    if (a[i].offsetTop+a[i].offsetHeight<cloneTop) { // Last
                        elmParent.appendChild(elmDrag);
                    } else {
                        elmParent.insertBefore(elmDrag, a[i].nextSibling);
                    }
                    break;
                }
            }
        }
        dragEnabled = false;
    }
   
    // Set event handlers on document object
    if (document.addEventListener) {
        document.addEventListener("mousemove", dragMove, false);
        document.addEventListener("mouseup", dragUp, false);
    } else {
        document.attachEvent("onmousemove", dragMove);
        document.attachEvent("onmouseup", dragUp);
    }
   
    // Make the setDrag function available from the global scope
    W.setDrag = function(elmCont, e) {
        elmDrag = findParent(e.target||e.srcElement, "bokse", elmCont);
        if (!elmDrag) return;
        if (!elmClone) createClone();
        pos = e.clientY-elmDrag.offsetTop;
       
        elmParent = elmCont;
        elmDrag.style.opacity = 0.3;
        elmClone.style.height = elmDrag.offsetHeight+"px";
        elmClone.style.top = elmDrag.offsetTop+"px";
        elmParent.appendChild(elmClone);
       
        maxTopPos = elmParent.clientHeight - elmClone.offsetHeight;
       
        dragEnabled = true;
       
        e.cancelBubble = true;
        e.returnValue = false;
        if (e.stopPropagation) e.stopPropagation();
        if (e.preventDefault) e.preventDefault();
    };
})(window);
</script>
</head>
<body>

<div style="padding:100px">

    <div class="overallContainer" onmousedown="setDrag(this, event)">
        <div class="bokse" id="boks1">Boks nummer 1</div>
        <div class="bokse" id="boks2">Boks nummer 2</div>
        <div class="bokse" id="boks3">Boks nummer 3</div>
        <div class="bokse" id="boks4">Boks nummer 4</div>
        <div class="bokse" id="boks5">Boks nummer 5</div>
        <div class="bokse" id="boks6">Boks nummer 6</div>
    </div>
   
    <hr>
   
    <div class="overallContainer wide" onmousedown="setDrag(this, event)">
        <div class="bokse" id="boks7">Boks nummer 7</div>
        <div class="bokse" id="boks8">Boks nummer 8</div>
        <div class="bokse" id="boks9">Boks nummer 9</div>
        <div class="bokse" id="boks10">Boks nummer 10</div>
        <div class="bokse" id="boks11">Boks nummer 11</div>
        <div class="bokse" id="boks12">Boks nummer 12</div>
    </div>


</div>

</body>
</html>

Det kan gøres med væsentligt mindre kode med jQuery, men det lærer du ikke så meget JavaScript af  =)

/mvh
</bole>
Avatar billede kjeldsted Novice
07. januar 2013 - 10:41 #2
Lækker lille kode, helt sikkert nok til den manglende inspiration. Og placeholderne ryger ud med det samme kan jeg se. Jeg ved faktisk ikke rigtig hvorfor de havnede dér, men jeg havde vel en idé med det sidste år da jeg skrev html'en til denne test side.

Og. Ja, du har helt ret. Det kan gøres nemmere med jQuery. Men hvis jeg var sat i verden for at gøre ting så simpelt som absolut muligt var jeg nok aldrig gået i gang med at kode hjemmesider ;)
Dels vil jeg jo gerne lærer noget mere om scripting, dels vil jeg gerne have et overblik over hvad der egentlig sker på siden med de forskellige JS funktioner og så vil jeg også helst gerne være fri for at være bundet op på en jQuery server.

Men der er da vist lige nogle ting herfra jeg hellere lige må have læst op på. Jeg synes godt nok at JS har vist sig at være noget af en stor mundfuld. Men jeg må jo bare læse videre på det. Og endnu engang mange tak. Hvis jeg kender dig ret er du uinteresseret i disse points, så dem kommer jeg vel ikke af med ;)
Avatar billede olebole Juniormester
07. januar 2013 - 13:19 #3
Du er velkommen til at spørge yderligere, hvis der er noget, du er i tvivl om. Og du har helt ret, jeg samler ikke point, men tak for tilbudet  =)

PS: Scriptet kan nok 'sexes' en hel del op. Det er blot til inspiration, og klokken var mange  *o)
Avatar billede kjeldsted Novice
07. januar 2013 - 14:12 #4
Jeg takker mange gange Ole.

Og jeg vil også "kun" bruge det til inspiration. Det der med bare at copy-paste en kode råt ind er ikke lige min stil :) Så det er en kæmpe hjælp. Men skal da vist have fat i 'The Rihno' og have læst op på afsnittet omkring insertBefore.
Avatar billede olebole Juniormester
07. januar 2013 - 14:24 #5
Første argument i insertBefore er det element, der skal indsættes. Andet argument er det element foran hvilket, det nye element skal indsættes.

Eksisterer elementet i andet argument ikke, skal det nye element appendes (tilføjes til sidst)
Avatar billede olebole Juniormester
07. januar 2013 - 14:26 #6
Der burde nok have stået:

"Eksisterer elementet i andet argument ikke, bliver det nye element appended (tilføjet til sidst)".

Det er ikke noget, du skal tænke på. Det sker helt automatisk  =)
Avatar billede olebole Juniormester
07. januar 2013 - 14:30 #7
PS: Vil du flytte et element, er det ikke nødvendigt først at fjerne det (med removeChild).

Hvis du indsætter et eksisterende element et andet sted, vil det automatisk blive fjernet fra dets nuværende plads - og blive indsat på den nye plads  =)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester