PDA

View Full Version : dom elements created, read in array. error while getting old array elements



ReMaX
04-26-2008, 09:38 PM
I drive crazy. I do not understand, why it doesn't work but perhaps I simply see no tree in the forest.


<html>
<body>

<div id="maincontainer">content.bla</div>

<script type="text/javascript">
function VirtualWindows() {

this.vwindows = new Array();
var maincont = document.getElementById("maincontainer");

this.make = function(number) {
var windowXMLString = '<div id="window'+number+'">window '+number+'</div>';
maincont.innerHTML += windowXMLString;
//this.vwindows.push(new Object());
var el = this.vwindows.length;
temp = new Object();
temp["vwindow"] = document.getElementById("window"+number);
this.vwindows[el] = temp;
}

this.showContent = function() {
var temp = '';
for (i=0;i<this.vwindows.length;i++) {
temp += '#'+i+'-'+this.vwindows[i].["vwindow"].innerHTML;
maincont.removeChild(this.vwindows[i].vwindow);
}
alert(temp);
}

}

var vw = new VirtualWindows();
vw.make(0);
vw.make(1);
vw.make(2);
vw.showContent();
</script>
</body>
</html>

Don't wonder, it is only an abstraction, a simple example of my problem. Normally I do not like creating elements and destroying them afterwards.:D
I need those created elements in an array for total access in the future. It will be a windowhandler.
If it works as I want it to the script has to alert "#0-window 0#1-window 1#2-window 2" and all window elements inside "maincontainer" will be deleted!

greetings
Max

jscheuer1
04-27-2008, 02:03 PM
Apparently you cannot store an element in an array and in the document at the same time. I got this to work in two ways, there are probably others.


<html>
<body>

<div id="maincontainer">content.bla</div>

<script type="text/javascript">
function VirtualWindows() {

this.vwindows = new Array();
var maincont = document.getElementById("maincontainer");

this.make = function(number) {
var windowXMLString = '<div id="window'+number+'">window '+number+'</div>';
maincont.innerHTML += windowXMLString;
this.vwindows.push(number);
}

this.showContent = function() {
var temp = '';
for (var i=0;i<this.vwindows.length;i++) {
temp += '#'+i+'-'+document.getElementById('window'+i).innerHTML+'\n';
maincont.removeChild(document.getElementById('window'+i));
}
alert(temp);
}

}

var vw = new VirtualWindows();
vw.make(0);
vw.make(1);
vw.make(2);
vw.showContent();
</script>
</body>
</html>


<html>
<body>

<div id="maincontainer">content.bla</div>

<script type="text/javascript">
function VirtualWindows() {

this.vwindows = new Array();
var maincont = document.getElementById("maincontainer");

this.make = function(number) {
var windowXMLString = '<div id="window'+number+'">window '+number+'</div>';
maincont.innerHTML += windowXMLString;
this.vwindows.push(new Function("return document.getElementById('window'+"+number+")"));
}

this.showContent = function() {
var temp = '';
for (var i=0;i<this.vwindows.length;i++) {
temp += '#'+i+'-'+this.vwindows[i]().innerHTML+'\n';
maincont.removeChild(this.vwindows[i]());
}
alert(temp);
}

}

var vw = new VirtualWindows();
vw.make(0);
vw.make(1);
vw.make(2);
vw.showContent();
</script>
</body>
</html>

If you were to create the new elements via the DOM, then you might be able to store and retrieve them directly as elements. I'll try that, if I have any luck, I'll let you know.

jscheuer1
04-27-2008, 02:23 PM
Yeah, using the DOM, it worked out:


<html>
<body>

<div id="maincontainer">content.bla</div>

<script type="text/javascript">
function VirtualWindows() {

this.vwindows = new Array();
var maincont = document.getElementById("maincontainer");

this.make = function(n) {
var l, v=this.vwindows
v[l=v.length]=document.createElement('div');
v[l].id='window'+n;
v[l].appendChild(document.createTextNode('window '+n));
maincont.appendChild(v[l]);
}

this.showContent = function() {
var temp = '';
for (var i=0;i<this.vwindows.length;i++) {
temp += '#'+i+'-'+this.vwindows[i].innerHTML+'\n';
maincont.removeChild(this.vwindows[i]);
}
alert(temp);
}

}

var vw = new VirtualWindows();
vw.make(0);
vw.make(1);
vw.make(2);
setTimeout('vw.showContent()', 3000);
</script>
</body>
</html>

Notes: The setTimeout at the end is just to give you a few seconds to see that the elements were added. You can replace it with the original line:

vw.showContent();

if you like.

Also, if you want to go 'all DOM' replace this line:

temp += '#'+i+'-'+this.vwindows[i].innerHTML+'\n';

with:

temp += '#'+i+'-'+this.vwindows[i].firstChild.nodeValue+'\n';

ReMaX
04-27-2008, 09:44 PM
Thanks a lot, John!
But there's another problem. Now, I use your second way because I give the window a special content, which can be a large XML string.
My new problem: If I want to give those dom elements special functions, for some reason, ít only works on one element.
Look at this:


function VirtualWindows() {

this.vwindows = new Object();
var maincont = document.getElementById("maincontainer");

this.make = function(content,top) {
var componentindex;
for (var prop in this.vwindows)
componentindex++;
var windowid = "window"+componentindex;
var windowXMLString = '<div id="'+windowid+'" style="border:1px solid red;width:50px;height:50px;position:absolute;top:'+top+'px;left:100px;">'+content+'</div>';
maincont.innerHTML += windowXMLString;var vwindow = new Object();
vwindow.getElement = new Function("return document.getElementById('"+windowid+"')");
this.vwindows[windowid] = vwindow;
this.vwindows[windowid].getElement().onclick = function() { alert('I am able to interact!'); };
};

this.showContent = function() {
var temp = '';
for (var prop in this.vwindows) {
temp += '#'+prop+'-'+this.vwindows[prop].getElement().innerHTML;
}
alert(temp);
};

}

var vw = new VirtualWindows();
vw.make("<span>asldfjdas</span>",50);
vw.make("<div>asdölfkj</div>",200);
vw.make("<div>öalskdj fpoiasd</div>",500);
vw.showContent();

???

jscheuer1
04-28-2008, 01:25 AM
That's why the true DOM methods, however tedious, are best for this sort of thing. There is a way around it here, but the more you try to get out of this, the greater the manipulations will become to pull it off without the true DOM, which after awhile actually will require less code.

The main problem is that you are repeatedly sucking up the innerHTML property, adding to it, and spitting it back into the parent, obliterating whatever was there before. However, the events you are adding aren't necessarily a part of the the innerHTML property (innerHTML is capricious in this regard when events are added to elements as functions, not strings). When they aren't, they get lost, if they are 'hard coded' as a part of the string (which incidentally isn't a true XML string), they will get preserved:


function VirtualWindows() {

this.vwindows = new Object();
var maincont = document.getElementById("maincontainer");

this.make = function(content,top) {
var componentindex=0;
for (var prop in this.vwindows)
componentindex++;
var windowid = "window"+componentindex;
var windowXMLString = '<div id="'+windowid+
'" onclick="alert(\'I am able to interact - hard coded #'+componentindex+'\');" '+
'style="border:1px solid red;width:50px;height:50px;position:absolute;top:'+top+
'px;left:100px;background-color:#ccc;">'+content+'</div>';
maincont.innerHTML += windowXMLString;var vwindow = new Object();
vwindow.getElement = new Function("return document.getElementById('"+windowid+"')");
this.vwindows[windowid] = vwindow;

};

this.showContent = function() {
var temp = '';
for (var prop in this.vwindows) {
temp += '#'+prop+'-'+this.vwindows[prop].getElement().innerHTML;
}
alert(temp);
};

}

var vw = new VirtualWindows();
vw.make("<span>asldfjdas</span>",50);
vw.make("<div>asdölfkj</div>",200);
vw.make("<div>öalskdj fpoiasd</div>",500);
vw.showContent();

jscheuer1
04-28-2008, 03:34 AM
To bolster my argument about how, as things become more complex, they begin to become easier using the DOM:


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

</head>
<body>
<div id="maincontainer">something</div>
<script type="text/javascript">
function VirtualWindows() {

var vwindows = new Object();
var maincont = document.getElementById('maincontainer');

this.cr = function(el, txt, id, evt){
var e = document.createElement(el); if(id) e.id = id;
if(txt) e.appendChild( document.createTextNode(txt) );
if(evt) e[evt.ev] = evt.f; return e;
};

this.make = function(el, txt, tp) {
var componentindex=0;
for (var prop in vwindows) componentindex++;
var windowid = 'window'+componentindex;
var nNode = this.cr('div', '', windowid, {ev:'onclick', f:function(){alert('ready to boogy #'+componentindex);}});
with (nNode.style){border='1px solid red';width='50px';height='50px';position='absolute';
top=tp+'px';left='100px';backgroundColor='#ccc';};
nNode.appendChild( this.cr(el, txt) );
maincont.appendChild(nNode);
vwindows[windowid] = nNode;
};

this.showContent = function() {
var temp = '';
for (var prop in vwindows) {
temp += '#'+prop+'-'+vwindows[prop].innerHTML + ' onclick-'+vwindows[prop].onclick+'\n';
}
alert(temp);
};

}

var vw = new VirtualWindows();
vw.make('span', 'asldfjdas', 50);
vw.make('div', 'asdölfkj', 200);
vw.make('div', 'öalskdj fpoiasd' ,500);
vw.showContent();
</script>
</body>
</html>

ReMaX
04-28-2008, 09:26 PM
Hey, John, thank you a lot!!! Of course! That cr function is very smart. I do it now as you said and everything is fine. In your post, I also learned a few more general JS features I didn't know before: The with-function and those {} to give the element a function:D. Without you my window API wouldn't work! Thanks!

greetings
Max

jscheuer1
04-29-2008, 05:53 AM
I'm not sure with would be called a function, it is more like a method or a statement. Using {} to pass the event is just an advanced way of using javascript objects that has become popular in many of the javascript frameworks (like jQuery, prototype, and mootools) to pass arguments. You see, whatever is in the {} when passed as an argument, emerges in the function you pass it to as properties of an Object with the same name as the function's name for that argument.

ReMaX
04-29-2008, 03:34 PM
Yeah, great. I do not use JS frameworks because I like doing things myself. I am now ready with a windowhandler that works better than this: http://prototype-window.xilinus.com/PWC-OS/ .:cool:
It is a nice idea to give parameters as object.
Like I said, I thank you a lot and I would like to send you a beer via mail :D.