Sitat av
RubiksRune
Jeg spør egentlig bare på grunn av nysgjerrighet, jeg kommer nok til å bruke iframes løsningen uansett da den er så å si klar. Men hadde vært greit å fått det til å fungere så kan jeg bytte ut løsningen min hvis jeg får tid/lyst en dag.
Jeg vet ikke helt hvor mye kunnskap du har om Javascript og PHP fra før, så jeg kan bryte opp koden og forklare så godt jeg får til. Kan jo hende at noen andre finner denne tråden om et år også, for alt vi vet.
Grunnidéen med skriptet jeg postet var å ha en fil som kan gjøre to oppgaver. Hvis fila åpnes
med en såkalt query string, eller GET-data, så kjøres en annen kode enn hvis filen åpnes
uten GET-data. På nettsider så har man to hovedmåter å sende informasjon på, GET-data og POST-data. Post er mer "usynlig" enn det GET er. Det er som regel POST du bruker når du trykker på knapper, logger inn med brukernavn og passord og slike ting. Hvis du prøver å oppdatere en fil (nettside) som du også har sendt POST-data til, så får du som regel en advarsel om at du er i ferd med å sende dataene én gang til.
GET er litt mer åpent, og i noen tilfeller mer praktisk. Variablene sendes her gjennom selve URL-en (linken). Her på forumet er det for eksempel ekstremt praktisk, ettersom hver tråd du leser genereres av den samme filen på serveren. Det som gjør at du ikke ser den samme tråden hver gang du åpner denne filen, er at variabelen "p" i URL-en har ulike verdier; i denne tråden ser du for eksempel "showthread.php?
p=2465045". Filen du har åpnet heter showthread.php, spørsmålstegnet angir at det som kommer etterpå er en query string (GET-data). "p" er variabelnavnet og erlik-tegnet viser hvilken verdi variabelen skal ha. Dette kan i PHP leses slik:
<?php
echo $_GET['p'];
?>
Output fra dette, når du leser denne tråden, vil da bli "2465045".
PHP-skriptet jeg postet er som sagt delt i to hoveddeler; isset()-funksjonen sjekker om variabelen "led" finnes i query stringen. Den skal da i teorien være true hvis du åpner filen med "?led" eller "?led=on" eller "?led=off" og så videre, bakerst i URL-en. isset() sjekker altså ikke hva verdien er for noe, den er true så lenge variabelen er noe annet enn underfinert eller NULL. "?led" vil gjøre at variabelen er en tom string (tilsvarende ""), som betyr at den er definert og ikke NULL. Grunnen til at denne sjekken er nødvendig er at PHP viser en notice (advarsel) hvis du prøver å sammenligne en variabel mot noe som ikke eksisterer. I det tilfellet hvor du åpner filen uten query string, så vil ikke $_GET['led'] eksistere, og if-løkken "if($_GET['led'] == 'on')" vil føre til en notice. Du kan selvsagt ignorere feilmeldinger å la dette være, men jeg synes det er litt dårlig praksis.
Hvis isset() finner at "led" eksisterer, så sjekker en ny if-løkke hva variabelen er satt til, enten "on" eller "off". Dette kommer da fra URL-en, enten "fil.php?led=on" eller "fil.php?led=off". Hvis den er noe annet enn "on" eller "off" så vil ikke skriptet gjøre noe som helst, og bare stanse. I tilfellene hvor den enten er "on" eller "off", så starter cURL-skriptet, som bare åpner én av de to URL-ene for å styre LED-lyset.
Hvis isset() finner at "led"
ikke eksisterer, så genererer filen HTML-output, som består av en Javascript-blokk og to knapper. Knappene er veldig enkle, de bruker onclick-funksjonen til å kjøre en Javascript-funksjon kalt "led()". Denne funksjonen er definert i Javascript-blokken øverst;
Kode
function led(status) {
var ajax;
try {
ajax = new XMLHttpRequest();
} catch (error) {
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP");
} catch (error) {
try {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
} catch (error) {
return false;
}
}
}
ajax.onreadystatechange = function() {
if(ajax.readyState == 4) {
}
}
ajax.open("GET", "?led=" + status, true);
ajax.send();
};
Her har jeg delt opp koden i tre deler. Den øverste er faktisk bare koden for å lage et AJAX-objekt. Dette er et objekt vi kan bruke til å sende data tilbake til webserveren uten å "oppdatere" nettsiden vi ser på. AJAX kan sende både GET- og POST-data, men i praksis er forskjellen på de to heller liten, siden du med AJAX aldri vil kunne se det som foregår i bakgrunnen (du ser ikke URL-en skriptet åpner når du trykker på knappene). Grunnen til at koden er så lang og merkelig, er at den er bakoverkompatibel, og skal fungere i alle nettlesere som på ett eller annet plan støtter AJAX. Det burde i grunnen holde med å bare si "ajax = new XMLHttpRequest();", men hvis noen prøver seg med en gammel versjon av Internet Explorer, Netscape eller noe slik tøys, så er vi på den trygge siden ved å teste alle andre måter å opprette et AJAX-objekt på. Derav alt dette try-catch styret.
Den miderste kodeblokken er en eksempelkode som ikke har noen funksjon slik jeg har skrevet den. Den første linjen knytter en funksjon til en event som kan skje med AJAX-objektet. Eventen heter "ready state change", som i praksis er statusen til AJAX-objektet. Denne statusen endrer seg når objektet holder på med noe. Enten laster inn, sender data, rapporterer feil eller mottar data. Alle statusene er knyttet til en ID. ID nummber 4 betyr at objektet har mottatt data fra serveren, og med "if(ajax.readyState == 4)" kan vi foreta oss noe når vi har fått svar. Dette kan for eksempel være en bekreftelse fra PHP-skriptet om at LED-lampen er endret. Hvis du for eksempel har mistet tilkoblingen til webserveren, så vil du ikke umiddelbart kunne se det på nettsiden når du har to knapper. Når du trykker på knappene, så vet du heller ikke om AJAX-forespørselen har kommet frem eller ei, spesielt ikke når denne respons-funksjonen ikke er programmert til å foreta seg noe når du får svar.
De to nederste linjene er det som er mest interessant. Den første linjen definerer hva slags og hvilken type data vi sender, og her velger vi GET. Query stringen er "led=" pluss variabelen "status". Vi sender altså ikke "led=status", men heller "led=" pluss hva enn variabelen "status" er satt til. Denne variabelen kommer fra knappene vi trykker på. Som du ser helt øverst i Javascriptet, der vi definerer funksjonen "led":
function led(status)
Her setter vi at variabelen "status" skal settes til det som sendes til funksjonen "led". Knappene er kodet på denne måten:
<input type="button" value="På" onclick="led('on')">
Her ser du på onclick-eventen, at funksjonen "led" åpnes med stringen "on", som betyr at "status" blir satt til "on" når du trykker. Dette sendes videre til ajax.open, og ajax.send() sender forespørselen til PHP-skriptet. Variabelen dukker da opp som $_GET['led'], og cURL-skriptet åpner den valgte URL-en for å slå på LED-lampen.
I psuedo-kode får vi da dette:
Kode
Hvis det finnes GET-data {
Hvis $_GET['led'] er "on" {
Ping URL 1
} Hvis $_GET['led'] er "off" {
Ping URL 2
}
} Hvis ikke {
Opprett AJAX-objekt
Send AJAX-data
Knapp 1
Knapp 2
}
Jeg klarer i farten ikke å se hvor koden brister hen, men det kan i ytterste konsekvens handle om at isset() ikke fungerer så bra sammen med $_GET-arrayet. En skitten hotfix er i så fall å skippe hele isset()-sjekken, og legge inn skillet i den andre if-sjekken, slik:
Kode
<?php
// Legg inn URL-ene som skal pinges:
$url_on = 'http://www.google.no/search?q=on';
$url_off = 'http://www.google.no/search?q=off';
// Sjekk om filen åpnes med GET-data eller ikke:
if($_GET['led'] == 'on') {
$link = curl_init($url_on);
curl_exec($link);
curl_close($link);
} elseif($_GET['led'] == 'off') {
$link = curl_init($url_off);
curl_exec($link);
curl_close($link);
} else {
// Ikke noe GET-data, så da viser vi layouten i stedet:
?>
<script>
function led(status) {
// Sett opp et AJAX-objekt:
var ajax;
try {
ajax = new XMLHttpRequest();
} catch (error) {
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP");
} catch (error) {
try {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
} catch (error) {
return false;
}
}
}
// Eksempel på ekstrafunksjon for å sjekke respons fra server:
ajax.onreadystatechange = function() {
if(ajax.readyState == 4) {
// Her kan du håndtere respons hvis du vil, serverdata ligger nå i ajax.responseText-variabelen (string)
}
}
// Send forespørsel til server
ajax.open("GET", "?led=" + status, true);
ajax.send();
};
</script>
<!-- Knapper for å starte AJAX-funksjonen: -->
<input type="button" value="På" onclick="led('on')">
<input type="button" value="Av" onclick="led('off')">
<!-- Avslutt else-løkken fra PHP-skriptet -->
<? } ?>
Eneste forskjell her er at jeg fjerner isset()-sjekken og legger til else-løkken som tredje alternativ på if-løkken som sjekker "on" og "off". Dette vil imidlertid produsere en notice hvis du har aktivert alle feilmeldinger.