Christoph Zurnieden: Lösungsansatz ohne Pferd

Beitrag lesen

Hi,

... weil man ja sonst nix besseres zu tun hat ... ;-)

Ummodeln der o.a. Opengeodb-Postleitzahlenliste in ein JS-Array (Liebe Perl-Gurus: bitte nicht gleich wieder hauen! ;-):

  
#!/usr/bin/perl -w  
  
use strict;  
  
my $opengeodb = "opengeodb-0.2.3e-UTF8-text-plz.txt"; #$ARGV[0];  
my $jsarray   = "opengeodb-js-array.js"; #$ARGV[1];  
  
my @line;  
my $out;  
my %entries;  
  
my $zip  = "";  
my $city = "";  
  
my $i = 0;  
  
open OPENGEODB, "< $opengeodb" || die "can't open $opengeodb";  
open JSARRAY,   "> $jsarray"   || die "can't open $jsarray";  
  
keys %hash = 8000; # alloziert 8192 Plätze für 8181 Plz.  
  
print JSARRAY "plz = new Array(\n";  
  
while(<OPENGEODB>){  
  next if $_ =~ /^\x23/;  
  
  @line = split(/;/,$_);  
  
  $zip  = $line[9];  
  $zip =~ s/[\n\r]//;  
  
  $city = $line[6];  
  
  $entries{$zip} = $city;  
  
}  
close OPENGEODB;  
  
foreach $out (sort(keys %entries)) {  
  print JSARRAY '["', $entries{$out}, '","', $out, '"],',"\n";  
}  
print JSARRAY '["",""]);';  
close JSARRAY;  

Kurzes Beispiel zur Nutzung (Liebe Javascript-Gurus: betreffs der Prügelfrage bitte ich euch an die Perl-Gurus zu wenden.):

  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
<head>  
<meta http-equiv="content-type" content="text/html; charset=UTF-8">  
<title>Die leidigen Postleitzahlen</title>  
<!-- Das Array heißt "plz" -->  
<script type="text/javascript" src="plz-array.js"></script>  
<script type="text/javascript">  
  
function binarySearch( needle, haystack){  
  var low    = 0;  
  var high   = haystack.length - 1;  
  var middle = 0;  
  var round  = 0;  
  while(low <= high){  
    round++;  
    middle = Math.floor((low + high)/2);  
    if(needle < haystack[middle][1])  
      high = middle - 1;  
    else if (needle > haystack[middle][1])  
      low = middle + 1;  
    else  
       return middle;  
  }  
  return -1;  
}  
  
function linearSearchExactFirst(needle, haystack){  
  
  var len  = haystack.length -1;  
  
  while(len--){  
    if (needle == haystack[len]){  
      return len;  
    }  
  }  
  return -1;  
}  
  
function linearSearchRegex(needle, haystack){  
  var len   = haystack.length -1;  
  var regex = new RegExp(needle);  
  var ret   = new Array();  
  var i     = 0;  
  
  while(len--){  
    if (regex.test(haystack[len][0])){  
       ret[i++] = haystack[len][0];  
     }  
   }  
  if(ret.length > 0){  
    return ret;  
  }  
  return -1;  
}  
  
  
function searchPLZ(entry){  
  
  var inpCity = document.forms[0].city;  
  /*  
    Eigentlich ist es ja heilige Pflicht nur das  
    zu nehmen, was man benötigt und nicht das  
    wegzuschmeisen, was man _nicht_ benötigt.  
    Soll im Produktionscode geändert werden?  
    Ach, wird doch eh nie!  
  */  
  entry = entry.value.replace(/[^0-9]*/g,"");  
  
  /* PLZ suchen */  
  if(entry.length != 5 && inpCity.value.length > 2){  
    /*  
      Aufgrund der Unsortiertheit der Ortsnamen  
      wäre es wohl besser diese Suche getrennt  
      durchzuführen. Evt sogar auf dem Server.  
      Für Experimentierfreudige trotzdem mal der  
      (ungeprüfte!) Code:  
    */  
    /*  
      Um die Sache zumindest etwas zu beschleunigen  
      wurde oben die Mindestlänge des Ortsnamenanfanges  
      auf drei festgelegt.  
      Für soviele und auch jeden weiteren Buchstaben  
      wird das ganze Array durchsucht und das Ergebnis in  
      einem weiterem Array festgehalten. Ist das Ergebnis-  
      array leer wurde nichts gefunden, ansonsten wird  
      eine Auswahliste gefüllt.  
    */  
    /*  
      linearSearchRegex() ist der Einfachheit halber  
      mittels eines Regex implementiert, wie auch der  
      Name schon anzudeuten versucht. Es wäre also  
      evt der Geschwindigkeit zuträglich vorher ein  
      wenig zu filtern.  
    */  
    /*  
      var ret =  linearSearchRegex(inpCity.value, plz);  
      if(typeof(ret) != "number" ){  
    */  
    /*  
      document.forms[0].city sei bereits eine Auswahlliste.  
      Die Auswahlliste wird bei jedem Aufruf von searchPLZ()  
      neu überschrieben.  
     */  
    /*  
      for(var i=0; i< ret.length;i++){  
        var newEntry = new Option(ret[i],ret[i],false,false);  
        inpCity.options[i] = newEntry;  
      }  
     */  
    /*  
       Code den Klick in die Auswahliste auszwerten ist  
       in dieser Datei nicht enthalten.  
     */  
    /*}  
      else{  
        return false;  
      }  
    */  
    return false;  
  
  }  
  /* Ort suchen */  
  else{  
    if(entry.length == 5){  
      // ermöglicht Korrektur der Plz.  
      inpCity.value = "";  
  
      /* Hier wird jeweils nur der exakte Wert  
         gesucht. Es kann aber auch mittels  
  linearSearchRegex() ein Array gefüllt werden  
  das ähnlich der Beschreibung bei "PLZ suchen"  
  ausgegeben wird.  
       */  
      var tmp = binarySearch(entry,plz);  
      if(tmp >= 0){  
        inpCity.value = plz[tmp][0];  
 return true;  
      }  
      else{  
        /* Aussagekräftige Fehlermeldung wäre  
    natürlich erheblich günstiger.  
  */  
        return false;  
      }  
    }  
    else {  
      /* Wenn das PLZ-Array auf mehrere Dateien  
         aufgeteilt ist, kann hier das Laden erfolgen.  
       */  
      return false;  
    }  
  }  
}  
  
function formSubmit(f,s,z,c){  
  alert(  "Es wurde \"submitiert\":\n"  
         + ((f.length > 0)?f:"kein Eintrag") + "\n"  
  + ((s.length > 0)?f:"kein Eintrag") + "\n"  
  + ((z.length > 0)?f:"kein Eintrag") + " "  
  + ((c.length > 0)?f:"kein Eintrag") + "\n");  
}  
  
</script>  
</head>  
<style type="text/css">  
fieldset{  
         padding: 1em;  
         margin-top: 1em;  
  width:25em;  
  border: 1px solid black;  
        }  
legend  {  
         border: 1px solid black;  
  color: black;  
  background-color:#c0c0c0;  
        }  
</style>  
<body>  
<h1>Automatische Postleitzahlensuche</h1>  
<form id="plzformular"  
      name="plzformular"  
      -- action="pfad/zum/bearbeitungscode" --  
      onsubmit="formSubmit();return false" >  
<fieldset><legend>Adresse</legend>  
Name<br>  
<input name="fullname"  
       id="fullname"  
       type="text"  
       size="50"  
       maxlength="50" /><br>  
Strasse<br>  
<input name="streetname"  
       id="streetname"  
       type="text"  
       size="50"  
       maxlength="50" /><br>  
Postleitzahl/Ort<br>  
<input name="zip"  
       id="zip"  
       type="text"  
       size="5"  
       maxlength="5"  
       onkeyup="searchPLZ(this);" />  
<input name="city"  
       id="city"  
       type="text"  
       size="40"  
       maxlength="40" />  
</fieldset>  
<fieldset><legend>Daten absenden</legend>  
<input name="sendbutton"  
       id="sendbutton"  
       type="button"  
       value="Abschicken"  
       onclick="formSubmit(this.form.fullname.value,  
                           this.form.streetname.value,  
      this.form.zip.value,  
      this.form.city.value);"/>  
<input name="resetbutton"  
       id="resetbutton"  
       type="button"  
       value="Zur&uuml;cksetzen"  
       onclick="this.form.reset()"/><br>  
</fieldset>  
</form>  
</body>  
</html>  

Ajax:
Von Pallas Athene mit Wahnsinn belegt nahm er sich das Leben.

Ist das jetzt ein unpassender Name für das Zeug um XMLHttpRequest()? Nein, ich finde nicht >;->

so short

Christoph Zurnieden