Add Ids and onClicks and Grab and Drop to Divs
There are three scripts that relate to the issue of grab-and-drop or drag-and-drop scripts: Grab and Drop, Not Drag and Drop, Add Ids and onClicks to Divs, and Add Ids and onClicks and Grab and Drop to Divs. Below is the script for Add Ids and onClicks and Grab and Drop to Divs. The point of finding all the divs on the page and putting in ids and onclick events, is that now the divs become accessible for such scripts as grab and drop and drag and drop scripts. I.e., they can be moved, if you have a script that can do it. And we do. As a matter of fact, our Add Ids and onClicks and Grab and Drop to Divs script below has the grab and drop built right in.
JavaScript Charts, Graphs, Graphics, Circles, Ellipses, Arcs, Lines, and Polygons
Grab and Drop, Not Drag and Drop
Add Ids and onClicks to Divs
Add Ids and onClicks and Grab and Drop to Divs
Make Anti-alias (Almost) Lines
Make Anti-alias (Almost) Lines Using Bresenham's Line Algorithm
Good JavaScript Circle Algorithm
Good JavaScript Ellipse Algorithm
Good JavaScript Arc Algorithm
Make JavaScript Irregular Polygon
JavaScript Area of Irregular Polygon Algorithm
Make Line Chart from User-Inputted Data
Make Line Chart from CSV Data
Make Line Chart from MySQL Table Data
Make Bar Chart from User-Inputted Data
Make Bar Chart from CSV Data
Make Bar Chart from MySQL Table Data
Make Pie Chart from User-Inputted Data
Make Pie Chart from CSV Data
Make Pie Chart from MySQL Table Data
The script uses JavaScript to Add Ids and onClicks and Grab and Drop to Divs. The Add Ids and onClicks to Divs script does the same, but displays alerts proving that the onClicks not only work right in the main three browsers (2013 versions of IE8, Firefox, and Chrome), they can furnish ids or other info to the user. The script below, Add Ids and onClicks and Grab and Drop to Divs, is a cross-browser script that not only changes all divs on a page by adding onClick events and ids (which gets them ready to be moveable), but also lets the user grab and move any and all divs as desired.
The Grab and Drop, Not Drag and Drop script gives you a grab and drop script that you can use in your scripts. It creates divs on the fly with onClicks and ids already installed, then lets you move them around. (If you used the script in your programs, you'd replace all the divs our script creates with your own divs, and then add appropriate onClick events and ids to your divs.) The div creation method employs the innerHTML property. We created the divs to test with and see if you like grab and drop rather than drag and drop. The script is cross-browser and quite short and simple. But, in truth, you'd be better off using our Add Ids and onClicks and Grab and Drop to Divs script, below, in your pages that have divs needing moving. It doesn't only contain the grab and drop script, it also transforms all divs on any page into moveable ones first, so they're all set for the script's grab and drop.
You may be asking yourself why we made any of these scripts. Here are three applications that make extensive use of our grab and drop code: Make Pie Chart from User-Inputted Data and Make Pie Chart from CSV Data and Make Pie Chart from MySQL Table Data. It turns out that even though it isn't that hard to make a pie chart, labelling it is anything but straightforward. There are so many factors: how many labels (which corresponds with how many elements are being charted), how many words per label, how large the font is, what position around the circle each label is, and what to do when labels try to overlap. There is a reason that the chart aspect of applications like Excel give users drag and drop capabilities when it comes to labels—especially pie chart labels. A human eyeballing a chart and adjusting label placements is simply more effective than any algorithm. So algorithms take their best shot at labelling effectively, and then humans take over for the final adjustments. Whether drag and drop or grab and drop, a grab and drop script like the one on Grab and Drop, Not Drag and Drop is essential for some types of apps, and the three pie chart script tutorials mentioned above let you experience why. True, we did not handle accessibility as nicely as ppk did with ppk at quirksmode.org, whose code works but it is quite long. We desired short and sweet. But click move click like our grab and drop script offers is much easier to do than click drag click, and easier on the hands.
Having established the worth of a grab and drop script, let us check out what the script on this page and the Add Ids and onClicks to Divs script have in common. Add Ids and onClicks to Divs, has the sole purpose of proving that our script succeeds at the following tasks:
- Looping through all divs on a page, some of which may have ids or events already, and adding ids and onClicks to each one. Except existing ids are left alone.
- Both the ids and onClicks are unique—no div gets the same id or onClick. The onclicks events themselves are identical, but the parameter stuck in the onclick handler function is unique for each div. Obviously, we want to stick the divs' ids into the functions registered as the handlers of the click events of HTML elements so, for example, onclick="check('a90003')" is stuck in the div whose id is 'a90003'.
- We've now made the divs accessible for such scripts as grab and drop and drag and drop scripts. I.e., they can be moved, if you have a script that can do it. We do.
- We prove the divs are now accessible (even if they had no events or ids to start with) by clicking on them and getting style or id attributes for the clicked div.
- Make sure if a div already has an id, it gets retained, not replaced.
- Make sure if a div already has an onClick event, it gets replaced, not retained.
- Set margin to 0px, position to absolute.
- It works with 2013 versions of IE8, Firefox, and Chrome.
As stated, the script below, Add Ids and onClicks and Grab and Drop to Divs, does the all tasks above, but also gives you the grab and drop script needed to take advantage of all this preparation work.
On to the script: Only the function addonclicks() is unrelated to grab and drop—all the other functions are grab and drop related. After some simple CSS to style the divs to be grabbed, we have the JavaScript function check(). It is called from inside the div we want to move. The code says: if the div we clicked is being carried, we drop it. But if the div we clicked is not being carried, we pick it up. The flag variable is 1 if the div is getting carried and 0 if it is not. It's set up as an on-off switch. The q variable is where the id of the div goes, or "iii" if we haven't grabbed one.
And, ignoring the function addonclicks() for the moment, next we define the variables we'll need for the grab and drop. It doesn't matter what goes in the divs we grab—it could be a picture or video or paragraph or iframe. We have the function startmouse() run off the onload event in the body tag, and onLoad also runs addonclicks(). The traditional event registration model is used to force the mouse coordinate getting function every time we move the mouse, by use of onmousemove. Note the absence of () after getCoords. Calling the function needs () but registering which event fires getCoords() requires you NOT to use ().
The getCoords() function itself is mostly the standard coordinate reader, which uses different properties depending on the browser, but instead of browser sniffing we check for object support. The clientX event attribute returns the horizontal coordinate (according to the client area) of the mouse pointer when an event was triggered. The client area is the current window. The clientY event attribute returns the vertical coordinate (according to the client area) of the mouse pointer when an event was triggered. The pageX property returns the position of the mouse pointer, relative to the left edge of the document. The pageY property sets or returns the y-coordinate of the mouse pointer relative to the top-left corner of the browser window's client area. The scrollTop property sets or retrieves the number of pixels by which the contents of an object are scrolled upward. The scrollLeft property sets or retrieves the number of pixels by which the contents of an object are scrolled to the left.
We use the getElementById() method to access the div element with the id of the div we clicked on. Then we alter the div's left and top properties to be the cursor's minus 5 pixels. This latter is because when we later drop the div, the cursor's click must be ON the div, not just off its top corner.
Note that we use the window.status property to display the values of the relevant variables. This is OPTIONAL. Delete window.status="x="+x+" y="+y+" flag="+flag+" q="+q+" "; from the script when you use it with your programs since most people's settings won't have status bar writing allowed anyway, including you(?).
But the window.status property does not work in the default configuration of IE, Firefox, Chrome, or Safari. To allow scripts to change the text of the status, the user must set the dom.disable_window_status_change preference to false in the about:config screen. (or in Firefox: "Tools - Options - Content -Enable JavaScript / Advanced - Allow scripts to change status bar text"). One has to also set the status bar to displayed from the View menu in IE8 and others. Funny, our security settings in Internet options for "Allow status bar updating via script" are Disable, but this script still changed the status bar content in IE8. Bug? Anyway, it should be obvious that it is best to disallow such scripting because of potential exploits by nefarious ass clowns. And, again, you may dump this part of the code if or when you use this grab and drop script. (In other words, change window.status="x="+x+" y="+y+" flag="+flag+" q="+q+" ";} to just }.)
We next code the function: addonclicks(). In it, we employ the getElementsByTagName() method to get all the divs in the browser page. These div elements are returned in a NodeList. The NodeList object represents an ordered collection of nodes. The nodes in the NodeList can be accessed through their index number, starting from 0. So one needs to use a for loop for this process. We create an id in the q variable adding i plus 90000 and putting "a" in front. Then we stick this new id attribute into the div with e[i].id=q, unless there is already an id, in which case we leave it alone. We change the position property value to absolute and the margin to 0px. The onclick event is handled similarly, except it needs special handling, and we replace any existing onClick events.
Setting positioning to absolute allows us to enable the grab and drop regardless of what positioning the div used to have. (Note that our divs initially have a variety of positioning styles, one has a margin value, one has an id already, and one even has an onClick event whose handler is a bogus, nonexistent function called test(). This tests the effectiveness of our script. Clicking them shows that all worked fine.) Changing the left and top properties when moving a div around won't help if the positioning is set to static, fixed, or relative. The divs may have gotten positioned with the margin property so we nullify this by setting the 4 margins to 0 with css shorthand.
We wanted to use the setAttribute() method to install our onClick event. But we couldn't. The setAttribute() method is supported in all major browsers, except most users have IE8 or below, and Internet Explorer 8 and earlier does NOT support this method, which makes it pretty useless for the next decade or so. Since it is not cross-browser, the question then becomes: What is? Here is the page (the poster was MooGoo) that offered a cross-browser script, textArea.onclick=function() {resize(this.id);}; to do what we needed: Adding event handler (with parameters) to element created using document.createElement. Nice work! There were warnings in all the forums not to use setAttribute() or getAttribute() methods with IE6-8, since they'll disappoint you. They should rename Microsoft ADLAADS, which means a day late and a dollar short. Or perhaps Internet Explorer could be renamed Internet Straggler.
So anyway, when we utilize e[i].onclick = function() {check(this.id);};, we are using two special tools: anonymous functions and the this keyword. When we use
e[i].onclick = function() {check(this.id);}; the div is the owner of the onclick event since we stuck it into the div in our addonclicks() function, along with an id. Since the div is the owner of the id and the onclick event, "this" means THIS DIV. An onclick property is owned by the HTML element it belongs to, as is an id. This ownership is the result of JavaScript's object oriented approach, ppk informs us. The overall upshot of all this is that the check(this.id) handler for the onClick event will successfully use our div's id as a parameter in the check() function and the script works cross-browser.
The function operator defines a function inside an expression. Anonymous functions are declared using the function operator. You can use the function operator to create a new function wherever it’s valid to put an expression. With e[i].onclick = function() {check(this.id);};, there doesn't seem to be any other cross-browser way to create a function that will get onClick="check(id)" into some divs, other than the way we did it. We tried several ways.
We run the addonclicks() function from the body tag using the onLoad event. Then we create some small colored divs with various properties, and an id and an event. But many of these will change once the addonclicks() function gets its paws on them. If you decide to use our script in your programs, make sure to dump our divs and have the script deal with your divs instead.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Add Ids and onClicks and Grab and Drop to Divs</TITLE>
<style type="text/css">
.grab {position:absolute;font-size:15px;font-weight:bold;color:black;}
</style>
<script type="text/javascript">
function check(id){
if(flag==1){flag=0;q="iii";return;}
if(q=="iii"&&flag==0){flag=1;q=id;}}
function addonclicks(){
var e=document.getElementsByTagName("div");
for(var i=0;i<e.length;i++){
var q="a" + (i + 90000);
if (e[i].id==""){e[i].id=q;}
e[i].style.position="absolute";
e[i].style.margin="0px";
e[i].onclick = function() {check(this.id);};
}}
var q="iii";//which one is grabbed--if none, this is "iii"
var flag=0;//if one is grabbed--if none, this is 0
var id,x,y;
function startmouse() {document.onmousemove=getCoords;}
function getCoords(e){
if (!e) var e = window.event;
if (e.pageX){x = e.pageX;y = e.pageY;} else if
(e.clientX){x = e.clientX + document.body.scrollLeft;y = e.clientY + document.body.scrollTop;}
if(flag==1&&q!="iii"){var myDiv=document.getElementById(q);myDiv.style.left=(x-5)+'px';myDiv.style.top=(y-5)+'px';}
window.status="x="+x+" y="+y+" flag="+flag+" q="+q+" ";}
</script>
</head>
<body onload="addonclicks(),startmouse()">
<div style='background-color:green;width:33px;height:33px;position:relative;top:0px;left:180px'></div>
<div style='background-color:pink;width:33px;height:33px;margin:80px 0 0 120px;position:static;'></div>
<div style='background-color:blue;width:33px;height:33px;position:absolute;top:80px;left:80px'></div>
<div id='m' style='background-color:gray;width:33px;height:33px;position:fixed;top:120px;left:120px'></div>
<div onclick="test()" style='background-color:red;width:33px;height:33px;position:fixed;top:160px;left:160px'></div>
</body>
</html>