Zur Navigation

Web indexDB

daten in der indexDB speichern, auslesen, anzeigen

1 Kokarde

Guten Morgen

Der Kai mit einem neuen Thema, nachdem die Sache mit WebSQL leider nicht geklappt hat, da grundsätzlich nicht geeignet für mobile Browser auf Handys etc., aber echt cool für Desktop-Browser, wer sich da mal einlesen will kann gerne den anderen Thread dazu aufsuchen.
Stelle auch bei Nachfrage den gesamten Quellcode zur Verfügung.

Da bin ich nun, durch Suche nach "indexDB", mal kurz auf dieses Beispiel gestoßen, dass die Grundlage für mein nächstes ToDo ist.

Beispiel:
https://mdn.mozillademos.org/de/docs/IndexedDB/IndexedDB_verwenden$samples/Full_IndexedDB_example?revision=1121927

Also habe ich mich mal ran gesetzt, als Anfänger, und heraus gekommen ist diese momentane Version meiner ursprünglichen Idee:

www.hardwareplattform.de/web-index-db/spielwiese.html

Was will ich erreichen?

Ich möchte eine Offline-Web-App für mein Handy und mein iPad haben, dass ich mitnehmen kann ohne mit einer Online-DB verbunden zu sein und das auch nach dem Schliessen des Browsers die Werte für spätere Verwendung speichert.

Und es soll natürlich für meinen Zweck optimiert sein was die Handhabung angeht. Daher habe ich mich auch gegen die Möglichkeiten wie z. B. google-Docs entschieden.

Doch kommen wir jetzt mal zum ersten Problem :)

Die Grundfunktionen laufen schon einwandfrei, die man auch auf der Spielwiese sehen kann. Es fehlt jetzt zwar noch die "Update Funktion" eines vorhanden Eintrags, doch ich wollte eigentlich erst mal mit etwas einfachem weiter machen.

Scheitere jedoch hier kläglich.

Ich möchte auf der list.html Seite, dass der Button der dort zu sehen ist, sofort ausgelöst wird, wenn die Webseite aufgerufen wird, man diesen also nicht erst anklicken muss.

Wie könnte das gehen?

Hier der Code:

www.hardwareplattform.de/web-index-db/list.html

Habe es schon mit <body onload="Funktion-XYZ()"> probiert, aber das geht nicht.

14.10.2016 11:12 | geändert: 14.10.2016 11:14

2 Jörg

Grundsätzlich würde ich solche Scripte nicht im Body, sondern im Head-Bereich unterbringen

Ich möchte auf der list.html Seite, dass der Button der dort zu sehen ist, sofort ausgelöst wird, wenn die Webseite aufgerufen wird, man diesen also nicht erst anklicken muss.

Das ganze baut ja auf jquery auf. In der Funktion addEventListeners() werden Event Listener definiert, darunter einer für den Event, wenn jemand auf den Button mit der ID 'add-button' klickt:

$('#add-button').click(function(evt) {
  /* ... */
});

Ich nehme an, das ist der besagt Button?

Statt dessen könntest du als Event definieren, dass das Document geladen ist:

$(document).ready(function() {
  /* ... */
});

Ich würde zudem das HTML validieren, dann erhältst du so eine Fehlermeldung:

End tag for body seen, but there were unclosed elements.

Nicht, dass der Browser den Body noch nicht als fertig geladen betrachtet und deswegen den Event nicht auslöst.

Dieses Element sollte deswegen noch geschlossen werden:

<div class="jumbotron">

14.10.2016 17:35 | geändert: 14.10.2016 17:38

3 Kokarde

Moin Jörg

Ich habe am Weekend alles mal korrekt mit der Startseite verbunden, so das man sich nicht immer diese ganzen Links merken muss.

http://www.hardwareplattform.de/web-index-db/

Der Button ist der mit der folgenden ID:



id="search-list-button"


Dieser ruft auf:



var search_button = $('#search-list-button');
    search_button.click(function(evt) {
      displayPubList();
    });


Naiv wie ich bin, dachte ich dass man nun displayPubList() einfach so oben als <body onload=""> oder ähnlich aufrufen kann, das es automtisch ausgeführt wird.

Doch dies scheint dann wohl so nicht zu gehen.

Die Funktion, die durch displayPubList() aufgerufen wird, ist recht groß und enthält mehrere Abschnitte, die durch die Funktion dann in die Webseite geschrieben werden. Dazu gehört u. a. auch var pub_list = $('#pub-list'); das die Liste erzeugt die ich haben will :)

Hier der große Code-Block, wie er auch derzeit auf der Webseite steht.



  function displayPubList(store) {
    console.log("displayPubList");

    if (typeof store == 'undefined')
      store = getObjectStore(DB_STORE_NAME, 'readonly');

    var pub_msg = $('#pub-msg');
    pub_msg.empty();
      
    var pub_list = $('#pub-list');
    pub_list.empty();
      
    var req;
    req = store.count();
      
    // Requests are executed in the order in which they were made against the
    // transaction, and their results are returned in the same order.
    // Thus the count text below will be displayed before the actual pub list
    // (not that it is algorithmically important in this case).
      
    req.onsuccess = function(evt) {
      pub_msg.append('<p>Derzeit <strong>' + evt.target.result +
                     '</strong> Einträge in der Liste.<br></p>');
    };
      
    req.onerror = function(evt) {
      console.error("add error", this.error);
      displayActionFailure(this.error);
    };

    var i = 0;
    req = store.openCursor();
    req.onsuccess = function(evt) {
      var cursor = evt.target.result;

      // If the cursor is pointing at something, ask for the data
        
      if (cursor) {
        console.log("displayPubList cursor:", cursor);
        req = store.get(cursor.key);
        req.onsuccess = function (evt) {
          var value = evt.target.result;
            
         var list_item2 = $('<table width="80%"><tr><td><b><u>LFD. NR: '  + cursor.key + '</u></b></td><td></td><td></td><td></td><td></td></tr><tr><td><b>DATEN-ID:</b></td><td><b>HERSTELLER:</b></td><td><b>STÜCKZAHL:</b></td><td><b>KALIBER:</b></td><td><b>KURZNOTIZ:</b></td></tr><tr><td>' + value.biblioid + '</td><td>' + value.title + '</td><td>' + value.year + '</td><td>' + value.kaliber + '</td><td>' + value.notiz + '</td></tr></table>' ); 
            
           pub_list.append(list_item2); 
           
        };

        // Move on to the next object in store
          
        cursor.continue();

        // This counter serves only to create distinct ids
          
        i++;
      } else {
        console.log("Keine weiteren Einträge!");
      }
    };
  } 


Ich habe alle unnötigen DIV entfernt, auch den <div class="jumbotron">
Die Seite soll so besser für einen Ausdruck geeignet sein.

Ich probiere es mal mit deiner Anregung und melde mich wieder :)

Hiermit klappt es schon mal nicht:

$( window ).load(function() {
 displayPubList();
});

Und das hier auch nicht:



// book is a ID of a image in the html body.

$( "#book" ).load(function() {
 displayPubList();
});

Aber mit dem hier bekomme ich eine im Footer angelegten Demo-Text zwischen <p></p> beim Laden der Webseite geändert.

$(function() {
      
       $( "p" ).text( "Text geändert!" );

  });


PS: Später werde ich natürlich deinem Vorschlag folgen und alle Dateien so ändern, dass das Script im Header steht, bzw. besser noch, in einer eigenen externen Datei.

17.10.2016 09:25 | geändert: 17.10.2016 10:22

4 Jörg

    <!-- Placed at the end of the document so the pages load faster -->
    <script src="start-Dateien/jquery.js"></script>

Allerdings basieren die Scripte davor auf jquery! Ans Ende des Body kann man gut externe Scripte von anderen Domains einbauen, aber Bibliotheken, die von andern Scripten benötigt werden, sollten schon im Head-Bereich geladen werden.

17.10.2016 15:19 | geändert: 17.10.2016 15:20

5 Kokarde

Moinsen

Ja, die Datei im Footer ist in diesem Fall ein Relikt, da es zum Paket von Bootstrap gehört. Das können wir ignorieren. Da geht es ja nur um Bootstrap Design und Layout und ein paar Funktionen wie Button-Change etc.

Leider komme ich nicht weiter, wie in Beitrag 3 bereits angedeutet.

Ich habe mich mit den Tutorials von Raymond Camden befasst, doch das ist mir alles zu chaotisch, da passt hinten und vorne nix zusammen. Teilweise funzt es auch nicht.

Ich stehe im Moment vor 2 größeren Problemen.

1. ich möchte dass die Funktion auf "list.html" automatisch gleich ausgeführt wird, wenn die Webseite startet und nicht erst dann, wenn man auf den Button klickt. Alle Lösungsansätze sind bisher gescheitert.

view-source:http://www.hardwareplattform.de/web-index-db/list.html

2. wenn Problem 1 gelöst, brauche ich eine Update-Funktion, die ich bereits habe, aber leider nicht startet, wenn man auf den Button klickt.
Sie funktioniert aber, wenn ich die Funktion einem Button zuweise und im Code, der wie folgt aussieht, die Daten fest eintrage.

view-source:http://www.hardwareplattform.de/web-index-db/form_edit_munition.html



function updateResult() {
  var transaction = db.transaction(['Munitionsliste'], 'readwrite');
  var objectStore = transaction.objectStore('Munitionsliste');

  objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if(cursor) {
        
        
          /**
   * biblioid funktioniert nur bei festen Wert direkt im Skript :(
   */
    
        var biblioid = $('123456789').val();
        
                   /**
   * cursor selektiert die ID für den Datensatz der upgedatet werden soll
   */
      
      if(cursor.value.biblioid === biblioid) {
        var updateData = cursor.value;

                  /**
   * year funktioniert nur bei festen Wert direkt im Skript :(
   */
          var year = $('year').val();
          
          
                 /**
   * updateData.year funktioniert nur bei festen Wert direkt im Skript :(
   */
          
        updateData.year = "2016; 
    
        var request = cursor.update(updateData);
        request.onsuccess = function() {
          console.log('a new year - done!');
        };
      };

      
      cursor.continue();   
        
    } else {
      console.log('Entries displayed.');         
    }
  };
};


Doch erst mal Schritt 1 :)

Hast Du dafür eine Idee?

http://www.hardwareplattform.de/web-index-db/list.html

18.10.2016 10:01

6 Jörg

Nur kurz, da ich etwas in Eile bin :) - den Rest schau ich mir später an:

Ja, die Datei im Footer ist in diesem Fall ein Relikt, da es zum Paket von Bootstrap gehört. Das können wir ignorieren.

Du hast nicht nur die Bootstrap-Datei, sondern auch die Jquery-Datei im Footer eingebunden (siehe den von mir geposteten Codeabschnitt)! und letztere sollten wir bei der Problemanalyse besser nicht ignorieren, da die betreffenden Scripte z.T. auf jquery basieren.

Das z.B. ist jquery Syntax:

var search_button = $('#search-list-button');

18.10.2016 10:53

7 Kokarde

Danke, bloss kein Stress :))

Aha, dann werden hier im Code selbst, der in der HTML Datei ist, 2 Sprachen vermischt?

Ich dachte die angebunden Datei kann ignoriert werden, da die dortigen Abschnitte nur dann greifen, wenn ich in der HTML Datei jetzt etwas einem Button zuordne, was dort dann gefunden wird.

Habe aber vorsorglich nun die Datei auskommentiert!

18.10.2016 14:28

8 Jörg

OK, ich seh grad, du hattest jquery zweimal eingebunden, weiter oben schon von ajax.googleapis.com:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

Habe aber vorsorglich nun die Datei auskommentiert!

Ja, einmal reicht auch. Das ist übrigens auch ein Grund, warum ich die Scripte allesamt nacheinander im Head-Bereich unterbringen würde - sonst verliert man sehr schnell den Überblick, was wo eingebunden ist. Mit den Event Listenern ist es nicht mehr notwendig, JavaScript irgendwo in den HTML-Body reinzuschreiben, man hat dann eine saubere Trennung von JavaScript und HTML

[Rest wieder gelöscht, weil Unsinn]

18.10.2016 16:59 | geändert: 18.10.2016 18:56

9 Jörg

Mit welchem Browser hast du das Problem?

Diesen Listener hast du ja zur Zeit drin:

    var search_button = $('#search-list-button');
    search_button.click(function(evt) {
      displayPubList();
    }); 

Wenn ich in Chrome auf den Button klicke, wird der folgende Text angezeigt:

Derzeit 0 Einträge in der Liste.

Scheint dort also zu funktionieren!

Firebug zeigt dagegen diese Fehlermeldung in der Konsole an:

SecurityError: The operation is insecure.

var req = indexedDB.open(DB_NAME, DB_VERSION);

Kommen bei dir auch solche Fehlermeldungen in der Konsole, wenn du auf den Button klickst?


Edit:

Wenn ich eine Kopie der Seite auf meinem lokalen Webser aufrufe, dann gibt auch Firefox den Text "Derzeit 0 Einträge in der Liste." aus. Schon merkwürdig das ganze...

18.10.2016 18:14 | geändert: 18.10.2016 18:19

10 Jörg

So, jetzt aber :)

$(document).ready(function() {
  displayPubList();
});

Dies funktioniert nicht, weil zu dem Zeitpunkt das Objekt db noch nicht fertig ist - das zeigen auch die Konsolenmeldungen in Firebug an.

Alternativ könnte man so vorgehen:

    function waitForDb() {
        if (typeof db !== "undefined") {
            displayPubList();
        } else {
            setTimeout(function() {
                waitForDb();
            }, 100);
        }
    }

    openDb();
    addEventListeners();
    waitForDb();

In einer rekursiven setTimeout Schleife wird gewartet, bis db da ist, dann wird displayPubList() ausgeführt. Nicht besonders elegante Lösung, aber funktioniert zumindest bei mir lokal: die Meldung "Derzeit 0 Einträge in der Liste." wird direkt (d.h. ein paar 100 Millisekunden) nach dem Aufbau der Seite angezeigt

18.10.2016 18:52 | geändert: 18.10.2016 18:58