[JS] Onmogelijk maken om ouder naar kind te verplaatsen

Pagina: 1
Acties:

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
In mijn CMS'je maak ik gebruik van een standaard parent-child tabel om de navigatie in op te slaan:
code:
1
2
3
4
5
6
7
8
9
10
+---------+----------+-----------+
| id      | parent   | name      |
+---------+----------+-----------+
| 1       | 0        | Home      |
| 2       | 1        | Groenten  |
| 3       | 1        | Fruit     |
| 4       | 1        | Vlees     |
| 5       | 2        | Winter    |
| 6       | 2        | Zomer     |
+---------+----------+-----------+

Ik ben nu bezig om de gebruiker een optie te geven pagina's kris-kras door de boom te verplaatsen:
Afbeeldingslocatie: http://www.odisys.net/images/verplaats.gif
Zie hier alleen het probleem: als iemand "Zomer" rechtstreeks onder "Home" wil zetten, is dat geen probleem. Ik verander dan de parent van "Zomer" van 2 (Groenten) naar 1 (Home). Maar het gaat fout als iemand "Groenten" onder een kind van "Groenten" wil zetten, zoals onder "Zomer". De nieuwe parent van "Groenten" wordt dan 6 ("Zomer"). De parent van "Winter" en "Zomer" blijft echter 2 ("Groenten"). Weg data integriteit.

Nu kan ik dit op twee manieren oplossen:
• serverside
• clientside

Omdat ik de server niet teveel wil belasten, wil ik het voor de gebruiker onmogelijk maken om een node uit het linker rijtje, te verplaatsen naar een van zijn eigen kinderen. Met andere woorden: als links "Groenten" wordt geselecteerd, moet het niet mogelijk zijn om rechts "Winter" of "Zomer" te selecteren. En als "Zomer" ook weer kinderen zou hebben, mogen die ook niet geselecteerd kunnen worden.

Ik zit hier nu een tijdje over te denken en heb besloten het clientside op te lossen, maar heb niet echt een idee hoe en of het ueberhaupt mogelijk is. De moeilijkheidsgraad van de javascript hangt voor een groot deel af van hoe ik de options van de select box noem:

• name="node[name][id][parent]" (bijvoorbeeld name="node[zomer][6][2]")
• name="name[id][parent]" (bijvoorbeeld name="zomer[6][2]")

Ik heb alleen te weinig ervaring met javascript om dit toch redelijk complexe probleem ineens op te lossen. Ik vraag daarom niet om een kant-en-klare oplossing, maar om jullie ideeen over hoe dit op te lossen: volgens welke conventie moet ik de options benamen om een goede oplossing te kunnen schrijven voor dit probleem? Welke andere problemen voorzie jij? Weet je of iemand eerder een soortgelijk probleem heeft gehad (ik kon zelf via de search niks vinden)?

"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."


  • Sendy
  • Registratie: September 2001
  • Niet online
Het idee is dat je de hele tree terugloopt naar het begin (loops mogen niet, dus dat kan). Al die parents moet je dus in de javascript doorgeven.

Aan een kind kan je nu zien dat de hele rij parent, grandparent, ... niet naar haar verplaats mogen worden.

Dit algoritme omdraaien (bij de parent aangeven naar welke childs hij niet verplaatst mag worden) is iets meer werk (de hele boom doorlopen op zoek naar kinderen), maar wel sneller.

Hou er wel rekening mee dat je deze check ook op de server moet doen. Iemand kan je javascript wijzigen voordat hij de data terugstuurt.

Als je nu een parent aanklikt, verwijder je uit de lijst de children waar hij niet naartoe mag worden verplaats.

En over je Javascript: daar moet je een beetje pragmatisch in zijn. Als je nette functies schrijf die die waarden interpreteren, dan kan je het format altijd later nog wijzigen.

[ Voor 12% gewijzigd door Sendy op 02-12-2004 22:58 ]


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Sendy schreef op donderdag 02 december 2004 @ 22:55:
Hou er wel rekening mee dat je deze check ook op de server moet doen. Iemand kan je javascript wijzigen voordat hij de data terugstuurt.
Dat lijkt me toch wat sterk? Waarom zou iemand dat doen - je verziekt dan zelf je boomstructuur?

"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."


  • Sendy
  • Registratie: September 2001
  • Niet online
Weet ik veel waarom iemand dat wil doen? Misschien doet-ie het zonder te weten? Misschien is het een etter? Misschien wil-ie het bedrijf op kosten jagen? Misschien vind-ie het leuk om jou weer eens langs te zien komen?

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Sendy schreef op donderdag 02 december 2004 @ 23:07:
Weet ik veel waarom iemand dat wil doen? Misschien doet-ie het zonder te weten? Misschien is het een etter? Misschien wil-ie het bedrijf op kosten jagen? Misschien vind-ie het leuk om jou weer eens langs te zien komen?
LOL :+ Oke, punt gemaakt ;)
Het idee is dat je de hele tree terugloopt naar het begin (loops mogen niet, dus dat kan). Al die parents moet je dus in de javascript doorgeven
Kan iemand dit wat meer uiteenzetten? Ik zie nog niet hoe dit moet icm het benoemen van de options...

[ Voor 27% gewijzigd door Reveller op 02-12-2004 23:42 ]

"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."


  • Tom
  • Registratie: Juni 1999
  • Niet online

Tom

Met je vraag kan ik je niet helpen, maar mocht je dat CMS in .NET maken, dan raad ik je aan om eens te kijken naar RAD Treeview:
http://www.telerik.com/Default.aspx?PageId=1828
Het is niet gratis, maar waarschijnlijk goedkoper dan zelf programmeren (tenzij je alles volledig zelf in de hand wilt hebben).

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Da´s ontzettend jammer / ik programmeer in PHP. Het ziet er geweldig uit, maar ik heb er niets aan. Ik zou hun javascripts kunnen doorlopen, maar denk daar weinig van te kunnen leren wegens de overkill aan code. Dan zie ik door de bomen het bos niet meer. Toch bedankt voor je link - het was leuk om eens mee te spelen :)

"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

Dan pak je toch die van mij :) Die kun je gewoon ook in je PHP projecten gebruiken. Hij is gewoon te gebruiken.

http://www.mschopman.demon.nl/treeview_v1.5/treeview.html

[ Voor 12% gewijzigd door Verwijderd op 03-12-2004 09:36 ]


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Gordijnstok, dank je wel! Ik hoop dat ik er iets aan heb - niet dat het er niet goed of geavanceerd uitziet, maar ik wil graag zelf begrijpen wat ik aan het doen ben. Ik zal dus proberen ideeen op te doen door je code te lezen, en het toe te passen binnen mijn eigen systeem. In principe is dit zo gevanceerd als je het maar hebben wilt, maar ik ben bang dat het voor mijn doelgroep - kleine MKB'ers - te veel functies heeft. Toch ontzettend bedankt :), ik hoop er van te leren. Als iemand eenvoudiger code-voorbeeld heeft, hoor ik het graag. Ik zal in deze topic uiteraard mijn vorderingen posten.

"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

Dit is de meest eenvoudige OO-achtige oplossing die ik kon verzinnen. Je moet er wel nog een visualisatie aanhangen.
Java:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function TreeObject( oParent ) {
    this.oParent = oParent;
    this.aChildren = new Array();

    this.MoveTo         = TO_MoveTo;
    this.DescendentOf   = TO_DescendentOf;
    this.RemoveChild    = TO_RemoveChild;
    this.AddChild       = TO_AddChild;
}

function TO_MoveTo( oTO ) {
    if(!oTO.DescendentOf( this )) {
        this.oParent.RemoveChild( this );
        oTO.AddChild( this );
        alert("Move OK.")
    }
    else {
        alert("Can't move node to its descendent.")
    }
}


function TO_DescendentOf( oTO ) {
    if(this.oParent) {
        if(this.oParent == oTO) return true;
        else return this.oParent.DescendentOf(oTO);
    }
    else {
        return false;
    }
}

function TO_RemoveChild( oTO ) {
    for(var i=0; i<this.aChildren.length; i++) {
        if(this.aChildren[i] == oTO) {
            this.aChildren.splice(i, 1);
            oTO.oParent = null;
        }
    }
}

function TO_AddChild( oTO ) {
    this.aChildren[this.aChildren.length] = oTO;
    oTO.oParent = this;
}

var oROOT = new TreeObject();
var oChild = new TreeObject();
var oChild2 = new TreeObject();
var oChild3 = new TreeObject();

oROOT.AddChild(oChild);
oChild.AddChild(oChild2);
oChild2.AddChild(oChild3);

oChild.MoveTo(oChild3); // no
oChild3.MoveTo(oROOT); // yes
oChild.MoveTo(oChild3); // yes

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Dank je Blues voor een erg uitgebreid antwoord :) Alleen - de reden dat ik deze thread begon was omdat ik niet genoeg uit de voeten kan met javascript om dit probleem ineens op te lossen. Als ik nu naar jouw oplossing kijk, weet ik niet goed hoe ik dit in moet passen in mijn situatie. Zou je misschien enige uitleg erbij kunnen geven over de werking of over hoe aan te sluiten op een dubbele option list? Ik zie namelijk niet waar het form wordt uitgelezen en hoe dat wordt gedaan...

[ Voor 22% gewijzigd door Reveller op 03-12-2004 22:12 ]

"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

Ah, I see. Zoals ik al zei: dit is puur een abstracte data-oplossing. Een koppeling met HTML (visualisatie + interactie) zit er nog niet in. Ik zal er alvast even een korte uitleg bij schrijven. Misschien dat ik dit weekend een volledig werkend voorbeeld post.

Allereerst de Object constructor. Het is een heel eenvoudig object met 2 properties: een pointer naar z'n parent en een lijst van directe kinderen. Daarnaast heeft het nog wat methodes voor het verplaatsen, toevoegen en verwijderen van kinderen.
Java:
1
2
3
4
5
6
7
8
9
function TreeObject( oParent ) {
    this.oParent = oParent;
    this.aChildren = new Array();

    this.MoveTo            = TO_MoveTo;
    this.DescendentOf    = TO_DescendentOf;
    this.RemoveChild    = TO_RemoveChild;
    this.AddChild        = TO_AddChild;
}


MoveTo is redelijk eenvoudig. Het belangrijkste is het controleren of het doel geen afstammeling is van deze node (daarover later meer). Als dat niet zo is is moven in feite niets meer dan het verwijderen van deze node bij z'n huidige parent en toevoegen aan de nieuwe.
Java:
1
2
3
4
5
6
7
8
9
10
function TO_MoveTo( oTO ) {
    if(!oTO.DescendentOf( this )) {
        this.oParent.RemoveChild( this );
        oTO.AddChild( this );
        alert("Move OK.")
    }
    else {
        alert("Can't move node to its descendent.")
    }
}


Dit is de functie waar het voor jou om zou moeten draaien; het controleren of een node een afstammeling is van een andere. Typisch geval van recursie. Node A is afstammeling van Node B als
  • B de parent is van A
  • De parent van A een afstammeling is van B
Java:
1
2
3
4
5
6
7
8
9
function TO_DescendentOf( oTO ) {
    if(this.oParent) {
        if(this.oParent == oTO) return true;
        else return this.oParent.DescendentOf(oTO);
    }
    else {
        return false;
    }
}


RemoveChild stelt ook niks voor. Kwestie van de verwijzing in de lijst van kinderen verwijderen en de verwijzing naar dit object als parent resetten.
Java:
1
2
3
4
5
6
7
8
function TO_RemoveChild( oTO ) {
    for(var i=0; i<this.aChildren.length; i++) {
        if(this.aChildren[i] == oTO) {
            this.aChildren.splice(i, 1);
            oTO.oParent = null;
        }
    }
}


AddChild is nog eenvoudiger.
Java:
1
2
3
4
function TO_AddChild( oTO ) {
    this.aChildren[this.aChildren.length] = oTO;
    oTO.oParent = this;
}


Nu we dit hebben kunnen we wat tests gaan doen. Ik creeer 3 losse instanties van een TreeObject en hang ze aan elkaar met AddChild.
Java:
1
2
3
4
5
6
7
8
var oROOT = new TreeObject();
var oChild = new TreeObject();
var oChild2 = new TreeObject();
var oChild3 = new TreeObject();

oROOT.AddChild(oChild);
oChild.AddChild(oChild2);
oChild2.AddChild(oChild3);

Nu heb ik deze structuur:
code:
1
2
3
4
5
6
7
+ oROOT
|
+-+ oChild
  |
  +-+ oChild2
    |
    +-+ oChild3


Java:
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
// Dit kan niet: oChild3 is een afstammeling van oChild:
oChild.MoveTo(oChild3);


// Dit kan wel
oChild3.MoveTo(oROOT); // yes

Nieuwe situatie:
+ oROOT
|
+-+ oChild
| |
| +-+ oChild2
|
+-+ oChild3


// Nu kan dit wel:
oChild.MoveTo(oChild3);

Nieuwe situatie:
+ oROOT
|
+-+ oChild3
  |
  +-+ oChild
    |
    +-+ oChild2

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Misschien begrijp ik jouw oplossing niet voldoende, maar zoals ik het na flink wat nadenken zie, zou het als volgt kunnen:

• kijken welke node links geselecteerd wordt
• tellen hoeveel spaties (&nbsp's) die node heeft
• vanaf daar recursief naar beneden lopen:
• > kinderen van de node hebben 1 (of 2, afhankelijk van hoe je je option list indent) &nbsp's meer
• > elke laag dieper heeft 2 spaties meer...
• telkens als er een kind gevonden is, in het rechter rijtje die option kleuren / disablen

In een ander topic heb ik code gevonden die juist het tegenovergestelde doet: hier wordt vanaf de geselecteerde node naar boven gelopen om het pad naar de geselecteerde node te bepalen. Om te testen selecteer je in het linker rijtje een node (bv. Groenten) en klik op Aanpassen. Het pad wordt nu gealert. Mijn vragen zijn:

• is dit een goede oplossing voor het probleem?

Java:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
function getPath(o)
{
  var i = o.selectedIndex + 1;
  var aRet = new Array();
  var iNumT = null;

  while ( i-- )
  {
    var sHTML = o.options[i].innerHTML;

    // Vervang alle &nbsp; voor een gewone spatie...

    sText = sHTML.replace( /\&nbsp;/g, " " );
    var t = 0;

    // Hier gaan we bepalen hoeveel spaties er voor de
    // tekst staan.

    while (sText.charCodeAt(t) == 32)
      t++;

    // De eerste keer bevat iNumT nog geen waarde
    // Dat is dus de eerste ronde. Dan zetten we iNumT. iNumT
    // geeft aan hoeveel spaties het volgende bovenliggende
    // item moet hebben (2 minter in dit geval, zie HTML).
    // Als die twee waardes gelijk zijn, dan is het 100% zeker
    // dat dat item de parent is.

    if (iNumT == null)
    {
      iNumT = t - 2;
      aRet.unshift(sText.substr(t));
      continue;
    }

    if (t == iNumT)
    {
      // Parent is gevonden, de volgende parent heeft 2 spaties
      // minder dan de huidige, daarom verlagen we iNumT met 2

      iNumT = iNumT - 2;
      aRet.unshift(sText.substr(t));
      if (t == 0)
        break;
    }
  }

  var sRet = '';

  // Nu hebben we dus een array met het complete pad. Van dat
  // pad maken we hier een string.

  for (var i = 0; i < aRet.length; i++)
  {
    sRet += aRet[i];
    if (i != aRet.length - 1)
      sRet += " > ";
  }

  alert(sRet);
}

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
28
29
30
31
32
33
34
<form>
<input type="hidden" name="data[action]" value="move">
  <table width="300" border="0" cellpadding="5" style="font-size: 12px;">
    <tr>
      <td valign="top">Verplaats:</td>
      <td>
        <select size="10" onclick="disable();" name="data[movee]">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
      <td valign="top">Naar:</td>
      <td>
        <select size="10" name="data[to]">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
    </tr>
    <tr>
      <td colspan="4" align="right">
        <input type="button" value="Aanpassen" onclick="getPath(document.forms[0].elements['data[movee]']);">
      </td>
    </tr>
  </table>
</form>

[ Voor 16% gewijzigd door Reveller op 04-12-2004 20:46 ]

"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."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik ben nu tot de volgende oplossing gekomen. Kortweg kijk ik hoeveel spaties er staan voor de geselecteerde optie. Vervogens maak ik alle opties daaronder rood die meer spaties hebben (dus: meer geindent zijn) dan de geselecteerde optie. Dit zijn directe kinderen. Zodra ik in de lijst een optie tegenkom die minder of evenveel spaties heeft dan de geselecteerde optie, stopt de functie; dit zijn geen kinderen meer.

Java:
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>
function check()
{
  var o     = document.forms[0].elements['data[movee]'];
  var p     = document.forms[0].elements['data[to]'];
  var i     = o.selectedIndex;
  var aRet  = new Array();
  var iNumT = null;

  p.style.backgroundColor = 'white';

  var sHTML = o.options[i].innerHTML;
  var sText = sHTML.replace( /\&nbsp;/g, " ");

  var t = 0;
  while (sText.charCodeAt(t) == 32)
    t++;

  for (a = i + 1; a < o.length; a++)
  {
    var cHTML = o.options[a].innerHTML;
    var cText = cHTML.replace( /\&nbsp;/g, " ");

    var c = 0;
    while (cText.charCodeAt(c) == 32)
      c++;

    if (c > t)
      p.options[a].style.backgroundColor = 'red';
    else
      break;
  }
}

</script>

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
28
29
30
31
32
33
34
35
36
37
38
<form>
<input type="hidden" name="data[action]" value="move">
  <table width="300" border="0" cellpadding="5">
    <tr>
      <td valign="top">Verplaats:</td>
      <td>
        <select size="10" name="data[movee]">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
      <td valign="top">Naar:</td>
      <td>
        <select size="10" name="data[to]">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
    </tr>
    <tr>
      <td colspan="4" align="right">
        <input type="button" value="Aanpassen" onclick="check();">
      </td>
    </tr>
  </table>
</form>


Dit schijnt te werken. Ik heb echter nog twee problemen waar ik niet uitkom:

• javascript regel 10 (p.style.backgroundColor = 'white';) zou ervoor moeten zorgen dat als ik een voor een tweede keer een element selecteer en voor de tweede keer check() uitvoer, de rechter select box eerst wit gemaakt wordt. Dit gebeurt echter niet en ik krijg zelfs een foutmelding. En dat is gek, want de code opzich klopt wel...

• kinderen van een bepaalde node maak ik nu rood, om aan te geven dat je er niet op moet klikken. Ik wil die options echter onmogelijk maken om op te klikken (zoals de hoofdfora in de select box bij de GoT search - als je erop klikt wordt ie meteen weer ge-deselecteerd. Dit werkt alleen met de <optgroup> tag en dat werkt niet in dit geval).

[ Voor 142% gewijzigd door Reveller op 04-12-2004 20:55 ]

"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."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Om op mijn tweede vraag van hierboven terug te komen - op w3schools vond ik dat je met behulp van
Java:
1
2
3
4
5
6
7
8
9
10
function makeDisable()
{
  var x=document.getElementById("data[to]")
  x.disabled=true
}
function makeEnable()
{
  var x=document.getElementById("data[to]")
  x.disabled=false
}

een option list in zijn geheel kunt dis/enablen. Vervolgens probeerde ik var x te vervangen door document.getElementById("mySelect").options[2] (bijvoorbeeld) om te kijken of ik ook alleen Witlof kon disablen, maar dit werkt ook niet. Heeft iemand een work-around zodat ik alleen specifieke opties uit de option list kan disablen? Google geeft ook niets zinnigs terug...

"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."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
* kick * ik ben er nog steeds niet uit. Samengevat: weet iemand hoe je alleen bepaalde options uit een option list kunt disablen (zodat als je erop klikt, ze niet geselecteerd worden)?

Met het scriptje hierboven kun je een hele option list dis- of enablen, maar dat is niet wat ik zoek. Afhankelijk van een user input moet ik enkele options kunnen disablen (verdere uitleg 2 posts terug).

"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."


  • Vinzzz243
  • Registratie: Februari 2001
  • Laatst online: 22-01-2025
dit is standaard zonder optgroup niet mogelijk. Je kunt wel natuurlijk zelf een selectboxje bouwen met html/css dan heb je meer vrijheid

[ Voor 55% gewijzigd door Vinzzz243 op 06-12-2004 11:22 ]


Verwijderd

document.getElementById('idvandeoption').disabled = true;

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Verwijderd schreef op maandag 06 december 2004 @ 11:36:
document.getElementById('idvandeoption').disabled = true;
Dat werkt dus niet...had ik al geprobeerd :)
Vinzzz schreef op maandag 06 december 2004 @ 11:21:
dit is standaard zonder optgroup niet mogelijk. Je kunt wel natuurlijk zelf een selectboxje bouwen met html/css dan heb je meer vrijheid
Heeft iemand daar een voorbeeld van? Of is het wellicht een optie om de option list niet in hardcoded html naar de client te sturen maar in een javascript array, en dan dynamisch een option list te bouwen waarbij de niet-te-selecteren options een <optgroup> tag krijgen (ik hoop dat ik duidelijk ben)? Heeft iemand daar nog ideeen over?

"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

Reveller schreef op maandag 06 december 2004 @ 12:08:
[...]

Dat werkt dus niet...had ik al geprobeerd :)

[...]

Heeft iemand daar een voorbeeld van? Of is het wellicht een optie om de option list niet in hardcoded html naar de client te sturen maar in een javascript array, en dan dynamisch een option list te bouwen waarbij de niet-te-selecteren options een <optgroup> tag krijgen (ik hoop dat ik duidelijk ben)? Heeft iemand daar nog ideeen over?
Mijn oplossing werkt inderdaad in niet in MSIE maar wel een MZFF. Ik ga nog even voor je zoeken.

Edit:

Na wat googelen lijkt het erop dat MSIE dergelijke functionaliteit niet ondersteunt. Kortom je zal bij een onclick op het selectelement iets moeten doen met CSS i.c.m. het terugspringen naar de laatst geselecteerde option.

[ Voor 17% gewijzigd door Verwijderd op 06-12-2004 12:28 ]


Verwijderd

Misschien kun je dynamisch een onclick="return false;" toevoegen aan de options om ze te disablen?

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Verwijderd schreef op maandag 06 december 2004 @ 12:39:
Misschien kun je dynamisch een onclick="return false;" toevoegen aan de options om ze te disablen?
Ook dat haalt helemaal niets uit - ik blijf het toch wat gek vinden dat er geen eenvoudige oplossing is om een standaard option list op deze manier eigenschappen mee te geven...

"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."


  • Vinzzz243
  • Registratie: Februari 2001
  • Laatst online: 22-01-2025
zoals al vaker gezegd is, die is er dus wel, alleen niet crossbrowser. DAAR moet je je dus aan 'ergeren' :)

Zoek nou eens naar een opensource html editor ofzo, er zijn er zeker weten die gebruik maken van css, html en javascript om zo'n SELECT na te bootsen...

Verwijderd

Of genereer de selects 'on the fly' met JavaScript op basis van je dataset en user input. Dan kun je die opties die disabled moeten zijn gewoon niet renderen.

  • gsteen
  • Registratie: November 2004
  • Laatst online: 13-01-2020
Mooi is het niet, maar ik heb een extra javascript functie gemaakt die de selectedIndex naar -1 zet. Dit heeft als gevolg dat er niets is geselecteerd.

code:
1
2
3
4
5
6
7
8
<script> 
function checkMe(value)
{
  var p = document.forms[0].elements['data[to]'];
  if(p.options[value].style.backgroundColor == 'red')
    p.selectedIndex=-1;
}
</script>


Ik heb trouwens je check() functie aan het onchange event van het eerste select element gehangen. (zelfde gedaan met mijn extra functie aan het tweede select element).

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
36
37
38
<form>
<input type="hidden" name="data[action]" value="move">
  <table width="300" border="0" cellpadding="5">
    <tr>
      <td valign="top">Verplaats:</td>
      <td>
        <select size="10" name="data[movee]" onChange="check()">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
      <td valign="top">Naar:</td>
      <td>
        <select size="10" name="data[to]" onChange="checkMe(this.selectedIndex)">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
    </tr>
    <tr>
      <td colspan="4" align="right">
        <input type="button" value="Aanpassen">
      </td>
    </tr>
  </table>
</form>


Op deze manier is er in iedergeval geen verkeerd element geselecteerd, maar gebruikers kunnen nog steeds op de knop drukken. Misschien een idee om deze uit te schakelen als een niet valide optie uit de lijst wordt geselecteerd.

Verander:
code:
1
<input type="button" value="Aanpassen">


In:
code:
1
<input type="button" name="aanpassen" value="Aanpassen">


En maak van chechMe() functie dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function checkMe(value)
{
  var p = document.forms[0].elements['data[to]'];
  var o = document.forms[0].elements['aanpassen'];
  if(p.options[value].style.backgroundColor == 'red')
  {
    p.selectedIndex=-1;
    o.disabled=true;
  }
  else
  {
    o.disabled=false;
  }
}

"In theory, there is no difference between theory and practice. But, in practice, there is."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Wow! Thanks gsteen, dat werkt perfect. Voor iedereen die zoiets had van "waarom verwijder je die opties niet gewoon uit de list?". Dat is inderdaad ook een mogelijkheid, maar ik denk dat het voor gebruikers wat verwarrend is als de linker optionlist telkens in lengte verspringt, omdat er bij elke select opties bij verschijnen / verdwijnen. Uiteraard wordt er nog eea aan het estetisch karakter :) gedaan - zo wordt de achtergrond van de kinderen niet rood gemaakt, maar bv. de tekst lichtgrijs - mensen herkennen van de meeste office applicaties ook dat lichtgrijze elementen niet-klikbaar zijn. Ik wil daar wat tegenaan blijven hangen. Heb jij goede argumenten voor een andere oplossing, dan hoor ik die uiteraard graag!

Rest mij nog een vraag:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function check() 
{ 
  var o     = document.forms[0].elements['data[movee]']; 
  var p     = document.forms[0].elements['data[to]']; 
  var i     = o.selectedIndex; 
  var aRet  = new Array(); 
  var iNumT = null; 

  p.style.backgroundColor = 'white'; 

  var sHTML = o.options[i].innerHTML; 
  var sText = sHTML.replace( /\&nbsp;/g, " "); 

  var t = 0; 
  while (sText.charCodeAt(t) == 32) 
    t++; 
[...]

Volgens mij zou regel 9 er bij elke nieuwe check voor moeten zorgen dat de hele rechter optionlist een witte achtergrond krijgt. Dit gebeurt alleen niet: options die eenmaal een rode achtergrond hebben, blijven een rode achtergrond houden...ik heb geen idee waarom, omdat de code opzich wel klopt... :?

"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."


  • gsteen
  • Registratie: November 2004
  • Laatst online: 13-01-2020
Verander regel 9 door dit for lusje:
code:
1
2
for(var a = 0; a < p.options.length; a++)
    p.options[a].style.backgroundColor = 'white';

"In theory, there is no difference between theory and practice. But, in practice, there is."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Dank je, dat werkt perfect. Ik kom net thuis en test je oplossing op FireFox - het "disablen" van de options blijkt daar niet te werken, evenals het disablen van de Aanpassen button. De rest werkt wel...kan iemand uitleggen waar dat aan ligt?

[ Voor 49% gewijzigd door Reveller op 06-12-2004 22:51 ]

"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."


  • Sendy
  • Registratie: September 2001
  • Niet online
Bedankt eerst eens wat er in gsteens voorstel gebeurd, en waarom dat werkt in IE. Zoek dan het "funtamentele" verschil (hint p.options). Pak dan een DOM handleiding erbij, en dan vind je het probleem vanzelf, en gemakkelijk.

edit:

Oftewel, we zijn geen helpdesk

edit:

Hmm, ik begrijp het niet meer zo goed, met al die edits. Ok, ik heb dat wat jij wilt nog nooit ergens gezien (jij wel?), en ik heb net even het DOM model voor de <OPTION> gelezen; en daar lijkt het niet te kunnen. (Het hiden/disablen van een option.)

Je kan wel wat trukjes (zoals inderdaad die index op -1, of tel er eentje bij op (ook leuk), of disable de hele box terwijl je over die optie hoverd (ik weet niet of dit werkt). Lijkt me lastig om de "beste" oplossing te vinden.

Misschien kan je ook het "selected" attribuut afzetten, net nadat het gezet is. (maar dit had ik, dacht ik, hier al ergens gelezen?

[ Voor 77% gewijzigd door Sendy op 06-12-2004 23:27 ]


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Sendy - met je edit heb je gelijk, maar ik ben bang dat we het over verschillende stukken code hebben: het weer wit maken van de option list werkt goed, alleen het disablen van de options niet. Net alsof je in FireFox de selectedIndex niet op -1 kunt zetten...daar zit hem het probleem, maar ik ga er achteraan.

"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."


  • gsteen
  • Registratie: November 2004
  • Laatst online: 13-01-2020
Reveller, uiteraard heb ik mijn oplossing in zowel IE (6) als FireFox (1.0) geprobeerd. In beide gevallen werkt de selectedIndex op -1 zetten gewoon.
Evenals het disablen/enablen van de button.

Dus waarom het bij jou niet werkt? :? Andere versies? Instellingen misschien?

"In theory, there is no difference between theory and practice. But, in practice, there is."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
gsteen schreef op dinsdag 07 december 2004 @ 09:45:
Dus waarom het bij jou niet werkt? :? Andere versies? Instellingen misschien?
Dat lijkt me sterk - ik kan me niet herinneren dat ik iets aan de instellingen veranderd heb en draai gewoon FF 1.0. Zou jij onderstaande code eens bij jou willen draaien? Of zou iemand anders deze code eens willen draaien in zijn FireFox? Het probleem bij mij is dat de nodes wel gekleurd worden, maar nog steeds gewoon te selecteren zijn. Het is een hele lap, maar dat komt vooral door het commentaar:

Java:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<script>
function check()
{
  var o     = document.forms[0].elements['data[movee]'];
  var p     = document.forms[0].elements['data[to]'];
  var i     = o.selectedIndex;
  var aRet  = new Array();
  var iNumT = null;

  /* "Reset" de data[to] list - kleur de font van alle options zwart */
  for(var a = 0; a < p.options.length; a++)
    p.options[a].style.color = '#000000';

  /* bepaal het aantal spaties voor de geselecteerde node in
   * de data[movee] list. Vul t met dit aantal. */
  var sHTML = o.options[i].innerHTML;
  var sText = sHTML.replace( /\&nbsp;/g, " ");

  var t = 0;

  while (sText.charCodeAt(t) == 32)
    t++;

  /* Kleur de geselecteerde node in de data[to] list grijs. Een node
   * kan immers niet naar zichzelf verplaatst worden. */
  p.options[i].style.color = '#cccccc';

  /* Loop door de lijst omhoog. De eerse node die we tegenkomen met
   * 2 spaties minder dan de geselecteerde node, is de parent. Kleur
   * deze node dan grijs - het is immers onzin een node naar zijn
   * huidige parent te "verplaatsen" */

  var found = false;

  for (a = i - 1; a >= 0; a--)
  {
    var jHTML = o.options[a].innerHTML;
    var jText = jHTML.replace( /\&nbsp;/g, " ");

    var j = 0;

    while (jText.charCodeAt(j) == 32)
      j++;

    if (j == (t - 2) && found == false)
    {
      p.options[a].style.color = '#cccccc';
      found = true;
    }
  }

  /* Kleur alle kinderen van de geselecteerde node grijs */
  for (a = i + 1; a < o.length; a++)
  {
    var cHTML = o.options[a].innerHTML;
    var cText = cHTML.replace( /\&nbsp;/g, " ");
    var c     = 0;

    while (cText.charCodeAt(c) == 32)
      c++;

    if (c > t)
      p.options[a].style.color = '#cccccc';
    else
      break;
  }
}

function checkMe(value)
{
  var p = document.forms[0].elements['data[to]'];
  var o = document.forms[0].elements['aanpassen'];

  if (p.options[value].style.color == '#cccccc')
  {
    p.selectedIndex=-1;
    o.disabled=true;
  }
  else
  {
    o.disabled=false;
  }
}

function submitForm()
{
  var m = document.forms[0].elements['data[movee]'].selectedIndex;
  var t = document.forms[0].elements['data[to]'].selectedIndex;

  if (t > -1 && m > -1)
    alert (m+' '+t);
  else
    return;
}
</script>


Merk overigens op dat ik check() en checkMe bij beide option lists aanroep. Hiermee maak ik het onmogelijk dat iemand EERST rechts klikt waar een node naartoe moet, en vervolgens LINKS een "foute" node aanklikt.
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
28
29
30
31
32
33
34
35
36
37
38
<form>
<input type="hidden" name="data[action]" value="move">
  <table width="300" border="0" cellpadding="5">
    <tr>
      <td valign="top">Verplaats:</td>
      <td>
        <select size="10" name="data[movee]" onChange="check(); checkMe(this.selectedIndex)">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
      <td valign="top">Naar:</td>
      <td>
        <select size="10" name="data[to]" onChange="check(); checkMe(this.selectedIndex)">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
    </tr>
    <tr>
      <td colspan="4" align="right">
        <input type="button" value="Aanpassen" name="aanpassen" onClick="submitForm();">
      </td>
    </tr>
  </table>
</form>

[ Voor 32% gewijzigd door Reveller op 07-12-2004 18:36 ]

"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."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik herinnerde mij dat in het vorige GoT forum, bij de search, het ook zo was dat je bepaalde options uit de lijst niet kon selecteren, dus ik ben gaan graven en vond het volgende op vpro.react.nl:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<SCRIPT>
function selectsearchforum(x)
{
  var i = x.options.length;
  while (i--)
  {
    if (x.options[i].id == 'switchCat') x.options[i].selected = false;
  }
}
</SCRIPT>

<SELECT onchange=selectsearchforum(this) size=15 multiple>
  <OPTION id=switchCat value=3>Algemeen</OPTION>
  <OPTION value=9>&nbsp;&nbsp;&nbsp;Suggesties</OPTION>
  <OPTION value=20>&nbsp;&nbsp;&nbsp;Globaliseringslezingen</OPTION>
  <OPTION id=switchCat value=1>Reacties op uitzendingen</OPTION>
  <OPTION value=51>&nbsp;&nbsp;&nbsp;De Berg</OPTION>
</SELECT>

Als ik nu op "Algemeen" of "Reacties op uitzendingen" klik, verdwijnt de select meteen. Dit werkt zowel in IE als FF. Mijn eerste vraag is:
• als ik uit de SELECT tag "multiple" verwijder, werkt het scriptje niet meer. Weet iemand waarom?

Aan het idee van dit scriptje heb ik mijn eigen script aangepast:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function checkMe(value)
{
  var p = document.forms[0].elements['data[to]'];
  var o = document.forms[0].elements['aanpassen'];

  if (p.options[value].style.color == '#cccccc')
  {
    p.options[value].selected=false;
    o.disabled=true;
  }
  else
  {
    o.disabled=false;
  }
}


En weer geldt: dit werkt perfect in IE, maar in FF kan ik alle grijze (#cccccc) options nog steeds selecteren, terwijl het GoT script wel in FireFox werkt. Mijn tweede vraag is: wat doe ik verkeerd? Ook de option DOM (nu goed doorgespit) geeft geen oplossing; daar wordt helemaal niet over dit probleem gesproken.

offtopic:
Ligt het aan mijn internetverbinding of is GoT op het moment ontzettend traag?

[ Voor 19% gewijzigd door Reveller op 07-12-2004 20:26 ]

"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."


  • Sendy
  • Registratie: September 2001
  • Niet online
En als je dat stukje VPRO code op je eigen server zet, werkt het dan nog steeds? Als dat zo is, lijkt jouw probleem mij gewoon een beetje debuggen?

  • gsteen
  • Registratie: November 2004
  • Laatst online: 13-01-2020
Ik denk je probleem te hebben gevonden.

Je zet de achtergrond kleur van elementen die niet geselecteerd kunnen worden naar '#cccccc'.
code:
1
p.options[a].style.color = '#cccccc';


Echter als je later bij controles de kleur weer opvraagt (even met een alert() gedaan) is het resultaat niet '#cccccc'. Dus onderstaande controle werkt dan niet (In FireFox dan IE heeft hier geen problemen mee).
code:
1
if (p.options[value].style.color == '#cccccc')

Mijn oplossing hiervoor:
Overal waar je de kleur van een element naar grijs zet voeg je een extra (eigen) attribuut toe aan het element.
code:
1
p.options[i].selectable=false;


Vervolgens controleer je op dit attribuut in de checkMe() functie.
code:
1
if (p.options[value].selectable == false)

Verder...
Ik zie dat je bij beide select lists de checkMe functie aanroept. Misschien is het dan beter deze functie zonder parameters te definieren en binnen de functie de selectedIndex op te vragen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function checkMe() 
{ 
  var p = document.forms[0].elements['data[to]']; 
  var o = document.forms[0].elements['aanpassen']; 
  var i = p.selectedIndex;

  if (p.options[i].selectable == false) 
  { 
    p.selectedIndex=-1; 
    o.disabled=true; 
  } 
  else 
  { 
    o.disabled=false; 
  } 
}


edit:
De manier van deselecteren de jij gevonden had ook even getest. Deze werkt ook gewoon dus... lag echt aan de controle binnen de checkMe() fucntie.

[ Voor 9% gewijzigd door gsteen op 08-12-2004 09:39 ]

"In theory, there is no difference between theory and practice. But, in practice, there is."


  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Bedankt Gert, dat is inderdaad de oplossing. Wel raar eigenlijk, dat FF een hexadecimale kleur op deze manier niet accepteert. Ik heb nog gekeken wat er gebeurt als ik dubbele quootjes gebruik, maar dat geeft hetzelfde resultaat. Nouja, ik gebruik nu style.color='silver' en dat werkt ook :)

Overigens:
• Jouw workaround werkt bij mij niet. IE geeft een "Error: object doesn't support this property or method"
• hoewel p.selectedIndex = -1 in beide browsers goed werkt, geeft FF op de achtergrond toch een "Error: uncaught exception: [Exception... "Index or size is negative or greater than the allowed amount" code: "1" nsresult: "0x80530001 (NS_ERROR_DOM_INDEX_SIZE_ERR)" location: "file:///C:/Test/Reveller/testform.htm Line: 65"]". Logisch natuurlijk, want dat is ook wat we doen :)
• de andere methode, p.options[i].selectable=false heb ik nu verwerkt in checkMe(). Dit werkt wel in FF, maar nu weer niet in IE (ik kan gewoon de silver opties selecteren, hoewel de button disabled blijft). Ziet iemand waar de fout nu zit?

Overigens, voor de mensen die hier nog eens wat aan hebben: zoals gezegd werkt dit, behalve het laatste punt hierboven, dat blijft een bugje. Dus als iemand raad weet...

Java:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<script>
function check()
{
  var o     = document.forms[0].elements['data[movee]'];
  var p     = document.forms[0].elements['data[to]'];
  var i     = o.selectedIndex;
  var aRet  = new Array();
  var iNumT = null;

  for(var a = 0; a < p.options.length; a++)
    p.options[a].style.color = '#000000';

  var sHTML = o.options[i].innerHTML;
  var sText = sHTML.replace( /\&nbsp;/g, " ");

  var t = 0;
  while (sText.charCodeAt(t) == 32)
    t++;

  p.options[i].style.color = 'silver';

  var found = false;

  for (a = i - 1; a >= 0; a--)
  {
    var jHTML = o.options[a].innerHTML;
    var jText = jHTML.replace( /\&nbsp;/g, " ");

    var j = 0;

    while (jText.charCodeAt(j) == 32)
      j++;

    if (j == (t - 2) && found == false)
    {
      p.options[a].style.color = 'silver';
      found = true;
    }
  }

  for (a = i + 1; a < o.length; a++)
  {
    var cHTML = o.options[a].innerHTML;
    var cText = cHTML.replace( /\&nbsp;/g, " ");
    var c     = 0;

    while (cText.charCodeAt(c) == 32)
      c++;

    if (c > t)
      p.options[a].style.color = 'silver';
    else
      break;
  }
}

function checkMe()
{
  var p = document.forms[0].elements['data[to]'];
  var o = document.forms[0].elements['aanpassen'];
  var i = p.selectedIndex;

  if (p.options[i].style.color == 'silver')
  {
    p.options[i].selected = false;
    o.disabled=true;
  }
  else
  {
    o.disabled=false;
  }
}

function submitForm()
{
  var m = document.forms[0].elements['data[movee]'].selectedIndex;
  var t = document.forms[0].elements['data[to]'].selectedIndex;

  if (t > -1 && m > -1)
    alert ('movee: '+m+' to parent: '+t);
  else
    return;
}
</script>

en de
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
28
29
30
31
32
33
34
35
36
37
38
<form>
<input type="hidden" name="data[action]" value="move">
  <table width="300" border="0" cellpadding="5">
    <tr>
      <td valign="top">Verplaats:</td>
      <td>
        <select size="10" name="data[movee]" onChange="check(); checkMe()">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
      <td valign="top">Naar:</td>
      <td>
        <select size="10" name="data[to]" onChange="check(); checkMe()">
          <option value="1">Home</option>
          <option value="2">&nbsp;&nbsp;Groenten</option>
          <option value="5">&nbsp;&nbsp;&nbsp;&nbsp;Winter</option>
          <option value="8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Witlof</option>
          <option value="6">&nbsp;&nbsp;&nbsp;&nbsp;Zomer</option>
          <option value="3">&nbsp;&nbsp;Fruit</option>
          <option value="7">&nbsp;&nbsp;&nbsp;&nbsp;Rood</option>
          <option value="4">&nbsp;&nbsp;Vlees</option>
        </select>
      </td>
    </tr>
    <tr>
      <td colspan="4" align="right">
        <input type="button" value="Aanpassen" name="aanpassen" onClick="submitForm();" disabled>
      </td>
    </tr>
  </table>
</form>

[ Voor 17% gewijzigd door Reveller op 08-12-2004 20:11 ]

"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."


  • gsteen
  • Registratie: November 2004
  • Laatst online: 13-01-2020
Jouw workaround werkt bij mij niet. IE geeft een "Error: object doesn't support this property or method"
Hmmm je hebt gelijk. Was waarschijnlijk vergeten te testen in IE, werkt bij mij ook niet. Ziet ernaar uit dat FF deze keer meer toestaat dan IE.
de andere methode, p.options[i].selectable=false heb ik nu verwerkt in checkMe(). Dit werkt wel in FF, maar nu weer niet in IE (ik kan gewoon de silver opties selecteren, hoewel de button disabled blijft). Ziet iemand waar de fout nu zit?
IE heeft problemen met deze regel:
code:
1
if (p.options[i].style.color == 'silver')
Dit komt denk ik doordat de selectedIndex op -1 staat. Aangezien het option element met index -1 niet bestaat en je hier wel naar kijkt.

Om dit op te lossen heb ik een extra controle aan de checkMe functie toegevoegd.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function checkMe() 
{ 
  var p = document.forms[0].elements['data[to]']; 
  var o = document.forms[0].elements['aanpassen']; 
  var i = p.selectedIndex; 

  if( !(i < 0))
  {
    if (p.options[i].style.color == 'silver') 
    { 
      p.options[i].selected = false; 
      o.disabled=true; 
    } 
    else 
    { 
      o.disabled=false; 
    } 
  }
}


Heb deze code bekeken in IE en FF. Echter IE schijnt problemen te hebben met p.options[i].selected = false, resulteert in disabled butten, maar selected in lijst. Dus misschien is p.selectedIndex = -1 dan toch een betere optie.

"In theory, there is no difference between theory and practice. But, in practice, there is."

Pagina: 1