TODO: How to make a drag and drop object Draggable items must be positioned items. As in the case for all positioned items, they are positioned absolute inside a container that is positioned relative to maintain the items within the flow of page elements. Coding for the above objects is shown below.

<div style="position:relative; width:550px; height:125px; cursor:hand">

<img src="jsdhtml.gif" style="position:absolute; left:15px; top:10px"

  onmousedown="Move(this)"/>

<span style="position:absolute; left:15px; top:80px; width:150; height:20; padding:3; background-color:red; color:white; font-weight:bold" onmousedown="Move(this)">

  This is a Text String

</span>

<div style="position:absolute; left:190px; top:10px; width:170px; border-style:solid 1; padding:5; text-align:left; background-color:white" onmousedown="Move(this)">

  This division is positioned absolutely on the page so it can be dragged
  by the user to other positions.

</div>

<div style="position:absolute; left:380px; top:10px" onmousedown="Move(this)">

  This division does not have a fixed width or height. When dragged to the
  left or right, the division adjusts its size to fit within the available
  space on the page.

</div>

</div>

Listing 15-1. Code to position draggable page elements.

All items are give left and top property settings to position them within the containing division. An item is designated for dragging by coding an onmousedown="Move(this)" event handler that calls the Move() function, passing its self reference to the function.

The script contains several variable that are defined globally for reference from two different functions. Variable SelectedItem stores the object reference for the item being dragged; SelectedX and SelectedY store the initial page coordinates of the item being dragged; MouseX and MouseY store the initial coordinates of the mouse cursor when the item is clicked.

<script type="text/javascript"> var SelectedItem; var SelectedX, SelectedY; var MouseX, MouseY;

function Move(ClickedItem) {

  SelectedItem = ClickedItem;
  SelectedX = SelectedItem.style.pixelLeft;
  SelectedY = SelectedItem.style.pixelTop;
  MouseX = event.clientX;
  MouseY = event.clientY;
  document.onmousemove = Drag;
  document.onmouseup = Drop;

} ... </script>

Listing 15-2. Code to control dragging and dropping of page elements.

Movement of the item around the page is based on changing positions of the mouse cursor as it is moved. In order to move an item, the initial position of the cursor needs to be known as well as the initial position of the item being moved. The item's pixelLeft and pixelTop positions are assigned to variables SelectedX and SelectedY to store the current item position. The cursor's current position within the window is given by event properties event.clientX and event.clientY which are stored in variables MouseX and MouseY. Cursor Property Description event.clientX event.clientY

	Coordinates of mouse pointer within the window or frame.

Figure 15-2. Mouse position properties.

Once these initial settings are captured, dragging of the item is put under control of the Drag() function. This function needs to be called repeatedly, whenever the mouse is moved. The mousemove event, therefore, is put under purview of the Web document itself so that any mouse movement across the document is captured. This assignment takes place with the statement,

document.onmousemove = Drag;

appearing at the close of the Move() function. At this point, the document's onmousemove event handler becomes sensitive to mouse movements, calling the Drag() function each time they occur. At the same time, the document is made sensitive to mouseup events with the statement,

document.onmouseup = Drop;

calling the Drop() function to cease moving an item when the mouse button is released.

Note the different syntax used when initiating an event handler within a script. These event handlers must be coded without parentheses (Drag, Drop).

A selected item is dragged by the Drag() function whose coding is shown below.

function Drag() {

  SelectedItem.style.left = SelectedX + (event.clientX - MouseX);
  SelectedItem.style.top = SelectedY + (event.clientY - MouseY);
  return false;

}

Listing 15-3. Script to drag a page element.

As mentioned, the direction and amount by which the selected item is moved is given by the direction and amount by which the cursor is moved. The difference between the new position of the cursor and its original position when the item was clicked is given by the formulas: (event.clientX - MouseX) and (event.clientY - MouseY). The horizontal mouse distance is then added to the previous horizontal position of the item; the vertical mouse distance is added to the previous vertical position of the item. On screen, the item tracks the position of the cursor. The return false statement is needed to suppress any other associated effects of dragging such as highlighting text on the page.

When the mouse button is released, the document's onmousemove and onmouseup event handlers are released by the Drop() function. Now, mouse movement isn't tracked until another object is selected for dragging.

function Drop() {

  document.onmousemove = null;
  document.onmouseup = null;

}

Listing 15-4. Script to drop a page element.

The above scripts can be coded on any page to permit dragging of any object on that page. All that is required to activate dragging is, first, to position an item on the page. Position it absolute inside a container that is positioned relative in order to establish the item's initial location on the page. Then assign the event handler onmousedown=Move(this) to the item.

1.  Using the JavaScript event

If you have a function, you can add the following to the top, to capture the element that caused it to fire.

if (navigator.appName == "Microsoft Internet Explorer"){
    ev = window.event.srcElement;
}
else{
    ev = this;
}

You can then refer to it else where, like getting the elements ID.

element_id = document.getElementById(ev.id);

2.  Add a method to an array object (Extending an object)

Array.prototype.in_array = function(p_val) {
       for(var i = 0, l = this.length; i < l; i++) {
               if(this[i] == p_val) {
                       return true;
               }
       }
       return false;
}

3.  Very basic JavaScript drag and drop example

This example lets you drag one of the files into the directory and then removes that file from the screen. The idea is that some Ajax will take the source and destination locations in the get file function and process some stuff on the server. Maybe for a file manager application ... etc. It's very primitive, but it works.

<html>
<head>
<title>Mouse</title>
<style type="text/css">
body {
        font-family:sans-serif;
        }
div.block1 {
        margin:8px;
        padding:8px;
        border:1px solid black;
        }
div.block2 {
        margin:8px;
        padding:8px;
        border:1px solid black;
        }
div.block1, div.block2 {
        width:200px;
        height:25px;
        }
div#output {
        margin:8px;
        padding:8px;
        border:1px solid black;
        width:500px;
        height:25px;
        }
</style>
<script type="text/javascript">
function set_file(source,id)
{
        drag_source = source;
        parent_id = id;

        return 1;
}

function get_file(destination)
{
        drag_destination = destination;
        if(drag_source && parent_id && drag_source != drag_destination)
        {
                document.getElementById('output').innerHTML = "mv " + drag_source + " " + drag_destination + " " + parent_id;
                document.getElementById('container').removeChild(document.getElementById(parent_id));
                parent_id = null;
                drag_source = null;
        }

        return 1;
}
</script>
<body>
<div id="container">
<!-- note, for directories, you put onmousedown and onmouseup
       also, i link this to some php code where it checks to see if the
       destination directory is in fact a directory and that the file being
       moved there doesn't already exist.
-->
<div id="dir1" onmousedown="set_file('/var/destination/www',this.parentNode.id)" onmouseup="get_file('/var/destination/www')" class="block1">
<a href="#">block1 dir</a>
</div>
<div id="file1" class="block2 dragfile">
<a onmousedown="set_file('/var/source1/www',this.parentNode.id)" href="#">block2 file 1</a>
</div>
<div id="file2" class="block2 dragfile">
<a onmousedown="set_file('/var/source2/www',this.parentNode.id)" href="#">block2 file 2</a>
</div>
<div id="output"></div>
</div>
</body>
</html>

4.  Accessing events without using event attributes on html elements

Say you have a <select> and you want something to happen when it changes. Normally you would use the onChange event like,

<select id="myselect" name="myselect" onChange="myfunc()">
<option>opt1</option><option>opt2</option>
</select>

So when someone changes the select value, the myfunc() function will be fired.

You can also do this another way without tying an even to it directly. Here's how.

<select id="myselect" name="myselect" onChange="myfunc()">
<option>opt1</option><option>opt2</option>
</select>
<script type="text/javascript">
var sel = document.getElementById('myselect');
sel.onchange = function()
{
     myfunc();
}
</script>

GOTCHAS

  • Make sure your javascript is inserted below the field you are acting on, or that it's in the onLoad event, otherwise your actions might not happen because the page hasn't loaded yet.
  • Another VERY important thing to look at is the capitalization or lack there of on that part that looks like sel.onchange. Notice the previous example use onChange. The lowercase version on sel.onchange must be that way. It must be lowercase ONLY!!!. When tying to html elements, there are not capitalization requirements. You could use onChange, OnChange, onCHANGE or anything else.

5.  Using array values as arrays themselves

5.1  The Problem

I have an issue where I need to get a value out of an array, and then use that value as an array itself to retrieve another value. Here's a little example.

Basically, I have an array of the form,

var animals = new Array("cats","dogs");

I have a form that has radio options, and let's pretend that one radio name is cats, as in

<input type="radio" name="cats" value="siamese" />
<input type="radio" name="cats" value="tiger" />

In my application, I only have two values for each radio name, so I reference them with,

document.getElementById('form').cats[0].value

and

document.getElementById('form').cats[1].value

or

document.getElementById('form').dogs[0].value

and

document.getElementById('form').dogs[1].value

What I'm wanting to do is use the animals array above to get the value, as in

document.getElementById('form').animals[0][0].value

which is wrong.

This previous line should really be document.getElementById('form').cats[0].value where animals[0] was replaced by cats.

That above should equal siamese, and document.getElementById('form').animals[0][1].value should equal tiger.

5.2  The Solution

Instead of using the dot notation, try the array index notation instead. So instead of element.name you will be using element[name].

document.getElementById('form')[animals[0]][0].value

So, document.getElementById('form')[animals[0]][0].value equals siamese.

Thanks pmw57 » for the help.

6.  How to use getElementById the way prototype does

Just add the following function to your JavaScript code.

function $(id)
{
     return document.getElementById(id);
}

7.  Order of actions

Sometimes, I've found it's necessary to perform certain actions in a particular order, even if it doesn't make sense. Here's one case.

document.getElementById('modify_group_user_button').removeAttribute('disabled');
document.getElementById('modify_group_user_button').removeAttribute('onClick');
document.getElementById('modify_group_user_button').setAttribute('type','submit');

I had these three lines in a different order, and IE7 was throwing an error. Firefox on the other had played nice and behaved as expected.

I'm not sure what was going on, but this is more or less a reminder that if you get strange errors, think about the order of actions you are performing.

8.  ID's and Functions having the same name causes an error

If you ever run into this error,

Error: Object doesn't support this property or method

You may have a tag ID that's the same as the function name. I'm not sure what the case is that causes the error, but I had a function name, say update_me() and an input button that I was trying to modify that had the same ID name as the function.

function update_me()
{
     document.getElementById('update_me')
}

The button looked partially like <input id="update_me" />.

I've left out the details, but the moral of the story is don't name any function the same as any ID attribute.

9.  Integrating PHP into JavaScript

Here's a little example that can throw you off for a while.

I have some JavaScript that upon clicking a button, the onClick fills a division using innerHTML. Let me just show you a bit.

<?php
$options = <<<eof
<option value="1">op 1</option>
<option value="2">op 2</option>
eof;

$javascript = <<<eof
<script type="text/javascript">
function on_click()
{
     document.getElementById('some_id').innerHTML = "<select name=\"somename\">{$options}</select>";
}
</script>
eof;
?>
<html><head><title>test</title>
{$javascript}
</head><body>
<input type="button" onClick="on_click()" value="click me" />
<div id="some_id"></div>
</body></html>

Basically, when you click that button, the division would be filled with an html <select> drop down box.

The code will not work.

Basically, in the $options variable, you must escape any quotations (") because, unlike php, the javascript doesn't auto escape them when putting a variable inside of another variable that contains quotes.

The 1st fix that needs to be done is,

$options = <<<eof
<option value=\"1\">op 1</option>
<option value=\"2\">op 2</option>
eof;

The second fix is that, even inside a heredoc, the javascript code must be in one line, so the final fix is.

$options = <<<eof
<option value=\"1\">op 1</option><option value=\"2\">op 2</option>
eof;

10.  Javascript Error: Not Implemented fix.

This error, "Not Implemented", can be caused when running JavaScript in IE. Tested in IE7 so far. The javascript may look as follows.

window.onload = foobar();

This will function properly, but IE7 and maybe before or after will trigger a strange error. To get rid of this error, simply remove the () from foobar(). It should look like,

window.onload = foobar;

If you need to run more than one function than just foobar() on load, do the following.

window.onload = foobar(){
     foobar1();
     foobar2();
     foobar3();
}

11.  Doing <body onLoad=""> onLoad outside of the <body> tag.

Right before </body> add

<script type="text/javascript">
function some_to_do_onload(){
     // do something
}

some_to_do_onload();
</script>

That's it. All you have to do is add the open and closing <script> tags and add the function you want inside there. Activate the function by simply calling it inside the <script> tags. There's no need for the onLoad event.

The reason for adding the script just before the </body> tag is that say you want to make the cursor focus in a text input box. Well, if the Javascript was in the <head>, it may try to put the cursor in the text box before the form is even loaded. By putting it at the end of your file, the form loads and then the action is taken.

11.1  Clear text box

onBlur="if(this.value=='') this.value='search...';" onFocus="if(this.value=='search...') this.value='';"

11.2  Popup window for picture

<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
function Start(page) {
OpenWin = this.open(page, "CtrlWindow",
"toolbar=no,menubar=no,location=no,scrollbars=no,resizable=no,width=234,height=254");
}
// End -->
</SCRIPT>
<A href="javascript:Start('http://domain/picture.jpg')";>text</A>

11.3  Form Validation

<html>
<head><title>test</title></head>
<script type="text/javascript">
function checkForm(form) {
  if(form.blah2.value == "") {
    alert("Error: error message");
    form.blah2.focus();
    return false;
  }
}
</script>
<body>
<form action="http://www.mydomain.com/someplace.html" method="post" onSubmit="return checkForm(this);">
<input type="text" name="blah1" size="30" /><br />
<input type="text" name="blah2" size="30" /><br />
<input type="text" name="blah3" size="30" /><br />
<input type="text" name="blah4" size="30" /><br />
<input type="submit" value="submit" />
</form>
</body>
</html>

11.4  Form Validation

<script type="text/javascript">
function clear_radio_buttons() {
  for(var i=0;i<document.decision.decision.length;i++){
    document.decision.decision[i].checked = false;
  }
}
function set_house_ref() {
  document.decision.decision[1].checked = true;
}

function remove_annotations() {
  document.decision.annotations.value = "";
}
</script>
<form name="decision" action="{$_SERVER['PHP_SELF']}?action=decision&amp;artid=$artid" method="post">
<div class="option1">
<strong>Return to author:</strong> <input type="radio" name="decision" value="return" onClick="remove_annotations()" />
</div>
<div class="option2">
<strong>Show to in-house referee:</strong> <input type="radio" name="decision" value="inhouse" onClick="remove_annotations()" />
<select name="house_ref" onClick="clear_radio_buttons(); set_house_ref(); remove_annotations()">
.
.
.

12.  Page Comments (Click to edit)

Design by N.Design Studio, adapted by solidGone.org (version 1.0.0)
Powered by pmwiki-2.2.0-beta65