so i have a <ul> and I allow the user to append items to it. The
problem is that on mozilla the <span class="line"> which is just a line
to divide the sections
gets overlaped and doesnt move down and adjust to the newly added items
like it does in iE.
So you have a problem with the style you are applying to the span.
This is a JavaScript newsgroup, why do you expect answers to
CSS/style problems?
Why do you expect any answer at all when you don't show the CSS for
the style you are applying?
It just occured to me that i dont really have to
use a span, and a html <hr> tag could do the trick -I will go try. But
aside from that could some one explain why this occurs? And will I get
the overlapping on other browsers? (oh and I know about innerHTML
support, I will change that.)
It is much better to use DOM for this type of operation. innerHTML
is great where you just want to splat some text or minimal markup
into somewhere, but it should not be used extensively for adding
elements, intrinsic events, attribute, etc.
The action attribute is required for form elements.
<ul id="uploadList">
<li>
<input id="file1" type="file" /></li>
<li id="end">
<a
href="javascript:attachAnother('uploadList');">Blah</a></li>
The javascript pseudo-protocol is unnecessary. Use an onclick event
and an href that links to a page to replace whatever functionality is
provided by the script. Return a suitable value from the script to
decide whether the link is followed or not:
<a href="sansJS.html" onclick="
return attachAnother('uploadList');">Blah said:
</ul>
<span class="line"> </span><br/>
<input type="submit" id="upload" />
</form>
Do not indent code with tabs, it makes assisting you far more
difficult than it need be and the uncontrolled wrapping it causes
often introduces new errors. Use 2 or 4 spaces for indents and wrap
code manually at about 70 characters.
CODE:
function attachAnother(e)
{
var li,id,fileLi,file;
var end = document.getElementById('end')
You should use feature detection and not assume every browser
supports a particular method. Maybe you also want to support older
browsers with document.all too:
var end;
if (document.getElementById) {
end = document.getElementById('end');
} else if (document.all) {
end = document.all['end'];
}
var ul = document.getElementById(e);
If you are going to use document.getElementById frequently, you may
wish to include something like the DynWrite function suggested on
this group's FAQ:
if( ul == null || end == null || ul.childNodes.length < 2)
return;
It is common to evaluate these in the reverse context so that any
syntax errors will show up. e.g.
if( ul = null || ...
will set ul to null and return true every time. If your testing is
not thorough, you will miss the error. Alternatively:
if( null = ul || ...
will throw an error every time that you will be able to debug and
correct to:
if( null == ul || ...
You could use;
if ( !ul || ...
// get the last <input> and make sure it
// has some value b4 we add another.
fileLi = ul.childNodes[ul.childNodes.length-2];
if(fileLi.firstChild.value != ''") {
There is a syntax error here ---------------^
You should be more careful and test that nodes exist before trying to
use them in expressions, as if they don't exist your script will
error and exit. Different browsers insert extra nodes in some
places, you can't be certain that any particular node will have a
firstChild.
If you create your inputs inside a form, or use getElementById on
your starting 'ul' tag then getElementsByTagName, you will have much
more certain results.
if( fileLi && fileLi.firstChild && fileLi.firstChild.value != ''") {
//file = fileLi.firstChild.clone();
id = 'liFile' + fileCount;
Where is 'fileCount' initialised?
li = document.createElement('li');
li.id = id;
This id is not used and not needed, why add it?
li.innerHTML = '<input type="file" id="File"' + fileCount++ +
'/>';
This will create elements with id="File". Creating multiples will
create numerous elements with the same id, which is invalid HTML and
you will likely only ever be able to access the first one (if any).
If you want the value of 'fileCount' to be included in the id (which
seems to be what you are attempting ):
li.innerHTML = '<input type="file" id="File' + fileCount++ + '"/>';
But anyway, form elements need both a name and a value to be
successful, so add a name and not an id (which isn't used and
therefore not needed).
li.innerHTML +=' <a
href="javascript:removeFile(\'uploadList\',\'' + id + '\');">Remove
File</a>';
As above, use an onclick event, not javascript pseudo-protocol. Have
the href go somewhere useful for non-JavaScript browsers and return
false to cancel it if your onclick exits successfully.
//li.insertBefore(file,null);
ul.insertBefore(li,end);
}
}
Anyhow, sick of finding errors. Here is a script that does
everything you are attempting but uses all DOM, no innerHTML.
I don't think it fixes your style issue since you haven't told anyone
what it is. There are still logic flow and usability issues, good
luck.
Tested in Firefox and IE - IIRC, some versions of IE have issues with
creating input type file, test thoroughly.
<script type="text/javascript">
// Provides limited support for getElementById for
// browsers that only support document.all
if (!document.getElementById && document.all) {
document.getElementById = function(id){
return document.all[id];
}
}
function attachAnother(ele) {
var li,id,fileLi,file;
var end = document.getElementById('end')
var ul = document.getElementById(ele);
if( !ul || !end || ul.childNodes.length < 2) {
return true; // Link will be followed, add input at server
}
// get the last <input> and make sure it
// has some value b4 we add another.
// fileLi = ul.childNodes[ul.childNodes.length-2];
var inputs = ul.getElementsByTagName('input');
if ( 0 < inputs.length ) {
fileLi = inputs[inputs.length-1];
}
// To ensure unique IDs, add '1' to last input id
if ( fileLi.id) {
var fileCount = fileLi.id.split('-')[1];
fileCount++;
}
if(fileLi.value != '') {
id = 'liFile' + fileCount;
oLi = document.createElement('li');
oLi.id = id; // don't need an id on the li
// Create the input - must have a name to be successful
var oInp = document.createElement('input');
oInp.type = 'file'
oInp.name = 'File-' + fileCount;
// Create link
var oA = document.createElement('a');
oA.href = 'aUsefulURI.html';
oA.onclick =
function() {
return removeFile(this.parentNode)
};
// Add text to link
oA.appendChild(document.createTextNode('Remove Upload'));
// Add 'em all before last li
oLi.appendChild(oInp);
oLi.appendChild(oA);
end.parentNode.insertBefore(oLi,end);
} else {
alert('Will only add another one'
+ ' if you have selected a file in this one');
}
return false;
}
function removeFile(a) {
// If remove works, return false to stop link being followed
if (a.parentNode && a.parentNode.removeChild) {
return !a.parentNode.removeChild(a);
}
return true;
}
</script>
<form>
<ul id="uploadList">
<li>
<input id="File-1" type="file"></li>
<li id="end">
<a href="useful.html" onclick="
return attachAnother('uploadList');
">Add another</a></li>
</ul>
<span class="line"> </span><br>
<input type="submit" id="upload">
</form>