In the following example, drag the puzzle pieces from the left into the boxed area in the center of the page to produce the picture shown at the right.
When the user attemps to move elements on a page to exact positions, it is often helpful to "snap" the element to the exact position when it is close to where it belongs. In the above example, dragging a puzzle piece close to its correct position and releasing the mouse button causes the piece to snap to its exact position.
Click the "View Targets" button above to reveal the layout of the target area into which the puzzle pieces are moved. The dotted boxes in the target area are small divisions representing the areas where the pieces fit. As long as a piece is dragged into the boundaries of one of these areas, it is deemed "close enough", and the piece is snapped to the top-left corner of the area.
Coding for these puzzle pieces and target areas is shown below:
<div id="DIV" style="position:relative; width:572; height:217; border:dashed 0"> PICTURE PIECES ARE DEFINED HERE <!-- ROW 1 --> <img id="PUZ10" src="Images/10.jpg" style="position:absolute; top:0; left:0; width:50; height:50"/> <img id="PUZ03" src="Images/03.jpg" style="position:absolute; top:0; left:55; width:50; height:50"/> <img id="PUZ01" src="Images/01.jpg" style="position:absolute; top:0; left:110; width:50; height:50"/> <!-- ROW 2 --> <img id="PUZ11" src="Images/11.jpg" style="position:absolute; top:55; left:0; width:50; height:50"/> <img id="PUZ05" src="Images/05.jpg" style="position:absolute; top:55; left:55; width:50; height:50"/> <img id="PUZ08" src="Images/08.jpg" style="position:absolute; top:55; left:110; width:50; height:50"/> <!-- ROW 3 --> <img id="PUZ12" src="Images/12.jpg" style="position:absolute; top:110; left:0; width:50; height:50"/> <img id="PUZ04" src="Images/04.jpg" style="position:absolute; top:110; left:55; width:50; height:50"/> <img id="PUZ09" src="Images/09.jpg" style="position:absolute; top:110; left:110; width:50; height:50"/> <!-- ROW 4 --> <img id="PUZ02" src="Images/02.jpg" style="position:absolute; top:165; left:0; width:50; height:50"/> <img id="PUZ06" src="Images/06.jpg" style="position:absolute; top:165; left:55; width:50; height:50"/> <img id="PUZ07" src="Images/07.jpg" style="position:absolute; top:165; left:110; width:50; height:50"/> TARGET DIVISIONS ARE DEFINED HERE <div style="position:absolute; top:0; left:165; width:200px; height:150px; background-color:#FFCC99></div> <!-- ROW 1 --> <div id="POS01" style="position:absolute; top:0; left:165; width:40; height:40; border:dashed 0"></div> <div id="POS02" style="position:absolute; top:0; left:215; width:40; height:40; border:dashed 0"></div> <div id="POS03" style="position:absolute; top:0; left:265; width:40; height:40; border:dashed 0"></div> <div id="POS04" style="position:absolute; top:0; left:315; width:40; height:40; border:dashed 0"></div> <!-- ROW 2 --> <div id="POS05" style="position:absolute; top:50; left:165; width:40; height:40; border:dashed 0"></div> <div id="POS06" style="position:absolute; top:50; left:215; width:40; height:40; border:dashed 0"></div> <div id="POS07" style="position:absolute; top:50; left:265; width:40; height:40; border:dashed 0"></div> <div id="POS08" style="position:absolute; top:50; left:315; width:40; height:40; border:dashed 0"></div> <!-- ROW 3 --> <div id="POS09" style="position:absolute; top:100; left:165; width:40; height:40; border:dashed 0"></div> <div id="POS10" style="position:absolute; top:100; left:215; width:40; height:40; border:dashed 0"></div> <div id="POS11" style="position:absolute; top:100; left:265; width:40; height:40; border:dashed 0"></div> <div id="POS12" style="position:absolute; top:100; left:315; width:40; height:40; border:dashed 0"></div> </div>
All puzzle elements are contained inside a single encompassing division (DIV) that is positioned relative within the flow of page elements. Placement of puzzle elements is relative to this division.
The small target positions are named "POS01" through "POS12" to correspond with the puzzle pieces which are named "PUZ01" through "PUZ12". When, for example, piece "PUZ01" is within the boundaries of position "POS01", then the piece is snapped into place. More correctly, when the center of piece "PUZ01" is within the boundaries of position "POS01" the piece is snapped. The divisions are given borders styles of dashed 0. Borders are not necessary, but when given a visible width they help in positioning the divisions during page setup.
Scripting for this application is similar to previous scripts involving restricted dragging of elements inside the boundaries of a division. Differences are in the Drop() function, called on a mouseup event to position the puzzle piece when it is dropped.
function Drop()
{
var i = SelectedItem.id.substr(3,2);
var TopLimit = document.getElementById("POS" + i).style.pixelTop;
var BottomLimit = document.getElementById("POS" + i).style.pixelTop +
document.getElementById("POS" + i).style.pixelHeight;
var LeftLimit = document.getElementById("POS" + i).style.pixelLeft;
var RightLimit = document.getElementById("POS" + i).style.pixelLeft +
document.getElementById("POS" + i).style.pixelWidth;
var CenterY = document.getElementById("PUZ" + i).style.pixelTop +
(document.getElementById("PUZ" + i).style.pixelHeight / 2);
var CenterX = document.getElementById("PUZ" + i).style.pixelLeft +
(document.getElementById("PUZ" + i).style.pixelWidth / 2);
if (CenterY >= TopLimit &&
CenterY <= BottomLimit &&
CenterX >= LeftLimit &&
CenterX <= RightLimit ) {
SelectedItem.style.pixelTop =
document.getElementById("POS" + i).style.pixelTop;
SelectedItem.style.pixelLeft =
document.getElementById("POS" + i).style.pixelLeft;
}
document.onmousemove = null;
document.onmouseup = null;
}
First, the boundaries of the target area are determined. The script checks to see which piece is being dropped by getting the last two characters of the id property of the dragged element and storing it in variable i:
i = SelectedItem.id.substr(3,2)The value of i, then, is used to determine the corresponding target area. If, for example, the piece being dropped is "PUZ01", then i is set to value 01. The corresponding position for this piece is ("POS" + i), or "POS01". The TopLimit, BottomLimit, LeftLimit, and RightLimit boundaries of this target division are determined.
If the center of the dropped piece is within this target division, then the piece is snapped to the top and left boundaries of that division. The vertical coordinate of the center point is calculated as the pixelTop position of the piece plus half its pixelHeight; the horizontal coordinate is its pixelLeft position plus half its pixelWidth:
var CenterY = document.getElementById("PUZ" + i).style.pixelTop +
(document.getElementById("PUZ" + i).style.pixelHeight / 2);
var CenterX = document.getElementById("PUZ" + i).style.pixelLeft +
(document.getElementById("PUZ" + i).style.pixelWidth / 2);
If the center of the puzzle piece is positioned within the target division, then it is snapped to the target division's top and left boundaries:
if (CenterY >= TopLimit &&
CenterY <= BottomLimit &&
CenterX >= LeftLimit &&
CenterX <= RightLimit ) {
SelectedItem.style.pixelTop =
document.getElementById("POS" + i).style.pixelTop;
SelectedItem.style.pixelLeft =
document.getElementById("POS" + i).style.pixelLeft;
}
This is a simple matter of setting the pixelTop and pixelLeft properties of the dropped puzzle piece to the corresponding property values of the target division.
The puzzle is set back to its original layout by clicking the "Reset Puzzle" button. To restore the original layout, the XHTML code of the encompassing division "DIV" is saved in global variable DIVSave when the page first loads by saving the division's innerHTML property.
var DIVSave; function SaveDIV() { DIVSave = document.getElementById("DIV").innerHTML; } <body onload="SaveDIV()">
When the divison is reset by clicking the "Reset Puzzle" button, function Reset() is called to replace the current layout of division "DIV" with its original code saved in variable DIVSave.
document.all.DIV.innerHTML = DIVSave
function Reset()
{
document.getElementById("DIV").innerHTML = DIVSave;
}