• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Frage Nach erweiterung von dem Formular geht JavaScript nicht in der Erweiterung

Igi

Neues Mitglied
Hi
ich wende mich an euch vielleicht könnt ihr mir weiter helfen. Ich bin dabei ein dynamisches Formular zu basteln, ich bin kein Profi was JavaScript angeht und von daher habe ich mir nach Legoprinzip dieses dynamisches Formular erstellt:
Formular.png
Soweit klappt alles gut bis auf in "Inviduvidual Settings".
Normalerweise ist dort nur eine Zeile drin anschließend kann ich dynamisch weitere Zeilen hinzufügen.
So jetzt kommt das Problem in der ersten Zeile was von Anfang an da ist funktioniert das DateTimePicker Script für das Auswahl des Datum aber ab der 2 geht es nicht mehr.
Datum.png
Da stehe ich jetzt etwas auf dem Schlauch und komme nicht vorran beide Elemente sind gleich von classen her warum geht das Script bei dem ersten und bei dem zweitem nicht?

Hier der Code ist ein Django web framework Projekt:
Die HTML Datei:
HTML:
{% extends "ps/base.html" %}

{% block title %}
Power Settings
{% endblock %}

{% block head %}
    <!--  Script for the Checkbox -->
    <script type="text/javascript" src="/static/ps/js/jquery-1.11.3.min.js"></script>
   
    <!-- Script for DateTimepicker -->
    <script src="/static/ps/js/jquery.js"></script>
    <script src="/static/ps/js/jquery.datetimepicker.js"></script>
     
    <!--  Scripts for power settings -->
    <script type="text/javascript" src="/static/ps/js/power_settings.js"></script>
    
    <!-- CSS for the DateTimepicker -->
    <link rel="stylesheet" type="text/css" href="/static/ps/css/jquery.datetimepicker.css"/ >
       
{% endblock %}

{% block content %}

<h1>Power Settings View</h1>

    <form action="/ps/save_change_settings/" method="post">
        {% csrf_token %}
       
        {{ pc_settings_form.as_p }}
       
    <div id="individual_settings">
        <fieldset>
            <legend>       
            Individual settings
            </legend>
           
            <table id="tableIndividualSettings">
            <thead>
              <tr>
                <th width = 110>From</th>
                <th width = 110>To</th>
                <th width = 55>Enable</th>
                <th width = 110>Power on</th>
                <th width = 110>Power off</th>
                <th width = 395>Comment</th>
                <th >Delete</th>
              </tr>
            </thead>
            <tbody>
                <tr>
                   
                </tr>
            </tbody>
              </table>  
                      
            <div class="item individual_sttings_fieldset">  
             
                 {{ individual_settings_formset.management_form }}
                    {% for form in individual_settings_formset.forms %}
                         {{ form }}
                   
                      {% endfor %}
                         
              <input type="button" class="delete checkbox_power_save" href="#" value="x" />
           
            </div>
                       
        <br>   
        <input id="add" href="#" type="button" class= "checkbox_power_save" value="+ individual Setting" />
           
        </fieldset>
    </div>
   
    <div id="timecontainer_working_days">
        <fieldset>
            <legend>
            Working Day Settings
            </legend>
               
                <!-- Timepicker -->
                {{ working_day_form.as_table}}
           
        </fieldset>
    </div>
       
    <div id="timecontainer_closing_days"> 
        <fieldset>
            <legend>
                Closing Day Settings
            </legend>
               
                <!-- Timepicker -->
                {{ closing_day_form }}
           
        </fieldset>
    </div>
       
    <p>
        <input type="submit" value="Save/Change Settings" />
    </p>
   
    </form>
   
    <script type="text/javascript">
        $('.timepicker').datetimepicker({
            datepicker:false,
              format:'g:i a',
            step:15,
        });
       
        $('.datepicker').datetimepicker({
            timepicker:false,
            format:'Y-m-d',
            dayOfWeekStart: '1',
        });
       
    </script>
   
   
{% endblock %}

Hier das Script:
Code:
$(document).ready(function () {

    // At first the script for enable/disable the Power Controll Settings Form
     
    // This function is for enable/disable the Power Controll Settings Form
    $("input[name='enable_power_control']").click(function(){
           if ($(this).is(':checked')) {
                   $('input.checkbox_power_save').attr("disabled", false);
                $('textarea.checkbox_power_save').attr("disabled", false);
                $('select.checkbox_power_save').attr("disabled", false);
             }
           else if ($(this).not(':checked')) {
                $('input.checkbox_power_save').attr("disabled", true);
                $('textarea.checkbox_power_save').attr("disabled", true);
                $('select.checkbox_power_save').attr("disabled", true);
            }
    });
   
    function activateDeactivateTime(){
        //var test =     $(el, prefix, ndx).click()
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
       
        //print(id_regex);
       
        if ($(this).is(':checked')) {
            $('#id_form-0-power_on').attr("disabled", false);
        }
        else if ($(this).not(':checked')) {
            $('#id_form-0-power_on').attr("disabled", true);
        }
    };
       
    // This function is for enable/disable the Power Controll times in the individual settings
    $("input[name='form-0-enable_power_off']").click(function(){
           if ($(this).is(':checked')) {
                   $('#id_form-0-power_off').attr("disabled", false);
                }
           else if ($(this).not(':checked')) {
               $('#id_form-0-power_off').attr("disabled", true);
               }
    });
       
    // Now the script for add and remove individual settings.
    // Code adapted from http://djangosnippets.org/snippets/1389/
    function updateElementIndex(el, prefix, ndx) {
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
        var replacement = prefix + '-' + ndx + '-';
        if ($(el).attr("for"))
            $(el).attr("for", $(el).attr("for").replace(id_regex,
                    replacement));
        if (el.id)
            el.id = el.id.replace(id_regex, replacement);
        if (el.name)
            el.name = el.name.replace(id_regex, replacement);
    }
    function deleteForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        if (formCount > 1) {
            // Delete the item/form
            $(btn).parents('.item').remove();
            var forms = $('.item'); // Get all the forms
            // Update the total number of forms (1 less than before)
            $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
            var i = 0;
            // Go through the forms and set their indices, names and IDs
            for (formCount = forms.length; i < formCount; i++) {
                $(forms.get(i)).children().children().each(function () {
                    updateElementIndex(this, prefix, i);
                });
            }
        } // End if
        else {
            alert("You have to enter at least one setting!");
        }
        return false;
    }
    function addForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        // You can only submit a maximum of 10 individual settings
        if (formCount < 10) {
            // Clone a form (without event handlers) from the first form
            var row = $(".item:first").clone(false).get(0);
            // Insert it after the last form
            $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);

            // Remove the bits we don't want in the new row/form
            // e.g. error messages
            $(".errorlist", row).remove();
            $(row).children().removeClass('error');

            // Relabel/rename all the relevant bits
            $(row).children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                if ($(this).attr('type') == 'text')
                    $(this).val('');
            });
           
            // Add an event handler for the delete item/form link
            $(row).find('.delete').click(function () {
                return deleteForm(this, prefix);
            });
            // Update the total form count
            $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
        } // End if
        else {
            alert("Sorry, you can only enter a maximum of ten settings.");
        }
        return false;
    }
   
    // Register the click event handlers
    $("#add").click(function () {
        return addForm(this, 'form');
    });

    $(".delete").click(function () {
        return deleteForm(this, 'form');
    });
   
});

Also ich vermutte es liegt an Javascript es ist noch nicht ganz fertig.
Ich hoffe ihr könnt mir einen Tipp geben woran das liegt. ;)

Gruß
Igi
 
Werbung:
Da stehe ich jetzt etwas auf dem Schlauch und komme nicht vorran beide Elemente sind gleich von classen her warum geht das Script bei dem ersten und bei dem zweitem nicht?

Per dom.ready registrierte Events wirken nicht auf nachträglich dem DOM hinzugefügte HTML-Elemente. Dafür benötigt man Event Delegation, also statt einfacher Listener etwas á la
Code:
$('body').on('click', '#myElement', function() {...})

Für das Datepicker Problem gibt es eine Antwort bei stackoverflow:
http://stackoverflow.com/questions/1667419/jquery-datepicker-not-working-on-newly-added-row
 
vielen Dank für die Antwort.
  1. Verstehe ich das richtig das nach dem DOM Änderung mein ganzer zusammengebastelter Code in
    Code:
    $(document).ready(function () {...}
    nicht funktionier und ich muss das neu bauen?
  2. Ich weiß nicht ob es sowas geht, aber kann man nicht einfach nachdem man den DOM verändert hat in irgendeineweise die fehlenden Events nachregestrieren?
  3. Und wenn es nicht geht, wie muss ich mein script mit Event Delegation erweitern?
 
Werbung:
Danke noch mal.
Aber ich bin bei Javascript noch recht neu und mit den Listener, Envents und dazugehören Classen/IDs noch nicht vertraut und komme da sehr schleppend voran.
Könnt ihr vielleicht ein einfaches Beispiel geben wie ich
Code:
$(document).ready(function () {...}
in solche
Code:
$('body').on('click', '#myElement', function() {...})
umwandle?
Weil ich habe jetzt etwas Schwierigkeit alle Listener in Events umzubauen, die ganzen Abhängigkeiten zu beachten und an welche stelle soll das gemacht werden.
 
Weil ich habe jetzt etwas Schwierigkeit alle Listener in Events umzubauen, die ganzen Abhängigkeiten zu beachten und an welche stelle soll das gemacht werden.

Das Script, welches innerhalb $(document).ready() steht, wird einmalig nach dem Aufbau des DOM abgearbeitet. Dazu zählt auch die Bindung eines Events an ein HTML-Tag, wie der Click auf einen Button. Sofern man anschließend weitere Buttons dynamisch hinzufügt, werden diese von einem einfachen Event-Handler nicht mehr berücksichtigt. Es sei denn, man 'delegiert' das Event von oben innerhalb des DOM nach unten zum Button. Das mag kompliziert klingen, lässt sich aber mit der Syntax von jQuery einfach abbilden. Ich habe es anbei mal verdeutlicht.

https://jsfiddle.net/rjtbvd60/1/

Nachträglich eingefügte Elemente führen das 'Hello World' nicht aus, aber wenn du Zeile 11 aus- und Zeile 16 einkommentierst, funktioniert es.
 
Werbung:
@Tronjer vielen Dank dir ;).

Die Event Händler habe ich eingebaut funktioniert wunderbar
Code:
// Add an event handler for the timepicker
            $(row).find('.timepicker').click(
                    $('.timepicker').datetimepicker({
                        datepicker:false,
                          format:'g:i a',
                        step:15,
                    })
            );
        
            // Add an event handler for the datepicker
            $(row).find('.datepicker').click(
                    $('.datepicker').datetimepicker({
                        timepicker:false,
                        format:'Y-m-d',
                        step:15,
                    })
);

hier komplett eingebaut:

Code:
(function($){ $(document).ready(function($){
 
    /** At first the script for enable/disable the Power Controll Settings Form
     *
     * Then the script for add and remove individual settings.
     */

    // This function is for enable/disable the Power Controll Settings Form
    $("input[name='enable_power_control']").click(function(){
           if ($(this).is(':checked')) {
                   $('input.checkbox_power_save').attr("disabled", false);
                $('textarea.checkbox_power_save').attr("disabled", false);
                $('select.checkbox_power_save').attr("disabled", false);
             }
           else if ($(this).not(':checked')) {
                $('input.checkbox_power_save').attr("disabled", true);
                $('textarea.checkbox_power_save').attr("disabled", true);
                $('select.checkbox_power_save').attr("disabled", true);
            }
    });
   
    // Now the script for add and remove individual settings.
    // Code adapted from http://djangosnippets.org/snippets/1389/
    function updateElementIndex(el, prefix, ndx) {
        var id_regex = new RegExp('(' + prefix + '-\\d+-)');
        var replacement = prefix + '-' + ndx + '-';
        if ($(el).attr("for"))
            $(el).attr("for", $(el).attr("for").replace(id_regex,
                    replacement));
        if (el.id)
            el.id = el.id.replace(id_regex, replacement);
        if (el.name)
            el.name = el.name.replace(id_regex, replacement);
    }
    function deleteForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        if (formCount > 1) {
            // Delete the item/form
            $(btn).parents('.item').remove();
            var forms = $('.item'); // Get all the forms
            // Update the total number of forms (1 less than before)
            $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
            var i = 0;
            // Go through the forms and set their indices, names and IDs
            for (formCount = forms.length; i < formCount; i++) {
                $(forms.get(i)).children().children().each(function () {
                    updateElementIndex(this, prefix, i);
                });
            }
        } // End if
        else {
            alert("You have to enter at least one setting!");
        }
        return false;
    }

    function addForm(btn, prefix) {
        var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
        // You can only submit a maximum of 10 individual settings
        if (formCount < 10) {
         
            // Clone a form (without event handlers) from the first form
            var row = $(".item:first").clone(false).get(0);
            // Insert it after the last form
            $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);
         
            // Remove the bits we don't want in the new row/form
            // e.g. error messages
            $(".errorlist", row).remove();
            $(row).children().removeClass('error');

            // Relabel/rename all the relevant bits
            $(row).children().children().each(function () {
                updateElementIndex(this, prefix, formCount);
                if ($(this).attr('type') == 'text')
                    $(this).val('');
            });
         
            // Add an event handler for the delete item/form link
            $(row).find('.delete').click(function () {
                return deleteForm(this, prefix);
            });
         
            // Add an event handler for the timepicker
            $(row).find('.timepicker').click(
                    $('.timepicker').datetimepicker({
                        datepicker:false,
                          format:'g:i a',
                        step:15,
                    })
            );
         
            // Add an event handler for the datepicker
            $(row).find('.datepicker').click(
                    $('.datepicker').datetimepicker({
                        timepicker:false,
                        format:'Y-m-d',
                        step:15,
                    })
            );
         
            // Update the total form count
            $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
        } // End if
        else {
            alert("Sorry, you can only enter a maximum of ten settings.");
        }
        return false;
    }
 
    // Register the click event handlers
    $("#add").click(function () {
        return addForm(this, 'form');
    });

    $(".delete").click(function () {
        return deleteForm(this, 'form');
    });
 
 
     
    // This function is for enable/disable the Power Controll times
    // in the individual settings
    $("input[name='form-0-enable_power_on']").click(function(){
           if ($(this).is(':checked')) {
                   $('#id_form-0-power_on').attr("disabled", false);
                }
           else if ($(this).not(':checked')) {
               $('#id_form-0-power_on').attr("disabled", true);
               }
    });
 
 
    // This function is for enable/disable the Power Controll times
    // in the individual settings
    $("input[name='form-0-enable_power_off']").click(function(){
           if ($(this).is(':checked')) {
                   $('#id_form-0-power_off').attr("disabled", false);
                }
           else if ($(this).not(':checked')) {
               $('#id_form-0-power_off').attr("disabled", true);
               }
    });
     
    // Add an event handler for the EnablePowerOn
    $(document).on('click', "input[name='form-0-enable_power_on']", EnablePowerOn);
 
    function EnablePowerOn(){
           if ($(this).is(':checked')) {
                   $('#id_form-0-power_on').attr("disabled", false);
                }
           else if ($(this).not(':checked')) {
               $('#id_form-0-power_on').attr("disabled", true);
               }
    };
 
    // Add an event handler for the EnablePowerOff
    $(document).on('click', "input[name='form-0-enable_power_off']", EnablePowerOff);
 
    function EnablePowerOff(){
       if ($(this).is(':checked')) {
               $('#id_form-0-power_off').attr("disabled", false);
            }
       else if ($(this).not(':checked')) {
           $('#id_form-0-power_off').attr("disabled", true);
           }
    };

});
})(jQuery);

funktioniert super bis auf die Checkbox. Ich möchte in jeder Zeile die Zeitauswahl deaktivieren und aktivieren können. Checkbox.png
Momentan kann ich nur die Zeitauswahl in der ersten Zeile deaktivieren, obwohl ich in der letzten Zeile die Checkbox deaktivire.
Da fehlt mir noch die Verknüpfung zur der jeweiligen Zeile. Da bräuchte ich auch Denkanstoß wie ich das am besten machen soll :)?!

LG Igi
 
ne event habe ich, das funktioniert ja nur nicht auf das gewünschte Feld,
hier noch mal visuell siehe Bild
checkbox-png.4186.png
in dem grünem dynamischen erstellten Formular klicke ich die Checkboxes an und die wirken immer auf den Input in der erste Zeile.
Z.B wenn ich die markierte Checkbox 1) anklicke, in der letzten Zeile und es soll den Input 3) aus der letzten Zeile (de-)aktivieren, aber es (de-)aktiviert den Input 2) aus der ersten Zeile.

Meine Idee ich vergeben dynamische IDs beim erzeugen von den neuen Zeilen und ich muss diese auswerten und anhand der ID dann auch die Inputs (de-)aktivieren.

Ist die Idee richtig? Wenn ja wie erstelle ich dynamische IDs und wie greife ich darauf zu? Da muss ich doch mit Regulären Ausdrücken arbeiten. (Regulären Ausdrücke ist kein Problem)
 
Werbung:
Du könntest natürlich eindeutige Identifier in Form von IDs erzeugen. Eine andere gebräuchliche Variante wäre, innerhalb des DOM zu traversieren, à la: 'Gehe eine Ebene nach oben, eine nach rechts und eine nach unten und mache was mit dem Element'. Dafür gibt es in jQuery Methoden wie closest(), find(), prev(), next(), usw.
 
  • Like
Reaktionen: Igi
Nochmal vielen Dank Tronjer!! :)
Es hat gut geklappt mit .find() und mit .next() das erleichtert die Arbeit um einiges!! :D

Hier nun das ganze dynamische Formular HTML ist wie oben unverändert und hier das Script:

Code:
(function($){ $(document).ready(function($){

   /** At first the script for enable/disable the Power Controll Settings Form
    *
    * Then the script for add and remove individual settings.
    */
 
 
   // This function is for enable/disable the Power Controll Settings Form
   $("input[name='enable_power_control']").click(function(){
      if ($(this).is(':checked')) {
           $('input.checkbox_power_save').attr("disabled", false);
         $('textarea.checkbox_power_save').attr("disabled", false);
         $('select.checkbox_power_save').attr("disabled", false);
        }
      else if ($(this).not(':checked')) {
        $('input.checkbox_power_save').attr("disabled", true);
        $('textarea.checkbox_power_save').attr("disabled", true);
        $('select.checkbox_power_save').attr("disabled", true);
       }
   });
 
 
   // Now the script for add and remove individual settings.
   // Code adapted from http://djangosnippets.org/snippets/1389/
   function updateElementIndex(el, prefix, ndx) {
     var id_regex = new RegExp('(' + prefix + '-\\d+-)');
     var replacement = prefix + '-' + ndx + '-';
     if ($(el).attr("for"))
       $(el).attr("for", $(el).attr("for").replace(id_regex,
           replacement));
     if (el.id)
       el.id = el.id.replace(id_regex, replacement);
     if (el.name)
       el.name = el.name.replace(id_regex, replacement);
   }
   function deleteForm(btn, prefix) {
     var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
     if (formCount > 1) {
       // Delete the item/form
       $(btn).parents('.item').remove();
       var forms = $('.item'); // Get all the forms
       // Update the total number of forms (1 less than before)
       $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
       var i = 0;
       // Go through the forms and set their indices, names and IDs
       for (formCount = forms.length; i < formCount; i++) {
         $(forms.get(i)).children().children().each(function () {
           updateElementIndex(this, prefix, i);
         });
       }
     } // End if
     else {
       alert("You have to enter at least one setting!");
     }
     return false;
   }

   function addForm(btn, prefix) {
     var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
     // You can only submit a maximum of 10 individual settings
     if (formCount < 10) {
     
       // Clone a form (without event handlers) from the first form
       var row = $(".item:first").clone(false).get(0);
     
       //Set attribute values to default and remove disabled
       $(row).find("input[type='text']").val("");
       $(row).find("*").removeProp('disabled');
     
       // Insert it after the last form
       $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);
     
       // Remove the bits we don't want in the new row/form
       // e.g. error messages
       $(".errorlist", row).remove();
       $(row).children().removeClass('error');

       // Relabel/rename all the relevant bits
       $(row).children().children().each(function () {
         updateElementIndex(this, prefix, formCount);
         if ($(this).attr('type') == 'text')
           $(this).val('');
       });
     
       // Add an event handler for the delete item/form link
       $(row).find('.delete').click(function () {
         return deleteForm(this, prefix);
       });
     
       // Add an event handler for the timepicker
       $(row).find('.timepicker').click(
           $('.timepicker').datetimepicker({
             datepicker:false,
               format:'g:i a',
             step:15,
           })
       );
     
       // Add an event handler for the datepicker
       $(row).find('.datepicker').click(
           $('.datepicker').datetimepicker({
             timepicker:false,
             format:'Y-m-d',
             step:15,
           })
       );
     
       // Update the total form count
       $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
     } // End if
     else {
       alert("Sorry, you can only enter a maximum of ten settings.");
     }
     return false;
   }
 
   // Register the click event handlers
   $("#add").click(function () {
     return addForm(this, 'form');
   });

   $(".delete").click(function () {
     return deleteForm(this, 'form');
   });
   
   /** Here are the function for disable/enable Power On/Off Times
    *    in the individual settings
    */
 
   // This function is for enable/disable the Power Control times
   // in the individual settings
   $("input[name='form-0-enable_power_off']").click(function(){
      if ($(this).is(':checked')) {
           $('#id_form-0-power_off').attr("disabled", false);
         }
      else if ($(this).not(':checked')) {
        $('#id_form-0-power_off').attr("disabled", true);
        }
   });
 
   // This function is for enable/disable the Power Control times
   // in the individual settings
   $("input[name='form-0-enable_power_off']").click(function(){
      if ($(this).is(':checked')) {
           $('#id_form-0-power_off').attr("disabled", false);
         }
      else if ($(this).not(':checked')) {
        $('#id_form-0-power_off').attr("disabled", true);
        }
   });
   
   // Add an event handler for the EnablePowerOn
  $(document).on('click', "input[name='form-0-enable_power_on']", EnablePowerOn);
 
  function EnablePowerOn(){
     
      if ($(this).is(':checked')) {
        $(this).next('.timepicker').attr("disabled", false);
        }
      else if ($(this).not(':checked')) {
        $(this).next('.timepicker').attr("disabled", true);
        }
   
   };
 
  // Add an event handler for the EnablePowerOff
  $(document).on('click', "input[name='form-0-enable_power_off']", EnablePowerOff);
 
  function EnablePowerOff(){
  if ($(this).is(':checked')) {
      $(this).next('.timepicker').attr("disabled", false);
      }
    else if ($(this).not(':checked')) {
      $(this).next('.timepicker').attr("disabled", true);
      }
   };
 
   // This function is for disable/enable the Power Control Times Settings
   //   in the individual settings
   // Add an event handler
 
   $(document).on('change', "select[name='form-0-enable']", PowerControlOnOff);
 
  function PowerControlOnOff(){
     if ($(this).val() === '2')
       $(this).siblings('.choice_ps_yes_no').attr('disabled', true);
     else
       $(this).siblings('.choice_ps_yes_no').attr('disabled', false);
  }
 
});
})(jQuery);

Das Script ist etwas träge aber es funktioniert ;)
 
Zuletzt bearbeitet:
Zurück
Oben