[JS] Element uit div verwijderen

Pagina: 1
Acties:
  • 166 views sinds 30-01-2008
  • Reageer

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Als je bij GMail meerdere attachments aan je bericht wil toevoegen, hebben ze hier een hele mooie interface voor:

Afbeeldingslocatie: http://www.danandan.luna.nl/got/gmail-file.jpg

Telkens als je op "Attach another file" klikt, krijg je een nieuwe file input box. Ook kun je alle aangemaakte file inputs verwijderen ("remove").

Eenzelfde interface zou ik graag voor mijn eigen website hebben. Ik ben eerst naar de gmail source gaan kijken maar heb dat al snel opgegeven: die is niet te lezen. Dus dan maar zelf doen :)

Ik ben nu zover dat ik file inputs kan toevoegen en ze een unieke id mee kan geven.
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
var num_files = 0;

function remove(id) {
  // ?
}

function add() {
  num_files++;

  var div = document.getElementById('files').innerHTML;
  var str = '<input id="image_'+num_files+'" type="file">'+
            '<a href="javascript: remove('+num_files+')">remove</a><br>';

  document.getElementById('files').innerHTML = div+str;
}
</script>

<div id="files">
  <input id="image_0" type="file"><br>
</div>
<a href="javascript: add()">Nog een plaatje uploaden</a>

Ik heb alleen geen idee hoe ik nu een file input moet verwijderen. Ik heb dit als remove functie geprobeerd:
code:
1
2
3
4
5
6
function remove(id) {
  var div = document.getElementById('files').innerHTML;
  var str = (document.getElementById('image_0')); //test

  document.getElementById('files').innerHTML = div-str;
}

Maar dan krijg ik een NaN error, waarschijnlijk omdat je strings wel kunt optellen (zoals bij de add() functie) maar niet zomaar kunt aftrekken van elkaar. Eigenlijk is het ook geen optellen, maar eerder "aan elkaar plakken" van twee strings, natuurlijk...

Mijn vragen zijn:
  • met welke aanpassing is de remove functie werkend te krijgen? (volgens mij is het iets kleins?)
  • is dit ueberhaupt wel een goede manier om de html in een browser te manipuleren? Ik heb er ook aan gedacht om elke file input in een aparte tabel rij te zetten, en dat ik dan de <tr > met de goede id in zijn geheel verwijder. Dat is misschien netter, hoewel tabellen symantisch gezien daar niet voor bedoeld zijn...

[ Voor 20% gewijzigd door Reveller op 03-07-2005 19:53 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:59

alienfruit

the alien you never expected

removeChild() ?
Overigens zal ik gewoon createElement() e.d. gebruiken ipv van innerHtml. Misschien minder snel maar werkt heerlijk voor het manipuleren van html meuk. Kijk ook eens op de website van de scriptnazi: http://www.quirksmode.org/dom/innerhtml.html

Zie verder ook mijn schoolopdracht (barslecht maar werkt O-) )::
http://student-kmt.hku.nl...l/tmp.js/eindopdracht.rar

Een voorbeeld uit het hoofd:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
holder = document.getElementById( 'attachments' );

anchorElement = document.createElement( 'a' );
anchorElement.onclick = removeDownload.
anchorElement.setAttribute( "name", "removeLink" + nIndex );
anchorElement.appendChild( document.createTextNode( 'remove' );
holder.appendChild( anchorElement );

inputElement = document.createElement( 'input' );
inputElement.setAttribute( "type", "file" );
inputElement.setAttribute( "name", "file" + nIndex );
holder.appendChild( inputElement );
teller++;

// weggooien
function removeDownload( nIndex ) {
     var x = document.getElementById( "file" + nIndex );
     var y = document.getElementById( "removeLink" + nIndex );
     var z = document.getElementById( "attachments" );
     z.removeChild( x );
     z.removeChild( y );
     teller--;
}

[ Voor 193% gewijzigd door alienfruit op 03-07-2005 19:59 ]


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
alienfruit schreef op zondag 03 juli 2005 @ 19:49:
Een voorbeeld uit het hoofd:
[...code...]
Lastige materie :) Ik heb geprobeerd er een werkend voorbeeld van te maken:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<script>
var teller = 0;

function add() {
  holder = document.getElementById('attachments');

  anchorElement = document.createElement('a');
  anchorElement.onclick = removeDownload;
  anchorElement.setAttribute("name", "removeLink" + teller);
  anchorElement.appendChild(document.createTextNode('remove'));

  holder.appendChild(anchorElement);

  inputElement = document.createElement('input');
  inputElement.setAttribute("type", "file");
  inputElement.setAttribute("name", "file" + teller);
  holder.appendChild(inputElement);

  teller++;
}

function removeDownload(nIndex) {
  var x = document.getElementById("file" + nIndex);
  var y = document.getElementById("removeLink" + nIndex);
  var z = document.getElementById("attachments");

  z.removeChild(x);
  z.removeChild(y);

  teller--;
}
</script>

<div id="attachments"></div>
<a href="javascript: add()">Nog een plaatje uploaden</a>

Het toevoegen van nieuwe file inputs gaat perfect. Het woordje "remove" is alleen geen link (niet onderstreept, cursor verandert niet in handje), maar geeft wel een reaktie als je er op klikt. Die reaktie is alleen een dikke error in mijn javascript console: "uncaught exception: removeDownload : data: no". Kan iemand mij hier mee verder helpen. En een tweede vraag: op deze manier worden alle elementen naast elkaar geplaatst in plaats van onder elkaar. Hoe zorg ik via deze weg voor een "<br >" op de goede plaats?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Verwijderd

innerHTML is wel de snelste methode, maar het heeft zo zijn nadelen. Zo heb je namelijk in de eerste plaats geen referenties naar je objecten, je dumpt immers een string.

removeChild is de method die je moet hebben voor het verwijderen van je elementen. Kijk alleen nog even uit of je alle referenties naar je elementen opruimt, dan voorkom je geheugen lekken.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:59

alienfruit

the alien you never expected

Ja, volgens moet href-attribuut altijd een waarde hebben, anders werkt het niet lekker. Probeer dat eens :)

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik heb het volgende toegevoegd en nu wordt het wel een link :)
code:
1
anchorElement.href = '#';

Blijft echter het probleem van de "uncaught exception" ... heb jij enig idee?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 10:07

crisp

Devver

Pixelated

"als het geen link is, gebruik dan geen a-element (anchor)". Dingen als onderlijning en een andere cursor kan je met CSS doen.

Intentionally left blank


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:59

alienfruit

the alien you never expected

Misschien probleem dat je geen parameters meestuurt? Ik zou het anders ook niet weten, script nazi wist het tijdens de lessen ook niet.

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 10:07

crisp

Devver

Pixelated

Even een testje geproggeld the unobtrusive way en mbv DOM methods: http://therealcrisp.xs4all.nl/meuk/fileinputs.html
Hij is nog wel aardig markup gevoelig, maar het geeft wellicht wat ideeen :)

Intentionally left blank


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
crisp schreef op zondag 03 juli 2005 @ 22:24:
Even een testje geproggeld the unobtrusive way en mbv DOM methods: http://therealcrisp.xs4all.nl/meuk/fileinputs.html
Hij is nog wel aardig markup gevoelig, maar het geeft wellicht wat ideeen :)
Crisp, dank je! Ik ga er meteen naar kijken. Vannacht ben ik zelf nog wat aan het prutsen geweest om het op te lossen mbv innerHTML:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<style type="text/css">
.jsaction {
  color: blue;
  text-decoration: underline;
  cursor: pointer;
}
</style>

<script>
function addFileInput() {
  var div = document.getElementById('fileInPuts').innerHTML;
  var arr = div.split("<br>");
  var inp = '<input name="file[]" type="file" size="50"> <a class="jsaction" onclick="removeFileInput()">remove</a>';

  arr[arr.length] = inp;

  document.getElementById('fileInPuts').innerHTML = arr.join('<br>');;
}

function removeFileInput() {
  var div = document.getElementById('fileInPuts').innerHTML;
  var arr = div.split("<br>");

  if (arr.length > 1) {
    arr.pop();
  }

  document.getElementById('fileInPuts').innerHTML = arr.join('<br>');
}
</script>

<div id="fileInPuts"><input name="file[]" type="file" size="50"></div>
<a class="jsaction" onclick="addFileInput()">Add fileinput</a>

Toen het af was bleek ineens dat het niet werkte:
  • je kunt alleen telkens de laatste file input verwijderen (niet de middelste bijvoorbeeld). Of je moet removeFileInput uitbreiden met een parameter input, dan kan het weer wel natuurlijk
  • omdat je de innerHTML telkens opnieuw opbouwt, verlies je de inhoud van de andere file inputs als je er 1 verwijderd...
Aldoende leert men, zullen we maar zeggen. Ik dacht het misschien toch met innerHTML te kunnen oplossen, maar dat blijkt tegen te vallen. Vraagje: klopt het dat je via innerHTML altijd de value van de file inputs zult verliezen? Ach, via DOM is het ws. nog veel netter ook. Ik ga er even op studeren!

[ Voor 37% gewijzigd door Reveller op 04-07-2005 10:17 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 10:07

crisp

Devver

Pixelated

Je kan en mag de value van een file input niet manipuleren middels script (vanwege security), dus dat zal inderdaad de reden zijn dat je hem verliest als je de innerHTML probeert te overschrijven.

Intentionally left blank


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Crisp's code bevat een aantal framework functies waarmee je leuk kunt spelen om DOM elementen toe te voegen / te verplaatsen. Sommige dingen snap ik nog niet helemaal, maar dat komt wel. Het grootste raadsel waar ik mee zit is dit:

Afbeeldingslocatie: http://www.danandan.luna.nl/got/fileinputs.jpg

Je ziet: bij de eerste file input zit er een aantal pixels ruimte tussen de browse-knop en de remove-link. Bij de tweede en volgende inputs is deze ruimte weg. De html van bovenstaande (verkregen door een innerHTML alert):
HTML:
1
2
3
4
<fieldset><legend>Images to upload</legend><div class="form-item">
 <input class="form-file" name="uploadfile[]" id="uploadfile[]" size="50" type="file">
<span class="jsaction">remove</span></div>
<div class="form-item"><input id="uploadfile[]" name="uploadfile[]" class="form-file" size="50" type="file"><span class="jsaction">remove</span></div><div class="form-item"><input id="uploadfile[]" name="uploadfile[]" class="form-file" size="50" type="file"><span class="jsaction">remove</span></div><div class="jsaction">add fileinput</div></fieldset>

Opgeschoond en css erbij:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<style>
.form-item {
  margin-bottom       : 10px;
}

.jsaction {
  color               : blue;
  text-decoration     : underline;
  cursor              : pointer;
}
</style>

<fieldset><legend>Images to upload</legend>
  <div class="form-item">
   <input class="form-file" name="uploadfile[]" id="uploadfile[]" size="50" type="file">
   <span class="jsaction">remove</span>
  </div>
  <div class="form-item">
    <input name="uploadfile[]" class="form-file" size="50" type="file">
    <span class="jsaction">remove</span>
  </div>
  <div class="form-item">
    <input name="uploadfile[]" class="form-file" size="50" type="file">
    <span class="jsaction">remove</span>
  </div>
  <div class="jsaction">add fileinput</div>
</fieldset>

De reden voor dit verschil zit hem ws. in een html interpretatiefoutje van de html: bij de eerste file input staat remove-span op een newline; daarna staat alles op 1 regel. Weet iemand hoe je dit op kunt lossen?

BTW: het default form (zie ook voorbeeld van Crisp) ziet er als volgt uit:
HTML:
1
2
3
4
5
6
7
<fieldset>
  <legend>Images to upload</legend>
  <div class="form-item">
    <input type="file" class="form-file" name="uploadfile[]" id="uploadfile[]" size="50" />
  </div>
  <script type="text/javascript">init_uploadform()</script>
</fieldset>

[ Voor 49% gewijzigd door Reveller op 04-07-2005 12:50 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:59

alienfruit

the alien you never expected

Tjonguh crisp had ik die before/after functies maar van jou toen ik voor de script nazi bezig was om mijn eindopdracht te maken. Zou me veel tijd hebben gescheeld :)

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
* kick * :)

Ik ben er nog steeds niet uit - weet iemand waarom er een kleine witruimte tussen de file input en de "remove" link (zie plaatje hier 2 posts boven) zit?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


  • crisp
  • Registratie: Februari 2000
  • Laatst online: 10:07

crisp

Devver

Pixelated

Reveller schreef op dinsdag 05 juli 2005 @ 11:02:
* kick * :)

Ik ben er nog steeds niet uit - weet iemand waarom er een kleine witruimte tussen de file input en de "remove" link (zie plaatje hier 2 posts boven) zit?
Verander de insertAfter in dit:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
function insertAfter(node, newnode)
{
    if (node.nextSibling)
    {
        node.parentNode.insertBefore(newnode, node.nextSibling);
    }
    else
    {
        node.parentNode.appendChild(newnode);
    }
}

Als je trouwens een spatie tussen de fileinput en 'link' wilt hebben kan je dit doen:
JavaScript:
1
2
3
4
5
6
7
8
9
10
function appendRemoveAction(fileinput)
{
    var text = document.createTextNode(' ');
    insertAfter(fileinput, text);
    var span = document.createElement('span');
    span.className = 'jsaction';
    span.appendChild(document.createTextNode('remove'));
    span.onclick = removeFileinput;
    insertAfter(text, span);
}

Intentionally left blank


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Hey Crisp, dank je! Dit is totaal nieuwe stof voor mij, en ik ga er zeker verder mee spelen :) Ik snap nog steeds niet waarom jouw oplossing werkt, dus als ik er niet uit kom hoor je er misschien nog van!

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."

Pagina: 1