PDA

View Full Version : "document.getElementById" issue.



shachi
08-03-2006, 04:50 PM
Hello everyone, I just came to know about a document.getElementById issue. What the problem is document.getElementById only gets the first element which has a certain id. What I mean is if I have this piece of code:



<html>
<head>
<title></title>
<script type="text/javascript">
function disappear(){
var testdiv = document.getElementById("test");
testdiv.style.visibility = "hidden";
}
</script>
</head>
<body>
<div id="test" style="width: 100px;height: 100px;background-color: red"></div>
<div id="test" style="width: 100px;height: 100px;background-color: red"></div><div id="test" style="width: 100px;height: 100px;background-color: red"></div><div id="test" style="width: 100px;height: 100px;background-color: red"></div><div id="test" style="width: 100px;height: 100px;background-color: red"></div><div id="test" style="width: 100px;height: 100px;background-color: red"></div>
<input type="button" value="Disappear" onclick="disappear();">
</body>
</html>



And if I click on the button only the first(the div with test id which appears at first) disappears and not the others:eek: . Now I have no idea how to make all the divs disappear. Any help would be appreciated.
Thanks.

blm126
08-03-2006, 05:21 PM
According to the W3 specs only one element may have a certain ID.
That is the difference between classes and IDs. This is the way it is intended to work.

shachi
08-03-2006, 05:29 PM
blm126: yes I know but in my case I can't loop through arrays having the same class name.:(

blm126
08-03-2006, 06:17 PM
Why Not?


function hideclass(searchClass) {
var els = document.getElementsByTagName("*");
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (i = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
els[i].style.visibility = "hidden";
}
}
}

shachi
08-03-2006, 06:34 PM
Because I want variables to be passed to the element.



var obj = getElementsById("drag");
for(var i = 0;i < obj.length;i++){
objX = parseInt(obj[i].offsetLeft);
objY = parseInt(obj[i].offsetTop);
objH = parseInt(obj[i].offsetHeight);
objW = parseInt(obj[i].offsetWidth);
objXpW = objX + objW;
objYpH = objY + objH;
}

if(objX > targX && objY > targY && objX < targXpW && objY < targYpH){
next.innerHTML = "Got It!!!";
} else {
next.innerHTML = "";
}

function getElementsById(sId)
{
var outArray = new Array();
if(typeof(sId)!='string' || !sId)
{
return outArray;
};

if(document.evaluate)
{
var xpathString = "//*[@id='" + sId.toString() + "']"
var xpathResult = document.evaluate(xpathString, document, null, 0, null);
while ((outArray[outArray.length] = xpathResult.iterateNext())) { }
outArray.pop();
}
else if(document.all)
{

for(var i=0,j=document.all[sId].length;i<j;i+=1){
outArray[i] = document.all[sId][i];}

}else if(document.getElementsByTagName)
{

var aEl = document.getElementsByTagName( '*' );
for(var i=0,j=aEl.length;i<j;i+=1){

if(aEl[i].id == sId )
{
outArray.push(aEl[i]);
};
};

};

return outArray;
}

mwinter
08-03-2006, 06:53 PM
[Why isn't using class names to identify multiple elements] Because I want variables to be passed to the element.
That's not an answer that means anything; variables can't be passed to an element as elements aren't functions.

There's nothing in the code that you posted that suggests that using class names is not an option, nor is there any logical reason that I can think of at the moment why that should be the case.

Mike

shachi
08-03-2006, 07:01 PM
mwinter: here's my full code.



<html>
<head>
<script type="text/javascript">
var ie = document.all;
var ns = document.getElementById && !ie;
var x,y;
var dobj;
var isdrag = false;

function contDrag(e){
if(isdrag){
dobj.style.left = ns ? tx + e.clientX - x : tx + event.clientX - x;
dobj.style.top = ns ? ty + e.clientY - y : ty + event.clientY - y;
return false;
}
}

function initDrag(e){
topelements = ns ? "HTML" : "BODY";
fobj = ns ? e.target : e.srcElement;
while(fobj.tagName != topelements && fobj.className != "drag"){
fobj = ns ? fobj.parentNode : fobj.parentElement;
}
if(fobj.className == "drag"){
isdrag = true;
dobj = fobj;
tx = parseInt(dobj.style.left + 0,10);
ty = parseInt(dobj.style.top + 0,10);
x = ns ? e.clientX : event.clientX;
y = ns ? e.clientY : event.clientY;
document.onmousemove = contDrag;
}
var cart = document.getElementById("cart");
}

function getElementsById(sId)
{
var outArray = new Array();
if(typeof(sId)!='string' || !sId)
{
return outArray;
};

if(document.evaluate)
{
var xpathString = "//*[@id='" + sId.toString() + "']"
var xpathResult = document.evaluate(xpathString, document, null, 0, null);
while ((outArray[outArray.length] = xpathResult.iterateNext())) { }
outArray.pop();
}
else if(document.all)
{

for(var i=0,j=document.all[sId].length;i<j;i+=1){
outArray[i] = document.all[sId][i];}

}else if(document.getElementsByTagName)
{

var aEl = document.getElementsByTagName( '*' );
for(var i=0,j=aEl.length;i<j;i+=1){

if(aEl[i].id == sId )
{
outArray.push(aEl[i]);
};
};

};

return outArray;
}


function termDrag(e){
isdrag = false;
with(document){
targ = getElementById("cart");
//obj = getElementById("drag");
space = getElementById("coor");
next = getElementById("nexcoor");
}
var obj = getElementsById("drag");

targX = parseInt(targ.offsetLeft - 8);
targY = parseInt(targ.offsetTop - 8);
targH = parseInt(targ.offsetHeight);
targW = parseInt(targ.offsetWidth);
targXpW = targX + targW;
targYpH = targY + targH;
for(var i = 0;i < obj.length;i++){
objX = parseInt(obj[i].offsetLeft);
objY = parseInt(obj[i].offsetTop);
objH = parseInt(obj[i].offsetHeight);
objW = parseInt(obj[i].offsetWidth);
objXpW = objX + objW;
objYpH = objY + objH;
}

if(objX > targX && objY > targY && objX < targXpW && objY < targYpH){
next.innerHTML = "Got It!!!";
} else {
next.innerHTML = "";
}
}
document.onmousedown = initDrag;
document.onmouseup = termDrag;

</script>
<style type="text/css">
div.drag {
width: 100px;
height: 100px;
background-color: red;
position: relative;
z-index: 200;
}
div.drag:active {
cursor: move;
}
div.cart {
width: 500px;
background-color: green;
height: 350px;
position: relative;
left: 300px;
}
</style>
</head>
<body>
<div id="drag" class="drag">television</div>
<div id="drag" class="drag">table</div>
<div id="drag" class="drag">sink</div>
<div id="cart" class="cart"></div>
<div id="coor"></div>
<div id="nexcoor"></div>
</body>
</html>



That shall be enough to tell you what I am trying to do.

The problem I am facing with this is the script displays "Got It!!!" only when the first div is dropped in the target.

Twey
08-03-2006, 08:41 PM
Give up on the browser detection! It is a flawed concept. Use feature detection instead.

You cannot have multiple elements with the same ID. It will simply not work. You could build a (or use a prebuilt) getElementsByClassName function, or you could use a similar method, but with different IDs through which one can loop:
function getElementsByIDStart(base) {
for(var i = 1, ret = [], e; e = document.getElementById(base + i); ++i)
ret.push(e);
}

shachi
08-04-2006, 06:50 AM
Twey, Thanks for your reply but how do I use feature detection?? I haven't even used half of the browsers on the web and don't know almost all the features.:(

If I don't have multiple IDs then how do I detect if the user has dropped item in the target(as that code uses ids to detect elements' offsetwidth and offsetheight)?? If I must not use IDs then how do I know if the user has dropped the item in the target, I have no idea??

And what does this code do??



function getElementsByIDStart(base) {
for(var i = 1, ret = [], e; e = document.getElementById(base + i); ++i)
ret.push(e);
}

jscheuer1
08-04-2006, 07:01 AM
The beauty of feature (object) detection is that it doesn't require that you know browsers. It simply tests to see whether or not the object you are about to use exists or not, ex:


var theEl=document.all? document.all[id] : document.getElementById? document.getElementById(id) : null;

Twey
08-04-2006, 04:14 PM
And what does this code do??With the return statement I accidentally omitted:
function getElementsByIDStart(base) {
for(var i = 1, ret = [], e; e = document.getElementById(base + i); ++i)
ret.push(e);
return ret;
}it will allow you to have elements with IDs such as droptarget1, droptarget2, droptarget3... and allow you to call getElementsByIDStart("droptarget") to fetch an array of them all. This way, they all have unique IDs, but are also able to be fetched as an array.

shachi
08-04-2006, 06:28 PM
Thanks Twey, let me try that.:)

sharmin
08-04-2006, 06:32 PM
Give up on the browser detection! It is a flawed concept. Use feature detection instead.

You cannot have multiple elements with the same ID. It will simply not work. You could build a (or use a prebuilt) getElementsByClassName function, or you could use a similar method, but with different IDs through which one can loop:
function getElementsByIDStart(base) {
for(var i = 1, ret = [], e; e = document.getElementById(base + i); ++i)
ret.push(e);
}


Have you read my tree menu problem, that i have posted today...

Please respond at my message.

shachi
08-04-2006, 06:36 PM
Twey, is it my stupidity or is there still some problems that it is still not working.

Here's the code so far.



<html>
<head>
<script type="text/javascript" src="drag.js"></script>
<style type="text/css">
div.drag {
width: 100px;
height: 100px;
background-color: red;
position: relative;
z-index: 200;
}
div.drag:active {
cursor: move;
}
div.cart {
width: 500px;
background-color: green;
height: 350px;
position: relative;
left: 300px;
}
</style>
</head>
<body>
<div id="drag1" class="drag">television</div>
<div id="drag2" class="drag">table</div>
<div id="drag3" class="drag">sink</div>
<div id="cart" class="cart"></div>
<div id="coor"></div>
<div id="nexcoor"></div>
</body>
</html>


drag.js:



var ie = document.all;
var ns = document.getElementById && !ie;
var x,y;
var dobj;
var isdrag = false;

function contDrag(e){
if(isdrag){
dobj.style.left = ns ? tx + e.clientX - x : tx + event.clientX - x;
dobj.style.top = ns ? ty + e.clientY - y : ty + event.clientY - y;
return false;
}
}

function initDrag(e){
topelements = ns ? "HTML" : "BODY";
fobj = ns ? e.target : e.srcElement;
while(fobj.tagName != topelements && fobj.className != "drag"){
fobj = ns ? fobj.parentNode : fobj.parentElement;
}
if(fobj.className == "drag"){
isdrag = true;
dobj = fobj;
tx = parseInt(dobj.style.left + 0,10);
ty = parseInt(dobj.style.top + 0,10);
x = ns ? e.clientX : event.clientX;
y = ns ? e.clientY : event.clientY;
document.onmousemove = contDrag;
}
var cart = document.getElementById("cart");
}

function getElementsByIDStart(base) {
for(var i = 1, ret = [], e; e = document.getElementById(base + i); ++i)
ret.push(e);
return ret;
}

/* function getElementsById(sId)
{
var outArray = new Array();
if(typeof(sId)!='string' || !sId)
{
return outArray;
};

if(document.evaluate)
{
var xpathString = "//*[@id='" + sId.toString() + "']"
var xpathResult = document.evaluate(xpathString, document, null, 0, null);
while ((outArray[outArray.length] = xpathResult.iterateNext())) { }
outArray.pop();
}
else if(document.all)
{

for(var i=0,j=document.all[sId].length;i<j;i+=1){
outArray[i] = document.all[sId][i];}

}else if(document.getElementsByTagName)
{

var aEl = document.getElementsByTagName( '*' );
for(var i=0,j=aEl.length;i<j;i+=1){

if(aEl[i].id == sId )
{
outArray.push(aEl[i]);
};
};

};

return outArray;
}
*/

function termDrag(e){
isdrag = false;
with(document){
targ = getElementById("cart");
//obj = getElementById("drag");
space = getElementById("coor");
next = getElementById("nexcoor");
}
/*objX = parseInt(targ.style.left + 0);
objY = parseInt(targ.style.top + 0);
objX = parseInt(targ.offsetLeft);
objY = parseInt(targ.offsetTop);
anX = parseInt(obj.offsetLeft);
anY = parseInt(obj.offsetTop);
objWidth = parseInt(targ.style.width + 0,10);
objHeight = parseInt(targ.style.height + 0,10);
objXpW = objX + objWidth;
objYpH = objY + objHeight;
space.innerHTML = "X: "+objX+" Y: "+objY+"<br>X: "+anX+" Y: "+anY;
next.innerHTML = "X+Width: "+objXpW+" Y+Height: "+objYpH;*/
var obj = getElementsByIDStart("drag");

targX = parseInt(targ.offsetLeft - 8);
targY = parseInt(targ.offsetTop - 8);
targH = parseInt(targ.offsetHeight);
targW = parseInt(targ.offsetWidth);
targXpW = targX + targW;
targYpH = targY + targH;
/*for(var i = 0;i < obj.length;i++){
objX = parseInt(obj[i].offsetLeft);
objY = parseInt(obj[i].offsetTop);
objH = parseInt(obj[i].offsetHeight);
objW = parseInt(obj[i].offsetWidth);
}*/
objX = parseInt(obj.offsetLeft);
objY = parseInt(obj.offsetTop);
objH = parseInt(obj.offsetHeight);
objW = parseInt(obj.offsetWidth);
objXpW = objX + objW;
objYpH = objY + objH;

if(objX > targX && objY > targY && objX < targXpW && objY < targYpH){
next.innerHTML = "Got It!!!";
} else {
next.innerHTML = "";
}
}
document.onmousedown = initDrag;
document.onmouseup = termDrag;

Twey
08-04-2006, 07:37 PM
"not working" is not an adequate description of a problem.

mwinter
08-05-2006, 12:17 AM
I've uploaded a reworked version (http://mwinter.webhop.info/dd/shachi/drag.html) of the code. It hasn't been tested outside of IE6 and Firefox 1.5, and it certainly could do with some improvements. However, it does demonstrate feature detection, which was raised in this thread, quite extensively.

One matter of note is the rudimentary event system that's been implemented. By calling the addEventListener and removeEventListener of the Drag object, client code can be notified when a draggable element is activated by the user, and when it is released. The event type for the former is called 'drag-start' and 'drag-end' for the latter. A drag-end listener is illustrated in the example: it performs the task of examining the position of the target and container in the original code.

Mike

shachi
08-05-2006, 06:07 AM
mwinter: thanks for your help, but there is one problem. As soon as I drop the object it doesn't cancel the event. What I mean is when I drop the item in the cart and a alert appears and when I go to click OK then the object follows my mouse. But anyways I don't need to alert. Thanks again.:)

Twey: sorry for the delay and apologise that I said that 'it didn't work' ok, here's my problem, the drag and drop cart script(which I included above) only detects the div which is declared first. And after applying your script it didn't show anything even when I dropped the first one declared. So that's the problem.

mwinter
08-05-2006, 02:20 PM
As soon as I drop the object it doesn't cancel the event. What I mean is when I drop the item in the cart and a alert appears and when I go to click OK then the object follows my mouse.

I know, but it only occurs (here, anyway) if an alert is triggered from a drag event (one of the ones I introduced, that is) listener, and that alert is dismissed with the mouse.



But anyways I don't need to alert.

Precisely. I couldn't be bothered to write code to manipulate text nodes, so I opted for an alert. I was only an example, after all. :p

Mike