Javascript och formulär

Events happening in the community are now at Drupal community events on www.drupal.org.
AdamLinden's picture

För er som läste min tidigare tråd (http://groups.drupal.org/node/16259) är det en variant på det problemet.

Jag vill implementera min "vanliga" PHP/JavaScript-kod på en Drupal-site men det går väl sisådär. Jag fick acceptera att formulärkoden var tvungen att skrivas om och söker nu bekräftning (allra helst dementering iofs;) på att även JS-koden måste "Drupalizeras".

Då det verkar som om det är fallet har jag även börjat viss användning av jQuery. Eftersom jag är relativt ny både inom Drupal och Javascriptande går det hela ganska långsamt framåt. Förhoppningsvis ska denna tråd ge mig lite skjuts.

Det hela är egentligen rätt simpelt. Formuläret består utav (för er relevanta) 3 checkboxar, ett textfält och en submitknapp. Det jag vill uppnå är att

1, Textfältet ska vara disablat när sidan öppnas
2, Checkbox ett ska vara ikryssad när sidan öppnas
3, Ifall checkbox 2 blir ikryssad skall checkbox 1 disablas och textfältet enablas
4, Ifall checkbox 3 blir ikryssad ska checkbox 1 disablas och en text skrivas ut

Såhär såg php-koden ut på min vanliga sida

....

Normal <input type="checkbox" id="Normal" name="Class1" value="Normal" checked onclick="change_disabled2(this, 'PP', 'Restricted');"/>
Password Protected <input type="checkbox" name="Class2" value="PP" id="PP" onclick="change_disabled(this, 'Normal', 'password');"/>
Restricted <input type="checkbox" id="Restricted" name="Class3" value="Restricted" onclick="change_disabled3(this, 'Normal', 'texty');"/>

</td><td id="texty"></td>
</tr>


<tr><td>Password:</td><td><input type='text' name='Password' id='password' disabled='disabled'></td></tr>


<?


echo "<tr><td><input type='submit' value='Send'></td></tr>";

.....

Och här kommer javascriptet

function change_disabled(me, id, id2){

document.getElementById(id).disabled = (me.checked == true ? true : false);
document.getElementById(id2).disabled = (me.checked == false ? true : false);



}








function change_disabled2(me, id, id2, id3, id4, id5, id6, p){

var url=id;
url=url+"["+p+"]"; 



document.getElementById(id).disabled = (me.checked == true ? true : false);
document.getElementById(id2).disabled = (me.checked == true ? true : false);
document.getElementById(id3).disabled = (me.checked == true ? true : false);
document.getElementById(id4).disabled = (me.checked == true ? true : false);
document.getElementById(id5).disabled = (me.checked == true ? true : false);
document.getElementById(id6).disabled = (me.checked == true ? true : false);
}
function change_disabled5(me, id, id2, id3, id4, id5, id6, p){

document.getElementById(id).disabled = (me.checked == false ? true : false);
document.getElementById(id2).disabled = (me.checked == false ? true : false);
document.getElementById(id3).disabled = (me.checked == false ? true : false);
document.getElementById(id4).disabled = (me.checked == false ? true : false);
document.getElementById(id5).disabled = (me.checked == false ? true : false);
document.getElementById(id6).disabled = (me.checked == false ? true : false);
}


function change_disabled3(me, id, divName)
{







if (document.getElementById(divName).innerHTML=="If restricted is blablabla")
{
document.getElementById(divName).innerHTML="";
}
else
{
document.getElementById(divName).innerHTML="If restricted is blablabla";
}


document.getElementById(id).disabled = (me.checked == true ? true : false);




}  

function change_disabled4(me)
{
document.getElementsByName("rYear").disabled = (me.checked == true ? true : false);

var x=document.getElementsByName("rYear");
  alert(x.length);



}   

Problem 1 och 2 är nog ganska lätta att lösa genom form API helt enkelt, inte provat ännu. Men hur jag ska göra på trean och fyran är ett större problem. Det enda jag lyckats uppnå är

$(document).ready(function() {
   $("goo").click(function() {
     alert("Hello world!");
   });
});

$form['node_options_'. $node->type] = array(
  '#type' => 'checkboxes',
  '#title' => t('Default options'),
  '#default_value' => variable_get('node_options_'. $node->type, array('Normal')),
  '#options' => array(
    'Normal' => t('Normal'),
    'PP' => t('Password Protected'),
    'Restricted' => t('Restricted'),
  ),
'#prefix' => '<div id="goo">',
  '#suffix' => '</div>',
);

Så jag antar att det jag först behöver lista ut är hur jag tilldelar varje enskilt checkbox (samt textfältet) ett ID. Men vilken kod som sedan krävs för att enabla/disabla har jag verkligen ingen aning om.

Comments

Problem ett och två kan som

fabsor's picture

Problem ett och två kan som du säger lösas med hjälp av FormAPI:t.

  • För att ett fält ska vara disabled så behöver du bara lägga till #disabled => TRUE till ditt element.
  • För att en checkbox ska vara ikryssad från start måste du sätta dess #default_value till nåt >1 (True alltså=)

Vad gäller dina övriga problem så borde det vara enkelt att lösa med JQuery. Du behöver dessutom inte sätta några unika ID:n på dina fält, de får ett automatiskt ("edit-namnetpådittfält")

Du kan alltså skriva nåt i stil med:

$("edit-checkbox2").change(Function{
  $("edit-textfield1").disabled = ($("edit-checkbox2").checked != TRUE);
});

för att aktivera ett fält när en checkbox trycks på.

Och nåt sånt här:

$("edit-checkbox3").change(Function{
  $("edit-checkbox2").disabled = $("edit-checkbox3").checked;
  if($("edit-checkbox3").checked )
    $('yourtext').display = 'compact'
  else
   $('yourtext').display ='none'
});

För att lösa ditt sista problem. Här utgår jag från att du lagt till din text nånstans så att du kan köra den genom t() först. Du måste också sätta display: none; på den i din css-fil.

Jag har inte testat koden, så jag kan ha tänkt fel. Det är bara för att illustrera hur det hela fungerar ;)

//Fabian Sörqvist

Ettan och tvåan löstes

AdamLinden's picture

Ettan och tvåan löstes utan några problem, tack så mycket.

Trean och fyran ger mig dock större problem, får ingen respons även när jag har hållit på och pillat på ditt kodförslag ett tag. Eftersom den ger livstecken ur sig när jag använder "goo" som namn så gissar jag att det är där skon klämmer. Du ser listan av checkboxar i mitt ursprungliga inlägg, namnetpåmittfält har jag alltså gissat ska vara "node_options_Normal", eller är jag way off base?

Firebug

fabsor's picture

Jag kan rekommendera dig att installera firebug (ett tillägg till firefox), då kan du lätt analysera din html-källkod, och se vilka id:n olika element har, och mycket mer. Själv klarar jag mig inte en dag utan det ;) Använder du t.ex. safari så finns det en liknande lösning och jag antar att det finns något tillägg förr IE med, dock så kraschade min IE helt när jag försökte installera nåt liknande sist.

Drupal lägger till 'edit-' innan namnet på sina ID:n. det blir alltså till exempel "edit-node_options_Normal", jag ber om ursäkt om detta inte framgick av mitt tidigare inlägg. Som sagt, använd firebug eller likvärdigt (eller kolla källkoden på vanligt vis) så slipper du undra ;)

//Fabian Sörqvist

Firebug

AdamLinden's picture

Firebug verkar mycket användbart, tack så mycket.
Nu är jag nästan framme vid mållinjen känner jag, koden ser nu ut såhär:

$(document).ready(function() {

$("#edit-node-options--PP").change(
function()
{

var checked_status = this.checked;
                if (checked_status == true) {
                   
            $("#edit-node-options--Normal").attr("disabled", "disabled");
            $("#edit-password").removeAttr("disabled");
                }
                else {
                   $("#edit-node-options--Normal").removeAttr("disabled");
            $("#edit-password").attr("disabled", "disabled");
                }

}
);


$("#edit-node-options--Restricted").change(
function()
{

var checked_status = this.checked;
                if (checked_status == true) {
                   
            $("p").show("slow");
           $("#edit-node-options--Normal").attr("disabled", "disabled");
                }
                else {
                   $("p").hide();
     

           $("#edit-node-options--Normal").removeAttr("disabled");
                }

}
);


});

Och problemen jag skrev om i första inlägget är nästan löst. Det enda problemet jag har är att användaren skulle kunna lyckas kombinera "Normal" med någon av de andra två valen..

I början är "Normal" ikryssad. Sedan väljer användaren kanske "Restricted" vilket gör "Normal" inaktiv. Sedan väljer kanske användaren att också kryssa i "PP", fortfarande inga problem. Men ifall användaren sedan klickar bort Restricted eller PP kommer Normal återigen att bli aktiv, vilket då inte ska vara möjligt.

Det jag gissar att jag måste göra är att här:

$("#edit-node-options--PP").change(
function()
{

var checked_status = this.checked;

Även kolla ifall Restricted är checkad eller ej, dvs ersätta "this" med något. Jag kan tyvärr inte syntaxen för det. Jag gissar att jag ska kolla attributet för "#edit-node-options--Restricted", eller behöver jag skicka med det värdet i funktionen på något sätt?

Du vill alltså att Normal

fabsor's picture

Du vill alltså att Normal bara ska vara aktiv om varken Restricted eller PP är checkad?

Då är det som du säger bara att kolla om någon av dem är checkade, med nåt i den här stilen:

if($("#edit-node-options--PP").attr("checked") == undefined && $(#edit-node-options--Restricted).attr("checked") == undefined)
  $("#edit-node-options--Normal").removeAttr("disabled");

Checken måste ligga i båda funktionerna, jag antar att det är snyggast att göra en egen funktion för den, men det gör du väl som du vill.

Jag är inte säker på om man faktiskt behöver använda attr() på allt egentligen, den är mest till för att kunna sätta ett värde på flera element hade jag för mig, men jag kör med attr() för säkerhets skull. Det kan vara så att checked alltid är antingen true eller false, och då ska du hantera dem som booleans, men jag är inte säker på att attr() använder dem på det viset. Testa det om det där inte funkar.

//Fabian Sörqvist

$("#edit-node-options--PP").c

AdamLinden's picture

$("#edit-node-options--PP").change(
function()
{

var checked_status = this.checked;
var checked_status2 =  $("#edit-node-options--Restricted").attr("checked");
                if (checked_status == true) {
                  
            $("#edit-node-options--Normal").attr("disabled", "disabled");
        $("#edit-node-options--Normal").attr("checked", false);
            $("#edit-password").removeAttr("disabled");
                }
               
else
{


if (checked_status2 == true) {


}
else
{
$("#edit-node-options--Normal").removeAttr("disabled");

}



                  
            $("#edit-password").attr("disabled", "disabled");
                }


















}
);


$("#edit-node-options--Restricted").change(
function()
{

var checked_status = this.checked;
var checked_status2 =  $("#edit-node-options--PP").attr("checked");
                if (checked_status == true) {
                  
            $("p").show("slow");
           $("#edit-node-options--Normal").attr("disabled", "disabled");
        $("#edit-node-options--Normal").attr("checked", false);
                }
                else {
                   $("p").hide();
    

        

if (checked_status2 == true) {


}
else
{
$("#edit-node-options--Normal").removeAttr("disabled");

}
                }

}
);

Nu fungerar det finfint (för de troubleshooters som stöter på tråden, jag lade till så att "Normal" uncheckas när den disablas).

Då kommer vi till nästa, och förhoppningsvis sista, problemet med Jquery/FormAPI för min del. Hoppas du kan vara vägledande här också Fabian, kan inte ens börja förklara hur mycket det underlättar.


Formuläret består av två delar, i första delen skriver användaren in ett värde under "Antal Turneringar". I den andra delen avgör det värdet hur ofta en for-sats ska upprepa sig. Ifall användaren skriver in värdet "3" kommer det att dyka upp 3 stycken rader på nästa sida.

Varje rad består av två stycken radioknappar samt ett antal selectrutor. Det jag försöker att uppnå nu är att ifall den ena radioknappen är vald så disablas alla selectknapparna. Hade det varit ett bestämt antal rader så skulle det inte ha varit några problem, bara att upprepa det här tillräckligt många gånger:

$("#edit-Registration-1-1").change(
function()
{

var checked_status = this.checked;
                if (checked_status == true) {
                   
          
          

          $("#edit-rYear-1").removeAttr("disabled");
         $("#edit-rMonth-1").removeAttr("disabled");
            $("#edit-rDay-1").removeAttr("disabled");
          $("#edit-rHour-1").removeAttr("disabled");
         $("#edit-rMinute-1").removeAttr("disabled");
           $("#edit-rTimeZone-1").removeAttr("disabled");
                }
               

}
);



$("#edit-Registration-1-0").change(
function()
{

var checked_status = this.checked;
                if (checked_status == true) {
                   
          
          

          $("#edit-rYear-1").attr("disabled", "disabled");
         $("#edit-rMonth-1").attr("disabled", "disabled");
            $("#edit-rDay-1").attr("disabled", "disabled");
          $("#edit-rHour-1").attr("disabled", "disabled");
         $("#edit-rMinute-1").attr("disabled", "disabled");
           $("#edit-rTimeZone-1").attr("disabled", "disabled");
                }
               

}
);

Problemet är då att jag inte vet hur många rader användaren kommer att välja. Jag skulle kunna upprepa koden ett rimligt antal gånger, men jag gissar att det finns ett snyggare sätt att lösa det hela på.

Jag antar att det jag behöver göra är att byta ut alla ettor i koden ovanför mot en variabel och sedan trycka in hela schabraket i en for-sats. Men hur uttrycker man variablerna? Jag småpillade lite med

$("#edit-Registration-[]-1").change(

och
$("#edit-Registration-" . $n . "-1").change(

... men ingen framgång tyvärr.

Här kommer jquery till undsättning

fabsor's picture

Jquery har en finfin funktion, nämligen att om du har satt en klass på flera element och säger åt den att ändra något för den klassen, så kommer det att ändra på alla element som har den klassen.

du kan alltså t.ex. skriva

$(".dinklass").attr(disabled,"disabled")

och alla element som du har satt den klassen på kommer att ändras. Observera punkten innan dinklass, den är där för att visa att det är en klass som vi ändrar på (precis som i css)

Det du behöver göra är att sätta en klass på alla element du vill ändra och sedan göra något i stil med kodförslaget ovan. lycka till ;)

//Fabian Sörqvist

Jag brukar använda Visual

zoo33's picture

Jag brukar använda Visual Jquery som referens när jag gör nåt med Jquery. Mycket bra när man väl har lärt sig hitta i den. Bara ett tips!

/ Hannes Lilljequist – SthlmConnection

Mjae, här tror jag du har

AdamLinden's picture

Mjae, här tror jag du har missförstått mig.
Koden i formuläret ser ut såhär:

$form['Registration_' . $i] = array(
  '#type' => 'radios',
  '#title' => t('Registration'),
  '#default_value' => variable_get('comment_preview', 0),
  '#options' => array(t('ASAP'), t('Specify')),
'#prefix' => '<tr><td>',
  '#suffix' => '</td>',
);




$form['rYear_' . $i] = array(
        '#type' => 'select',
        '#title' => t('Year'),
        '#options' => $Year,
'#prefix' => '<td>',
  '#suffix' => '</td>',
'#disabled' => 'TRUE',
    );

$form['rMonth_' . $i] = array(
        '#type' => 'select',
        '#title' => t('Month'),
        '#options' => $Month,
'#prefix' => '<td>',
  '#suffix' => '</td>',
'#disabled' => 'TRUE',
    );

$form['rDay_' . $i] = array(
        '#type' => 'select',
        '#title' => t('Day'),
        '#options' => $Day,
'#prefix' => '<td>',
  '#suffix' => '</td>',
'#disabled' => 'TRUE',
    );

$form['rHour_' . $i] = array(
        '#type' => 'select',
        '#title' => t('Hour'),
        '#options' => $Hour,
'#prefix' => '<td>',
  '#suffix' => '</td>',
'#disabled' => 'TRUE',
    );

$form['rMinute_' . $i] = array(
        '#type' => 'select',
        '#title' => t('Minute'),
        '#options' => $Minute,
'#prefix' => '<td>',
  '#suffix' => '</td>',
'#disabled' => 'TRUE',
    );

if ($i==$max)
{

$form['rTimeZone_' . $i] = array(
        '#type' => 'select',
        '#title' => t('TimeZone'),
        '#options' => $TimeZone,
'#prefix' => '<td>',
  '#suffix' => '</td></tr></table>',
'#disabled' => 'TRUE',
    );

}
else
{

$form['rTimeZone_' . $i] = array(
        '#type' => 'select',
        '#title' => t('TimeZone'),
        '#options' => $TimeZone,
'#prefix' => '<td>',
  '#suffix' => '</td></tr>',
'#disabled' => 'TRUE',
);
}

"$i" har då bestämts av användaren i en tidigare del av dokumentet. Ifall användaren har skrivit in "4" så kommer det att finnas fyra stycken sådana här:

<label class="option"><input type="radio" id="edit-Registration-1-0" name="Registration_1" value="0"  checked="checked"  class="form-radio" /> ASAP</label>
</div>
<div class="form-item" id="edit-Registration-1-1-wrapper">
<label class="option"><input type="radio" id="edit-Registration-1-1" name="Registration_1" value="1"   class="form-radio" /> Specify</label>
</div>

När "edit-Registration-1-1" blir vald så skall "edit-rYear-1", "edit-rMonth-1" osv aktiveras.
När "edit-Registration-2-1" blir vald så skall "edit-rYear-2", "edit-rMonth-2" osv aktiveras.
När "edit-Registration-3-1" blir vald så skall "edit-rYear-3", "edit-rMonth-3" osv aktiveras.
När "edit-Registration-4-1" blir vald så skall "edit-rYear-4", "edit-rMonth-4" osv aktiveras.

Så jag ser inte hur en Class-lösning skulle kunna hjälpa här. Problemet är fortfarande att javascriptsfunktionen måste ha en variabel i namnet

$("#edit-Registration-1-1").change(
function()
{

(Har bifogat skärmdump ifall någon inte förstår hur det ser ut)

Flyttar frågan

itangalo's picture

Jag märker denna tråd som en gammal fråga.
Tyvärr är den lite för omfattande för att jag ska kunna bedöma om den blivit tillfredsställande besvarad eller inte - den som har bättre koll (AdamLinden?) får gärna märka om tråden.

//Johan Falk, forumadministratör