Zielstellung

Bei der Registrierung im Shop VirtueMart (Relevanz geprüft bis Version 1.1.4) findet die Prüfung des Wunsch-Usernamens immer erst nach dem Absenden des Formulars statt. Das kann mitunter etwas nervig werden, weshalb schon bei der Eingabe des Wunsch-Usernamens eine Prüfung stattfinden soll, ob dieser noch verfügbar ist. Gleichzeit soll auch eine Anzeige erfolgen, die Auskunft gibt über die Anzahl der notw. Zeichen die noch einzugeben sind. Im konkreten Fall 3.

Umsetzung im Detail

Um in Echtzeit die Eingabeereignisse abzufragen soll die jQuery-Bibliothek verwendet werden, was allerdings nicht zwingend notw. wäre, es könnte auch über getElementById() gearbeitet werden. Die Prüfung selbst findet selbstverständlich per Ajax-Funktion statt. Hierfür ist also ein JavaScript erforderlich, welches in das Registrierungsformular dem Wunschbenutzerfeld folgend integriert wird. Da die Statusausgaben neben dem Eingabefeld und noch weiter rechts neben dem ToolTip-Icon platziert werden soll, ist es sinnvoll im Script ps_userfield.php, welches für die Ausgabe des Formulars verantwortlich ist, diese im Umfeld der ToolTip-Ausgabe zu platzieren.



Konkret wird ca. Zeile 575 folgendes ergänzt:

ps_userfield.php
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
 if( $field->description != '' ) {
 if ( $my->id != 0 && $field->name == "vm_kdnr" ) {} else { // Marks-Spezifisch Nicht wenn User-angemeldet für das Feld KdNr.
 echo ($field->readonly == 1 || $page == "admin.user_form") ? "" : vmToolTip( $field->description ) ; // Marks-Spezifisch, Tooltip nur wenn nicht readonly-Feld,
 }
 }
 if ($field->name == "vm_wishusername") :
 ?><div id="validusername"></div>
<style type="text/css">
/* Styles für username-Instant-Check */
#validusername { position:absolute; left:150px; top:0; line-height:20px; }
#checkattention, #checkokay { height:24px; padding-left: 30px; }
#checkattention { color: #d00; background: url(/images/M_images/check_attention.png) no-repeat left; }
#checkokay { background: url(/images/M_images/check_okay.png) no-repeat left; }
</style>
 
<script type="text/javascript">//<![CDATA[
// Script für UserName-Instant-Check
jQuery(document).ready(function() {
 jQuery("#vm_wishusername_field").focus();
 jQuery("#vm_wishusername_field").attr('autocomplete', 'off').keyup(function(event) {
 var name = jQuery("#vm_wishusername_field").val();
 // Prevent invalid keyboard inputs.
 // Keys with codes 40 and below are special
 // (enter, arrow keys, escape, etc.).
 // Keys with codes 91 and above are special
 // (NUM LOCK, window keys, etc.).
 // Key code 8 is backspace.
 // Key code 13 is enter.
 // Key code 20 is CAPS LOCK.
 // Key code 16 is SHIFT.
 // Key code 9 is TAB.
 // Key code 37 is LEFT key.
 // Key code 38 is UP key.
 // Key code 39 is WRITE key.
 // Key code 40 is DOWN key.
 if(event.keyCode > 40 || event.keyCode < 91 || event.keyCode == 8 || event.keyCode == 13 || 
 event.keyCode == 20 || event.keyCode == 16 || event.keyCode == 9 || 
 event.keyCode == 37 || event.keyCode == 38 || event.keyCode == 39 || 
 event.keyCode == 40)
 {
 jQuery("#validusername").empty();
 var chars = name.length;
 if(chars > 2 ) {
 jQuery("#validusername").html('<img align="absmiddle" src="/images/loadingcircle.gif" /> Pr&uuml;fen Verf&uuml;gbarkeit...').show();
 jQuery.ajax({
 type: "POST",
 url: "index2.php?page=checkout.index&option=com_virtuemart&Itemid=91",
 data: "checkUsername="+ name,
 success: function(msg) { 
 msg = msg.replace(/vmMainPage/,'');
 jQuery("#validusername").html(msg).show(); }
 });
 } else {
 var rest = 3 - chars;
 jQuery("#validusername").html('noch wenigstens '+rest+' Zeichen').show();
 }
 } else {
 jQuery("#validusername").html('Unzul&auml;ssiges Zeichen!').addClass('err').show();
 }
 });
});
//]]</script>
 

Anmerkung: Es wurden hier die Textausgaben nicht über die Sprachdatei eingebunden, sondern hart kodiert. Einfach aus Bequemlichkeit.

Hier kurze Erläuterung dieser Sequenz:

Wenn im Durchlauf der Felder das Wunschusername-Feld dran ist zunächst ein zusätzlicher DIV-Block mit id=validusername ausgegeben, der die folgenden Statusmeldungen erhalten soll. Dann wird ein kurzer Style-Block ausgeben, der die Anzeige der Statusinfos gefällig formatiert und der genannte Java-Script-Block.

Bei jeder Eingabe, wenn das Feld den Focus hat, wird zunächst geprüft, ob dies ein zulässiges Zeichen ist – es findet also zusätzlich auch gleich eine Validierung der Eingabezeichen statt. Die Serverabfrage findet nur statt, wenn die Länge der Eingabe im Feld drei Zeichen übersteigt. Solange das nicht zutrifft, wird dem user als Status angezeigt, wie viele Zeichen er noch mind. eingeben muss.

Ist die Mindestzeichenzahl erreicht, wird der String per Ajax-Funktion als Post-Parameter checkUsername an den Server gesendet. Dabei wird das auch sonst für dieses Formular verantwortliche checkout.index.php-Script referenziert durch den Request-URL index2.php?page=checkout.index&option=com_virtuemart&Itemid=91.

Emfangen wird der Status-Inhalttext in der Variablen msg. Leider gibt VirtueMart durch die Nutzung dieses Scriptes in der Meldung auch den DIV-Block mit der id=" vmMainPage" aus. Den gäbe es dann zweimal auf der Seite, was Konfliktpotential hat. Deshalb wird dieser Selector aus dem msg-String herausgelöscht. Dies serverseitig zu machen wäre aufwändiger. Die Statusmeldung wird dann im dafür vorgehaltenen Kontainer validusername ausgeben.

Soweit die clientseitige Umsetzung.

Um Namensraum-Konflikte mit den auch verwendeten MooTools zu vermeiden wurde der ausführliche Name für jQuery statt des $ verwendet.

Hier eine kurze Aufstellung der gefilterten Zeichen und ihrer Bedeutung:

  •   // Keys with codes 40 and below are special
  •   // (enter, arrow keys, escape, etc.).
  •   // Keys with codes 91 and above are special
  •   // (NUM LOCK, window keys, etc.).
  •   // Key code 8 is backspace.
  •   // Key code 13 is enter.
  •   // Key code 20 is CAPS LOCK.
  •   // Key code 16 is SHIFT.
  •   // Key code 9 is TAB.
  •   // Key code 37 is LEFT key.
  •   // Key code 38 is UP key.
  •   // Key code 39 is WRITE key.
  •   // Key code 40 is DOWN key.

Serverseitig wurde diese Prüf-Funktion in das Script checkout.index.php implementiert, weil dieses ja auch so schon für die Behandlung des Registrierungsformular verantw. ist. Es wurde aus Sicherheitsgründen kein Standalone-Script verwendet, sondern das J!- und VM-Framework verwendet.

Nachfolgender Block wird in dieses Script ganz oben eingefügt:

checkout.index.php
10
11
12
13
14
15
16
17
18
19
20
21
22
$checkUserName = $vmInputFilter->safeSQL((string)vmGet( $_REQUEST, 'checkUsername'));
if ( !empty($checkUserName) ) {
 $db = new ps_DB;
 $query = "SELECT `username` FROM `#__users` WHERE `username`='$checkUserName'";
 $db->query($query); 
 $db->next_record();
 
 $msg = ( $db->num_rows() )
 ? '<div id="checkattention">Der Benutzername <b>'.$checkUserName.'</b> ist schon vergeben.</div>'
 : '<div id="checkokay"><b>'.$checkUserName.'</b> ist noch verfügbar.</div>';
 die( $msg );
}
 

 

Kurz kommentiert:

Es wird der Post-Parameter checkUsername SQL-injection-sicher ausgelesen. Nur wenn dieser Parameter nicht leer ist, findet die Prüfung statt. Es wird ganz einfach geschaut, ob es einen Datensatz mit diesem Usernamen schon in der jos_users gibt und fallabhängig der Meldungstext ausgegeben. Die Übergabe an den Browser erfolgt hier mit die(), weil das Script dann sofort beendet werden soll, wenn die Prüfung stattgefunden hat.

 

Quellenhinweis: Die hier für VirtueMart realisierte Umsetzung basiert auf der Beschreibung von Arvind Bhardwaj.

color: #666666; font-style: italic;||span style=gt; Prcolor: #009900;color: #0000ff;span style=