Avatar billede KHHP Juniormester
20. august 2012 - 14:30 Der er 30 kommentarer

AJAX til tjek om eksistens af brugernavn

Hej
Jeg er igang med at lave en side hvor der er login-mulighed og dertil hører der en mulighed for at oprette sig som bruger. Problemet er dog at på en sådan side dur det ikke at der findes flere brugere med samme brugernavn og det har jeg fikset ved at lade mig PHP-script tjekke om det eksisterer i forvejen. Læste så et par tutorials omkring AJAX her sidste dag og tænkte at jeg måske kunne drage nytte af dette. så brugerne slap for først at blive sendt til mit script, få tjekket om brugernavn findes og dernæst blive sendt til en side hvor de får besked om at brugernavnet allerede er i brug. Hvis jeg bruger AJAX kan jeg få den til at tjekke om brugernavnet eksisterer så snart brugeren forlader feltet hvor de skriver brugernavn. Det kan jeg også sagtens lave koden til, men vil det fungere på mit site, da jeg har login i en skjult div, som kan vises ved tryk på et link, via fancybox. Kan jeg godt have en div inde i min skjulte div, således at når jeg åbner min div med fancybox, skriver et brugernavn og så går videre til næste felt, så tjekker den om brugernavnet findes og så sender den svar tilbage, som vises med det samme(forbehold for et lille delay mens scriptet loades ind i siden)?
Avatar billede olebole Juniormester
20. august 2012 - 15:36 #1
<ole>

Den leteste løsning kræver du lægger en lille transparent gif (t.gif) på serveren:

<script type="text/javascript">
function showWarning() {
    alert("Navnet er allerede i anvendelse.")
}
function checkUser(sUserName) {
    var oIm = new Image();
    oIm.onerror = showWarning;
    oIm.src = "check_user.php?user="+encodeURIComponent(sUserName)+"&u="+new Date().getTime();
}

checkUser("olebole");
</script>

- og serverkoden:

<?php
if (!empty($_GET)) {
    // Check user in DB
   
    if ([USER_EXISTS]) {
        header('Status: 404 Not Found');
        exit();
    }
    header('Location: t.gif');
    exit();
}
?>

/mvh
</bole>
Avatar billede Panen Nybegynder
20. august 2012 - 15:38 #2
Det kan du sagtens.
Hvis du bruger jQuery kan du evt. lave en funktion der ser således ud:

function validateUsername(username){
  $.post("ditscript.php", {username: username},
    function(data) {
      alert("Returned data: " + data);
    }
  );
}

Så skifter du bare ditscript ud med stien til det script der tjekker om brugernavnet er ledigt, og det som der bliver echo'et i det script vil blive smidt tilbage og ind i variablen data i Javascript funktionen.

Så kalder du bare validateUsername("brugernavnher") når brugeren forlader feltet.
Avatar billede olebole Juniormester
20. august 2012 - 16:06 #3
#2: Men vi er vel enige om, at det ville være over-kill at bruge jQuery til den opgave, hvis ikke jQuery i forvejen er i brug på siden  =)
Avatar billede Panen Nybegynder
20. august 2012 - 16:11 #4
#3 Indeed, men eftersom han bruger Fancybox er chancerne ret store (:
Avatar billede olebole Juniormester
20. august 2012 - 16:21 #5
Sorry, det havde jeg overset  =)
Avatar billede KHHP Juniormester
20. august 2012 - 16:38 #6
Tak for jeres svar. Enig med olebole i at jeg ikke skal bruge jquery, hvis det ikke allerede bliver brugt. Dog benytter fancybox og diverse andre ting på siden jquery, så derfor ville det jo være muligt.
Lige nu ser min loginside således ud:
<div style="display: none;" id="logind">
<form name="login" action="user/auth.php" method="post">
    <h1>Log ind</h1>
    Brugernavn: <input type="text" name="username" /><br />
    Password: <input type="password" name="password" /><br />
    <input type="submit" name="submit" value="Log ind" class="btn" />
</form>
</div>

Hvis jeg vil kalde funktionen validateUsername, hvad skal jeg så skrive?
Det AJAX-script jeg ville bruge, ser således ud:
<script type="text/javascript">
function usercheck() {

if (window.XMLHttpRequest) {
    xmlhttp = new XMLHttpRequest();
}
else {
    xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}

xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readystate == 4 && xmlhttp.status == 200) {
        document.getElementById('check').innerHTML = xmlhttp.responseText;
    }
}

xmlhttp.open('GET', 'inc/usercheck.php?username='+document.login.username.value, true);
xmlhttp.send();

}
</script>

Så tilføjer jeg <div id="check"></div> lige efter feltet for brugernavn. Så ved brugeren med det samme at de ikke kan bruge det ønskede brugernavn.
Havde som sådan regnet med at det ville virke, men ville lige være helt sikker, det kunne jo være at man skulle gøre noget specielt for at den ville virke inde i fancybox.
Avatar billede KHHP Juniormester
20. august 2012 - 16:43 #7
Hovsa mente selvfølgelige min form til brugeroprettelse, den ser således ud:
<form name="bruger" action="user/user.php" method="post">
    <h1>Opret bruger</h1>
    Navn: <input type="text" name="navn" /><br />
    Brugernavn: <input type="text" name="username" /><br />
    Password: <input type="password" name="password" /><br />
    E-mail: <input type="text" name="epost" /><br />
    Adresse: <input type="text" name="vej" /><br />
    Postnr. og by: <input type="text" name="postby" /><br />
    <input type="submit" name="submit" value="Opret bruger" class="btn" />
</form>

Også selvom forskellen ikke er så stor.
Avatar billede olebole Juniormester
20. august 2012 - 17:05 #8
Generelt skal du være overordentlig forsigtig med innerHTML, som har nogle fatale bivirkninger, hvis du ikke har helt styr på, hvad den faktisk gør - og det har du overvejende sandsynligt ikke. Brug i stedet DOM, når du kan slippe afsted med det.

I den forbindelse er det også vigtigt at fremhæve det tåbelige i at HTML-formatere data på serveren og indsætte dem med innerHTML. Det er en skræmmende udbredt praksis, men det gør den ikke mindre tosset.

At HTML-formatere data på serveren tager mange gange den tid, det tager at XML- eller JSON-formatere dem - og bruger oceaner af unødige serverressourcer.

Hold dig til at formatere som XML eller JSON (til nød som ren tekst) og sæt data/elementer ind med DOM. Så koder du effektivt og undgår de værste 'fælder'  *o)
Avatar billede jokkejensen Novice
20. august 2012 - 17:20 #9
Hvis vi antager at inc/usercheck.php?username=XXXX svarer "optaget" ellers intet i ren text/plain mime.

$("input[name=username]").keypress(function(){

if($(this).val().length > 3)
{

$.ajax({
  url: 'inc/usercheck.php?username='+encodeURIComponent($("input[name=username]").val(),
  success: function(data) {
      if(data == 'optaget')
      {
          $("#username").text("Optaget")
      }else
      {
          $("#username").text("Frit")
      }
  },statusCode: {
    404: function() {
      alert("page not found");
    }
  }, error :function ()
{
alert("fejl i kaldet")
}

}
});
});


<div id="username">
</div>

Der mangler nok et par paranteser :)
Avatar billede Panen Nybegynder
20. august 2012 - 17:33 #10
Det ajax-script du viser i #6 benytter ikke jQuery :)

Kig på denne simple ajax funktion som benytter sig af jQuery.

<code>
<script>
$.get("test.php", function(data){
  alert(data);
});
</script>
</code>

Og lad os så sige du har en test.php som kun indeholder
<code>
Hello World!
</code>

Smider du det første javascript i en html fil og besøger den i din browser, vil javascriptet forrespørge din test.php fil som returnerer "Hello World!", for derefter at vise en alert med det.
Avatar billede Panen Nybegynder
20. august 2012 - 17:34 #11
Og jeg har ikke fået lært det BBCode endnu ^^
Avatar billede olebole Juniormester
20. august 2012 - 17:44 #12
#9: Jeg tror nu nok, jeg ville lægge koden på onchange i stedet. Validering virker sjældent ret brugervenlig, når den køres realtime - mens der skrives  =)
Avatar billede jokkejensen Novice
20. august 2012 - 18:16 #13
onchange ? afvikles først onblur() altså når du forlader det - Med undtagelse for radio, select og textarea, til input type=text vil jeg altid holde mig til keypress?


Jeg ville blive irriteret over først at få svaret efter jeg forlader feltet.. og sådan vil scenariet se ud med jquery's change på et input[text].

Alternativ skulle man flytte fokus til #username, hvis det allerede er optaget.

Skulle jeg lave det ville jeg benytte en jquery autocomplete, skjule lortet, og tælle antal forekomster, herved drager jeg endnu mere udnyttelse af jquery, når det nu alligevel er smidt på. Så sikre den at brugeren ikke skriver 10 tegn i sekundet samt tager sig af alle de andre problemer man kunne løbe ind i.
Avatar billede olebole Juniormester
20. august 2012 - 21:23 #14
Jokke, jeg har stor respekt for, at du føler anderledes for dette end flertallet, men det er næppe din brugertype, jeg ville designe efter  =)

Hvis du tester brugere med eye- og mousetracking - evt. støttet af videoovervågning og efterfølgende interview - viser det sig ikke altid at fungere særlig godt.

Der findes en udmærket AListApart artikel, som meget godt passer på de erfaringer, jeg har set gjort i de firmaer, jeg har arbejdet. Specielt det ene var nærmest 'hysterisk' med hensyn til tæt overvågede brugertest, og det var faktisk overordentlig lærerigt at se, hvor ofte grafiske designere og frontend udviklere tog fejl i, hvad der er mest brugervenligt  =)
Avatar billede KHHP Juniormester
21. august 2012 - 16:25 #15
Nu har jeg fået kigget de forskellige løsningsforslag igennem og samtidig fået testet det jeg selv havde foreslået, som så ikke lige viste sig at virke, også selvom jeg burde have gjort tingene rigtigt. Jeg prøvede endda, eftersom at onchange og onblur ikke ville vise noget, at benytte onkeyup i stedet, fordi så skulle den jo vise det når jeg har trykket på en tast, men jeg får hverken be- eller afkræftet om brugernavnet findes i systemet.
Mit usercheck.php script virker fint. Tjekkede endda for en sikkerheds skyld at den del virkede, så derfor forsøgte jeg at gå til filen via min browser og skrive ?username=webmaster efter filnavnet, så havde jeg jo min $_GET['username']. Og brugeren webmaster eksisterer i systemet, og ganske rigtigt, så får jeg også at vide at brugeren allerede findes.  udskifter jeg username med khhp i stedet for webmaster, som ikke findes i db, så siger den at brugernavnet kan bruges.
Blot for god ordens skyld, så kunne det jo være at der er et eller andet med mit php-script der gør at jeg ikke kan få output via AJAX, så I får lige koden her(og ved godt at det stadig bruger MySQL-API, men det er en af de få sider jeg ikke har fået konverteret til MySQLi endnu):
<?php
include '../includes/connect.php';
$bruger = $_GET['username'];
$tjek = mysql_query("SELECT * FROM users WHERE username='$bruger'");
if ($kontrol = mysql_num_rows($tjek) !=0) {
    echo 'Det valgte brugernavn er desværre allerede i brug. Vælg venligst et andet.';
}
else {
    echo 'Brugernavnet er ok.';
}
?>
Avatar billede olebole Juniormester
21. august 2012 - 16:49 #16
Din PHP-kode ser rigtig ud - og som du siger, fungerer den fint - så du må jo lave en eller anden fejl et sted i din frontend kode. Prøv at vise, hvad du præcist har prøvet med  =)
Avatar billede olebole Juniormester
21. august 2012 - 16:54 #17
PS: Koden i #6 må du ikke forveksle med Ajax. Det er en skidt og misforstået kode, som du har kopieret fra en, der ikke kan skrive JavaScript - og tydeligvis ikke har opnået dybere forståelse af browseres virkemåde. Undlad at spilde tid med den  =)
Avatar billede KHHP Juniormester
21. august 2012 - 17:20 #18
Først indsatte jeg dette:
<input type="text" name="username" onchange="usercheck();" />
<div id="check"></div>

Så forsøgte jeg med:
<input type="text" name="username" onblur="usercheck();" />
<div id="check"></div>

Og da ingen af delene virkede, så forsøgte jeg:
<input type="text" name="username" onkeyup="usercheck();" />
<div id="check"></div>

Filen til login er indsat med php include, fordi den skal bruges over flere filer og derfor er det jo smart at gøre det på den måde.
Mit "AJAX"-script er indsat lige ovenover den formular med brugeroprettelse:
SCRIPT
FORM

Oprindelsen af det frontend-script var egentlig et forsøg på at vise hvordan google's auto suggestions fungerer, og det var jo næsten det samme jeg skulle bruge og derfor kunne jeg med relativt få rettelser, såsom stien til mit php-script og navnet på funktionen.
Avatar billede olebole Juniormester
21. august 2012 - 17:30 #19
Ja, det er nogle INPUT elementer, men hvordan ser din JS-kode ud?

Har du prøvet at lave et fuldstændig 'nøgent' script, hvor det kun er denne funktion, du tester - helt barberet og uden includes? Jo flere muligheder for fejl, der er, jo vanskeligere er det for dig at finde en fejl
Avatar billede KHHP Juniormester
21. august 2012 - 17:58 #20
Det er den eneste funktion jeg har, alt andet ligger i separate js-filer.
De stylesheets og js-filer jeg har inkluderet i head er disse:
<link rel="stylesheet" href="style/style.css" type="text/css" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
        <link rel="stylesheet" href="style/bootstrap.css" type="text/css" />
        <script type="text/javascript" src="js/bootstrap.js"></script>
        <link rel="stylesheet" href="js/fancybox/jquery.fancybox.css?v=2.1.0" type="text/css" media="screen" />
        <script type="text/javascript" src="js/fancybox/jquery.fancybox.pack.js?v=2.1.0"></script>
        <script type="text/javascript" src="js/js_settings.js"></script>

Og filen js_settings.js indeholder blot indstillinger/parametre til fancybox og den ser således ud:
<link rel="stylesheet" href="style/style.css" type="text/css" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
        <link rel="stylesheet" href="style/bootstrap.css" type="text/css" />
        <script type="text/javascript" src="js/bootstrap.js"></script>
        <link rel="stylesheet" href="js/fancybox/jquery.fancybox.css?v=2.1.0" type="text/css" media="screen" />
        <script type="text/javascript" src="js/fancybox/jquery.fancybox.pack.js?v=2.1.0"></script>
        <script type="text/javascript" src="js/js_settings.js"></script>

Lidt længere nede på siden bruger jeg <?php include 'inc/login.php'; ?> til at indsætte login og brugeroprettelse. Det er bare frontend-scriptet og så de to forms jeg postede i #6 & #7.
Det er som sådan det eneste jeg ikke indsætter med php.
Avatar billede KHHP Juniormester
21. august 2012 - 17:59 #21
Hovsa glemte at copy/paste indholdet af js_settings.js, så den får du lige her:
$(document).ready(function() {
    $(".various").fancybox({
        maxWidth    : 800,
        maxHeight    : 600,
        fitToView    : false,
        width        : '70%',
        height        : '70%',
        autoSize    : false,
        closeClick    : false,
        openEffect    : 'elastic',
        closeEffect    : 'elastic'
    });
});
Avatar billede olebole Juniormester
21. august 2012 - 18:24 #22
Hold da op ... det er tungt det her! Hvordan ser den kode ud, som foretager forespøgslen til serveren?
Avatar billede KHHP Juniormester
21. august 2012 - 18:51 #23
Altså min php-kode som kører en forespørgsel til mysql-serveren for at finde ud af om brugernavnet findes eller ikke findes?
Hvis ja, så kig i #15, der har jeg allerede postet koden.
Avatar billede olebole Juniormester
21. august 2012 - 19:24 #24
Nej, det er JavaScript koden, som sender forespørgslen til serveren, jeg efterlyser. Der har været givet flere forslag i tråden, så ingen kan vide, hvad det er, du forsøger dig med
Avatar billede KHHP Juniormester
21. august 2012 - 19:49 #25
Har ikke forsøgt nogle af forslagene endnu, fordi det kunne jo være at jeg kunne lære noget ved at få den "uduelige" kode, jeg selv foreslog, til at virke. Men kan da godt prøve med en af de forslag der er givet og så vende tilbage når jeg har forsøgt.
Avatar billede KHHP Juniormester
22. august 2012 - 15:34 #26
Ok. Nu har jeg forsøgt at lave en helt clean fil, hvor jeg så forsøger at tjekke brugernavnet med et af de andre scripts. Og med det fra #10 skulle jeg jo få en alert-box med resultatet i, men intet sker. Prøvede så at indsætte den fra #9, men min editor laver rigtig mange sorte streger, i form af syntax errors. Prøvede dernæst at genopbygge hans script ved at tage linjerne en efter en og indsætte alle if/else-statements og funktioner, og så lave parenteser og {} selv, for at være sikker på at der var nok, men fik ikke udryddet de syntax-errors.
Avatar billede jokkejensen Novice
22. august 2012 - 15:58 #27
Så er syntaxen i orden, men drop mit forslag hvis javascript syntax kan drille:

$("input[name=username]").keypress(function () {

    if ($(this).val().length > 3) {

        $.ajax({
            url: 'inc/usercheck.php?username=' + encodeURIComponent($("input[name=username]").val()),
            success: function (data) {
                if (data == 'optaget') {
                    $("#username").text("Optaget");
                } else {
                    $("#username").text("Frit");
                }
            },
            statusCode: {
                404: function () {
                    alert("page not found");
                }
            },
            error: function () {
                alert("fejl i kaldet");
            }
        });
    }
});
Avatar billede KHHP Juniormester
22. august 2012 - 16:13 #28
@jokke: Det gav heller ikke noget, men den skal jo have værdien af data retur fra php, men det er jo ikke noget den får. Jeg beder php om at echo resultatet ud:
<?php
include '../includes/connect.php';
$bruger = $_GET['username'];
$tjek = mysql_query("SELECT * FROM users WHERE username='$bruger'");
if ($kontrol = mysql_num_rows($tjek) !=0) {
    echo 'Det valgte brugernavn er desværre allerede i brug. Vælg venligst et andet.';
}
else {
    echo 'Brugernavnet er ok.';
}
?>

Men jeg skal vel have et eller andet onchange/onblur for at kalde funktionen, eller tjekker den selv automatisk(hvilket jeg tolker det som om den gør)? Lige nu ser feltet til brugernavn således ud:
Brugernavn: <input type="text" name="username" onchange="usercheck();"/><br />

Der er jo noget der, et eller andet sted, går galt, fordi når jeg har en helt ren test-fil, så burde der ikke være noget der kan forvirre den.
Jeg har i min test-fil husket at linke til jquery og her kan jeg få den fra #10 til at virke, men den tjekker når siden loades og så er der ingen værdi i mit felt.
Avatar billede olebole Juniormester
22. august 2012 - 16:57 #29
Hvad i alverden har du dog gang i? 25(!) indlæg uden at prøve et eneste af de forslag, du er blevet givet!

Hvorfor kommer jeg mon her i tanker om min gamle delingsførers yndlingsreplik: "Er du dum - fræk - eller begge dele?"
Avatar billede jokkejensen Novice
23. august 2012 - 12:11 #30
Ad #9 "Hvis vi antager at inc/usercheck.php?username=XXXX svarer "optaget" ellers intet i ren text/plain mime. "

Og så vælger du at returnere:

echo 'Det valgte brugernavn er desværre allerede i brug. Vælg venligst et andet.';

eller

echo 'Brugernavnet er ok.';

Jeg siger heller ikke at mit eksempel vil virke 100%, det var blot inspiration.

- Jeg er ude
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester