Ajax holt Daten, JQUERY erkennt ID nicht?

4 Antworten

Nun verstehe ich das richtig, dir geht es um die Controls, die du innerhalb der AJAX Datei nach lädst, sprich in dem Beispiel:

<input type="number" id="image_horizontal_edit1" value="" placeholder="Horizontal">
<input type="number" id="image_vertical_edit1" value="" placeholder="Vertical"><br><br>
<input type="number" id="image_zoom_edit1" value="" placeholder="Zoom"><br><br>

In den Code, den du uns da zeigst sehen wir nix von EventHandlern für diese Controls, also können die auch nix machen. Diese EventHandler müssten ja gebindet werden, nachdem du die Elemente erstellt hast. Sprich in deiner success Funktion kommen, nachdem du sie in den DOM eingefügt hast.

Woher ich das weiß:Berufserfahrung – Softwareentwickler/Projektleiter seit 2012

Wenn ich mir deinen unten geposteten Code anschaue, fällt mir sofort ein Fehler auf: Du vergibst IDs mehrmals, obwohl sie eindeutig sein sollten. Je Iteration solltest du eine neue ID generieren:

for ($i = 0; $i < $count; ++$i) {
  echo $name[$i];

  echo "<input type=\"number\" id=\"image_horizontal_edit{$i}\" placeholder=\"Horizontal\">";
  echo "<input type=\"number\" id=\"image_vertical_edit{$i}\" placeholder=\"Vertical\"><br><br>";
  echo "<input type=\"number\" id=\"image_zoom_edit{$i}\" placeholder=\"Zoom\"><br><br>";
}

Das value-Attribut brauchst du im Übrigen nicht zu definieren, so lange es keinen eigenen (nicht leeren) Startwert hat.

Bei deinem zweiten Code-Abschnitt (ab /* ===c Bilder Laden === */) weiß ich nun nicht, ob dieser den direkten Anschluss zum obigen Code hat oder wie das zu interpretieren ist. Der JavaScript-Code steht in keinem script-Tag und wird nicht herausgerendert. Das sollte dir als Fehler doch auch schon aufgefallen sein?

Bezüglich deines letzten Code-Abschnitts wäre das zu prüfen, was Dory1 schon geschrieben hat.


BudSpenser 
Beitragsersteller
 10.01.2019, 17:59

Sry, nur ich weiß jetzt echt nicht mehr weiter. Ich hab nocheinmal dutzend mal mit Klassen probiert. Verschiedene IDs mit fortlaufende zahlen (for-schleife.). Ich habe nur 1 einziges Bild heruntergeladen und nochmals alles von vorne. Ich steh echt vor einem fragezeichen.

Ich habe jetzt nocheinmal nur das nötigste hochgeladen

HTML: https://pastebin.com/4Z4cGz0s

PHP Ajax: https://pastebin.com/n7YEKWhX

Komplettes HTML https://pastebin.com/sapiVhe4

regex9  10.01.2019, 23:39
@BudSpenser

Ich schreibe einmal wieder alles auf, was mir zunächst so auffällt.

1) script-Tags gehören in head- oder body-Element. Außerhalb derer dürfen sie nicht stehen. Den jQuery-Include würde ich von daher in den head schieben, das Skript darunter für Slider etc. entweder ebenso oder vor das Ende des body-Körpers. Am besten kommt dessen JS-Code in eine externe Datei, auf die das script-Tag nur verweist.

2) In dem ersten großen Script-Block (den ich eben bereits erwähnt habe), sehe ich immer wieder mehrere aufeinanderfolgende Blöcke mit nahezu gleichem Code - nur der Selektor ändert sich etwas. Da sind bspw. die keyup-Listener, die du definierst. Dazu könntest du dir eine Funktion schreiben, in der alle Vorgänge generalisiert werden.

Ein Beispiel (vgl. mit Zeile 108-117 aus deinem 3. pastebin):

function setImageAndTextKeyUpListener(area) {
  $("#title_" + area + "_inp1").keyup(function () {
    let value = $(this).val();
    $("#ff_home_image_" + area + "1").html(value);
    $("#ff_home_image_" + area + "_editor1").html(value);
  });
}

setImageAndTextKeyUpListener("header");
setImageAndTextKeyUpListener("text");

Das einzige, was sich in deinen beiden Blöcken ändert, sind die IDs - und das sogar jeweils nur an einer Stelle. Auf das Element selbst, an welches der Listener gehängt wird, kann man mit jQuery übrigens via $(this) zugreifen.

Mache also zunächst aus - welche Code-Blöcke haben viele Gemeinsamkeiten bzw. tun dasselbe, nur halt an individuellen Elementen. Schreibe dazu ruhig eine Funktion. Individuelle Stellen werden mit einem Platzhalter (Parameter) belegt, welcher später bei Aufruf der Funktion gesetzt wird.

3) Lasse leere HTML-Attribute (wie z.B. class="") raus. Es sind nur Daten, die zusätzlich an den Client übermittelt werden müssen, obwohl es nicht notwendig wäre. Zudem blähen sie das Markup auf.

4) Da du im head die Zeichenkodierung UTF-8 gewählt hast, kannst du Umlaute normal schreiben, du musst sie nicht mehr maskieren.

5) Vermeide Inline-Styles (Zeile 776, 786). Stattdessen kannst du die Elemente bspw. mit dem Pseudoselektor nth-child in CSS ansprechen.

/* not tested */
#row_main2 li:last-child {
  margin-bottom: .5rem;
}

6) Weiterhin gibt es wieder sehr sehr viel Markup, welches mit PHP verkürzt werden könnte. Bspw. eine Navigation, in der sich nur URL und Title je Listenpunkt ändern: Pack diese Daten in ein assoziatives Array und iteriere über dieses.

Ein simples Beispiel:

$links = array("point a" => "some url", "point b" => "other url", // ...

foreach ($links as $linkTitle => $link): ?>
  <li>
    <a href="<?= $link $?>"><?= $linkTitle ?></a>
  </li>
<?php endforeach; ?>

Zu deinem Problem: Ich glaube, ich habe es nun (so wie auch apachy) verstanden. Du fügst dynamisch HTML-Elemente zu deinem Dokument und möchtest dann auf Events reagieren, die auf ihnen ausgelöst werden können. Das ist aber derzeit noch nicht möglich, da die neuen Elemente zu dem Zeitpunkt, an dem du deine Listener bindest, noch nicht vorhanden sind.

Du musst die Listener also im AJAX Callback binden.

Ich habe einmal ein simples Beispiel geschrieben, welches zeigt, wie es geht.

index.php

<!doctype html>
<head>
  <title>Bind event listener to dynamic loaded HTML</title>
  <script shttps://code.jquery.com/jquery-latest.jst.js"></script>
</head>
<body>
  <button id="load" type="button">Click me</button>
  <div id="output"></div>
  <script>
    $("#load").click(function (event) {
      $.post("getParagraphs.php", function (data) {
        let output = $("#output");
        output.html(data);

        $("p", output).click(function () {
          $(this).css("background-color", "yellow");
        });
      });
    });
  </script>
</body>

getParagraphs.php:

<?php

  for ($i = 0; $i < 5; ++$i) {
    print "<p id=\"paragraph{$i}\">{$i}</p>";
  }        

Vielleicht steckst du einfach alle Zeilen, in denen du die neu geladenen Elemente mit Listenern ausstattest, in eine Funktion setup und rufst diese im Callback auf.

BudSpenser 
Beitragsersteller
 11.01.2019, 17:40
@regex9

Danke, so wie immer, der beste

2. Auf eine Funktion habe ich auch schon gedacht, nur weiß/wusste ich nicht ganz wie ich das schreiben soll, da mein Ansatz nicht wirklich funktionierte.

$('#title_header_inp1').keyUP(function() { headertext(this); });
function headertext(inp) { 
if ($(inp).attr('class').includes('header')) {
inputtext = inp.val();
title = $(inp).attr('class').substr(5,6); //So ungefähr glaube ich
$('#ff_home_image_'+title+'1}.html(inptext); 
} else if {
 ..... TEXT ....
}

3. Dachte eigentlich, das es ziemlich egal sein wird ob es jetzt nun da steht oder nicht, da es für sowieso leer ist.

6. Oky, werde ich ausprobieren

Ich hatte zwar etwas Probleme beim nachkonstruierten beim code, aber ich verstehe denn sinn dahinter.

regex9  11.01.2019, 22:01
@BudSpenser

Bei deinem Code-Versuch hättest du ein Problem gehabt: Du hättest für jede Variante des Selektors, einen else-if-Zweig einbauen müssen. Angenommen, da käme nun noch ein title_footer_inp1 hinzu, wären es wieder mehrere Zeilen Code, die eigentlich redundant wären.

Abläufe zu generalisieren, erfordert etwas Übung, aber genügend Fälle hast du bei deinem Code ja gegeben. 😁 Manchmal - das denke ich, sollte ich noch erwähnen, kann es aber auch besser sein, Code zu belassen, wenn die verschiedenen Blöcke, die man zusammenfassen wollen würde, doch zu viele Eigenheiten aufweisen. Da gilt es abzuwägen und zu schauen, ob nicht stattdessen Teilbereiche aufsplitten / auslagern könnte.

Eine generelle Annäherung an die OOP bzw. eine Nutzung dieser, wäre das letztendliche Ziel.

BudSpenser 
Beitragsersteller
 12.01.2019, 14:02
@regex9

sry wenn ich das jetzt sage, aber jetzt verstehe ich gerade nur bahnhof

Else if versteh ich ja, aber dass andere

regex9  12.01.2019, 18:31
@BudSpenser

In kurz: Schau einfach, ob es Sinn macht, Code über Funktionen zu generalisieren.

Beispiel:

firstRectangle.color = "red";
firstRectangle.innerText = "hello";
firstRectangle.border = "2px solid";

secondRectangle.color = "red";
secondRectangle.border = "2px solid";
secondRectangle.position.x = 50;

thirdRectangle.color = "red";
thirdRectangle.position.y = 5;
thirdRectangle.innerText = "world";

Hier ließen sich z.B. kaum Gemeinsamkeiten finden, bis auf die Zeile, in der die Farbe gesetzt wird. Ob man das wirklich herauszieht, ist Abwägungssache.

let rectangles = [ firstRectangle, secondRectangle, thirdRectangle ];

rectangles[0].innerText = "hello";
rectangles[0].border = "2px solid";

rectangles[1].border = "2px solid";
rectangles[1].position.x = 50;

rectangles[2].position.y = 5;
rectangles[2].innerText = "world";

for (let i = 0; i < rectangles.length; ++i) {
  rectangles[i].color = "red";
}

Das lohnt sich vielleicht, wenn man mehrere Properties hat, die zudem immer den gleichen Wert bekommen.

BudSpenser 
Beitragsersteller
 12.01.2019, 19:11
@regex9

Ok, ja da fällt mir was ein.

Dann hätte ich gleich dazu eine frage

Wie kann ich transform-origin splitten?

Das problem ist, ich habe kein Beistrich als Anhaltspunkt, nur ein Leerzeichen

regex9  12.01.2019, 19:15
@BudSpenser

Möchtest du den Wert dieses Properties in einzelne Worte splitten oder meinst du etwas anderes?

Ein Leerzeichen kann ebenso als Trennzeichen verwendet werden. Beispiel mit JavaScript:

let text = "What a nice day";
let words = text.split(" ");
BudSpenser 
Beitragsersteller
 12.01.2019, 19:21
@regex9

Hab ich mir schon gedacht

        horizontal = $('.header_text_transform').css('transform-origin');
        test = parseInt(horizontal.split(' ')[0]);
        $('#testss').html(test);

Nur leider bekomme ich garkein ausgabe

Weder bei [0] noch [1]

BudSpenser 
Beitragsersteller
 12.01.2019, 19:33
@BudSpenser

sryy, ich hab eine Zeile zuweit unten den code eingefügt, da wurde bereits der code etwas gesplittet

regex9  12.01.2019, 19:33
@BudSpenser

Ein Beispiel: https://jsfiddle.net/pbdyxk6L/

Lasse dir einmal den Wert von horizontal ausgeben und prüfe über den Webinspektor, welche Werte für das CSS-Property bei den betroffenen Elementen wirklich angegeben sind.

EDIT: Ah, ok.

BudSpenser 
Beitragsersteller
 12.01.2019, 19:36
@regex9

tut mir echt leid, da war ich etwas zu voreilig

Danke

BudSpenser 
Beitragsersteller
 17.01.2019, 19:45
@BudSpenser

Sorry, auch wenn es jetzt schon 5 Tage her ist, zu jQuery, was ich jetzt mit $(document).on('load') gelöst habe. Wie funktioniert es dann bei der einfachen function? Weil das Img was per Ajax hinzugefügt wird, existiert ja eigentlich nicht. Der onclick wird dennoch ausgeführt(hinzugefügten IMG) aber es wird immer das letzte existierende img aufgerufen "currentSlide(6)"

      function plusSlides(n) {
        showSlides(slideIndex += n);
      }

      function currentSlide(n) {
        showSlides(slideIndex = n);
      }
 
<img onclick="currentSlide(7)" class="slideshow-demo slideshow-cursor ff-test-image" alt="Mountains and fjords">
BudSpenser 
Beitragsersteller
 17.01.2019, 19:55
@BudSpenser

Sorry, auch wenn es jetzt schon 5 Tage her ist, zu jQuery, was ich jetzt mit $(document).on('load') gelöst habe. Wie funktioniert es dann bei der einfachen function? Weil das Img was per Ajax hinzugefügt wird, existiert ja eigentlich nicht. Der onclick wird dennoch ausgeführt(hinzugefügten IMG) aber es wird immer das letzte existierende img aufgerufen "currentSlide(6)"

      function plusSlides(n) {
        showSlides(slideIndex += n);
      }

      function currentSlide(n) {
        showSlides(slideIndex = n);
      }
 
<img onclick="currentSlide(7)" class="slideshow-demo slideshow-cursor ff-test-image" alt="Mountains and fjords">
regex9  17.01.2019, 21:14
@BudSpenser

In dem Moment, in dem das neue img-Element vom Browser gerendert wird, werden natürlich auch die jeweiligen Attribute interpretiert und in diesem Fall, die Funktion currentSlide an das onclick-Property des img-Elements gebunden. Ob die Funktion überhaupt existiert, wird erst zur Laufzeit auffällig, wenn man auf das Bild klickt. Da die Funktion jedoch bereits definiert ist, wird es kein Problem diesbezüglich geben.

(...) aber es wird immer das letzte existierende img aufgerufen "currentSlide(6)"

Dazu kann ich nichts sagen. Die 7 sollte auf jeden Fall an die Funktion übergeben werden. In dieser könntest du n eigentlich gleich durchreichen, eine neue explizite Variable brauchst du gar nicht. Um nun noch einen besseren Bezeichner zu haben, wäre dies ausreichend:

function currentSlide(slideIndex) {
  showSlides(slideIndex);
}

Was in showSlides nun durchgeführt wird, müsstest du überprüfen.

BudSpenser 
Beitragsersteller
 17.01.2019, 21:25
@regex9

OK, ich habe es mal so gelöst

Attribute beim img hinzugefügt, dadurch wurde currentSlide geschichte.

  $(document).on('click', '.slideshow-demo', function () {
   var slide = $(this).parents('.slideshow-column').attr('data-slideshow');
   slideIndex = slide++;
   slideIndex = slide++;
   showSlides(slideIndex);
  });
   function showSlides(n) {
    var i;
    var slides = document.getElementsByClassName("slideshow-mySlides");
    var dots = document.getElementsByClassName("slideshow-demo");
    if (n > slides.length) {slideIndex = 1}
    if (n < 1) {slideIndex = slides.length}
    for (i = 0; i < slides.length; i++) {
      slides[i].style.display = "none";
    }
    for (i = 0; i < dots.length; i++) {
      dots[i].className = dots[i].className.replace(" slideshow-active", "");
    }
    slides[slideIndex-1].style.display = "block";
    dots[slideIndex-1].className += " slideshow-active";
   }
BudSpenser 
Beitragsersteller
 10.01.2019, 06:59

Doch, tag ist vorhanden, davor noch $(document).ready...

Du versuchst deine Event-Handler zu registrieren bevor die tatsächlichen Elemente im Dokument existieren. Zum Zeitpunkt der Ausführung ist noch keines der Elemente vorhanden, somit kann auch nichts registriert werden.

Anstatt die Event-Handler direkt am Element zu erzeugen:

$('.title-edit').click(function () { 
   ...

kannst du das Click-Ereignis an ein höher liegendes Element delegieren, dass zum Zeitpunkt der Ausführung bereits existiert (Event-Delegation):

$(document).on('click', '.title-edit', function () { 
   ...

regex9  11.01.2019, 23:21

Bei so einer Lösung ist allerdings mit zu beachten, dass das Elternelement, welches künftig die Events abfängt, eine größere Klickfläche zur Verfügung stellen könnte, die nicht einmal eines der Elemente enthalten muss. Das tatsächlich geklickte Element holt man sich dann am besten über das Event-Objekt.

$(document).on("click", ".title-edit", function (evt) {
  let element = evt.target;
  // ...
});  
BudSpenser 
Beitragsersteller
 12.01.2019, 11:37
@regex9

Danke, dass habe ich bemerkt.

Ich habe jetzt eine frage noch. Die Inputs die ich mit php(ajax) erzeuge, werden mittels button more ein ausgeblendet.

Da ich jetzt das script etwas umschreiben musste sieht das jetzt so aus

      $(document).on('click', '.editor_more', function () {
          $(this).next().toggle(); // header_text_horizontal
          $(this).next().next().toggle(); // header_text_vertical
          $(this).next().next().next().toggle(); // header_text_reset
          $(this).parents('.title-editor-style').next().nextUntil('.image-editor-position').toggle(); 
      });

Das funktioniert ja auch, nur ist es blöd wenn jetzt zum Beispiel irgendwo zwischen drinen ein weiteres div hinzukommt, was garnicht ausgeblendet werden soll. Ich müsste dann immer das Script mit ein weiteren next oder prev umändern.

Gibt es auch hierfür eine Lösung?

Die 2 gingen leider nicht

$(this).next('.header_text_horizontal').toggle();
$(this).next('.header_text_vertical').toggle();
$(this).next('.header_text_reset').toggle();

$(this).nextUntil('.header_text_horizontal').toggle();
$(this).nextUntil('.header_text_vertical').toggle();
$(this).nextUntil('.header_text_reset').toggle();

Wie sollen wir das beurteilen ohne deinen Code zu sehen? Bitte poste zumindest den relevanten HTML-Abschnitt und dein JavaScript.


BudSpenser 
Beitragsersteller
 10.01.2019, 00:12

Sry, da war ja was

Ajax PHP Datei

if (!$title->execute()) {
  echo "Fehler";
} else {
  $name = array();
  while ($data = $title->fetch()) {
    $name[] = $data['name'];
  }
$count = count($name);
  for ($i=0; $i < $count; $i++) {
    echo $name[$i];


    echo '    <input type="number" id="image_horizontal_edit1" value="" placeholder="Horizontal">';
    echo '    <input type="number" id="image_vertical_edit1" value="" placeholder="Vertical"><br><br>';
    echo '    <input type="number" id="image_zoom_edit1" value="" placeholder="Zoom"><br><br>';


      /* ===c Bilder Laden === */
      $('#load_image').click( function (event) {
        event.preventDefault();
        $.ajax({
          type: 'POST',
          url: 'ajax/home.php',
          data: $(this).serialize(),
          success: function (title_image) {
            $('#title_image').html(title_image);
          }

        });

    echo '  <a id="editor_more1" class="btn btn-info editor_more"><span class="glyphicon glyphicon-plus"></span> MORE</a>';



<button id="load_image" type="submit" name="load_image" class="btn btn-primary start"> <span><i class="glyphicon glyphicon-picture"></i>Bilder Laden</span> </button>
        <div id="title_image" class="margin">
          <!-- DIVS vom PHP AJAX -->
        </div>

Leider kommt funktioniert die abfrage nicht

      $('.editor_more').on('click',function () {

        $('#testss').html("test");

});

Dory1  10.01.2019, 00:15
@BudSpenser

Existiert denn ein Element mit der ID "testss"? In deinem HTML sehe ich keins.

Werden dir JS-Fehler in der Browserkonsole angezeigt?

BudSpenser 
Beitragsersteller
 10.01.2019, 06:56
@Dory1

testss existiert im HTML, <p></p>

In der konsole wird nichts ausgegeben.

Die Bilder, buttons, inputs werden zwar geladen und angezeigt aber führen keinen event aus