Skip to content

Instantly share code, notes, and snippets.

@andreasmischke
Last active October 30, 2016 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreasmischke/07979657d28617de07e9817f9b77714f to your computer and use it in GitHub Desktop.
Save andreasmischke/07979657d28617de07e9817f9b77714f to your computer and use it in GitHub Desktop.

Badgers Mayor Javascript

Problem

Die vielen 'undefined' kommen daher, dass die <script> Tags die überall verteilt sind, dann ausgeführt werden, wenn sie im HTML auftauchen. D.h. bei den meisten Aufrufen sind noch gar nicht alle <span>-Tags geladen, die dann mit Usernames befüllt werden sollen.

Außerdem sollte man die vielen einzelnen <script>-Tags vermeiden, und das ganze möglichst bündeln.

Verbesserungsvorschlag

Besser wäre es, alle Ersetzungen in einem einzigen Funktionsaufruf abzuarbeiten und zwar dann, wenn das HTML fertig geladen wurde. Dazu gibt es ein Event 'document.ready', auf das man so reagiert:

$(document).ready(function() {
  // <... code ...>
});

Die Funktion bzw. die JS-Datei mit der Funktion sollte dann im <head>-Bereich der Seite eingebunden werden.

Um alle <span>-Tags auf einmal abzuarbeiten, kann man z.B. dieselbe (CSS-)Klasse für alle verwenden, z.B. <span class="username"></span>. Dann muss natürlich noch die User-ID irgendwo hinterlegt werden, die bisher in den Klassennamen codiert war. Da das ja eigentlich Nutzdaten sind, bietet sich dafür ein eigenes Tag an. Man kann in HTML (offiziell ab HTML5, funktioniert aber auch mit älteren Browsern) data-* Tags verwenden, mit beliebigen selbstdefinierten Namen statt dem *. Damit würde aus bisher <span class="user_10000000007"><script>...</script></span> in Zukunft <span class="username" data-userid="10000000007"></span>

In der alles-auf-einmal-Funktion kann man dann schön alle Elemente auf einmal selektieren und die Namen laden:

$(document).ready(function() {
  $('.username').each(function() {
    var $span = $(this);
    var username = load_username($span, $span.data('userid'));
  });
});

Als nächstes müssen wir noch die Funktion load_username(span, userid) definieren:

var load_username = function($span, userid) {
  $.post('/_app/userName.php',
    {
      id: userid
    },
    function (data) {
      var username = data[0];
      $span.text(username);
    });
  }
}

Ganz wichtig ist noch das Caching, damit jeder Username nur einmal beim Server abgerufen wird:

var cache = {};                              // Objekt als Cache, Schlüssel userid und Wert username
var load_username = function($span, userid) {
  if(userid in cache) {                      // Fall 1:  userid ist schon im Cache
    if("string" == typeof cache[userid]) {   // Fall 1A: Der Cache-Eintrag ist ein String, dann ist das der 
                                             //          Username
      $span.text(cache[userid]);
    } else {                                 // Fall 1B: Der Cache-Eintrag ist ein Array, dann sind da noch
                                             //          alle $span-Elemente drin, die auf eine Antwort für 
                                             //          diese User-ID warten. Der aktuelle $span wird 
                                             //          "hinten angestellt"
      cache[userid].push($span);
    }
  } else {                                   // Fall 2:  Wir haben noch keinen Cache-Eintrag für die userid
    cache[userid] = [$span];                 //          Dann lege eine Warteschlange (ein Array) an und
                                             //          stell dich hinten an
    $.post('/_app/userName.php',
    {
      id: userid
    },
    function (data) {
      var username = data[0];
      cache[userid].forEach(function($span) { // Gehe durch das Warteschlangen-Array...
        $span.text(username);                 // ...und setze bei jedem $span den Username als Inhalt
      });
      cache[userid] = username;               // Setze den Username als Cache-Eintrag, damit sich kein 
                                              // $span mehr "anstellt", sondern den Username bekommt.
    });
  }
}
$(document).ready(function() {
  $('.username').each(function() {
    var $span = $(this);
    var username = load_username($span, $span.data('userid'));
  });
});

Zusammenfassung

HTML bisher:

<span class="user_10000000013"><script>document.write(Application.userName(10000000013))</script></span>

Neues HTML:

<span class="user" data-userid="10000000013"></span>

Neues Javascript:

var cache = {};
var load_username = function(span, userid) {
  if(userid in cache) {
    span.textContent = cache[userid];
  } else {
    var request = new XMLHttpRequest();
    request.open('POST', '/_app/userName.php', true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.onload = function() {
      var username = JSON.parse(request.response)[0];
      cache[userid] = username;
var cache = {};
var load_username = function($span, userid) {
  if(userid in cache) {
    if("string" == typeof cache[userid]) {
      $span.text(cache[userid]);
    } else {
      cache[userid].push($span);
    }
  } else {
    cache[userid] = [$span];
    $.post('/_app/userName.php',
    {
      id: userid
    },
    function (data) {
      var username = data[0];
      cache[userid].forEach(function($span) {
        $span.text(username);
      });
      cache[userid] = username;
    });
  }
}
$(document).ready(function() {
  $('.username').each(function() {
    var $span = $(this);
    var username = load_username($span, $span.data('userid'));
  });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment