Arhive za kategoriju ‘Internet’

Tutorial: Validacija Web forme pomocu JavaScript-a – Part 1

sreda, 3. mart 2010.

Okej, tema za mart mesec na blogu je JavaScript. Dosta sam se bacio na taj scripting jezik u poslednjih 20-ak dana, te sam rešio da svoju preokupaciju podelim sa svima. Našao sam jednu sjajno napisanu skriptu u knjizi „JavaScript and Ajax for the Web“ (strana 167) čiji su autori Tom Negrino i Dori Smith, pa ću ovde, na srpskom, objasniti šta ona ustvari radi, tako da će svima koji ne znaju JavaScript ovo dobro doći da neke stvari shvate. Ukoliko dobro poznajete ovu materiju, preporučujem da ipak pogledate o čemu se radi s obzirom da vam ovo može poslužiti kao dobar framework za dalji rad, ili čak kao gotovo rešenje spremno za implementaciju.

S obzirom da su Web 2.0 aplikacije uveliko standard, samim tim je i veća interakcija između korisnika i i web sajta. Forme su klasičan primer za prethodno rečeno. Ono o čemu ću ja danas pisati je verifikacija forme, odnosno, pokazaću kako možete proveriti da li je korisnik popunio sva polja iz forme i da li je to učinio pravilno. Postoje dva načina na koje možemo uraditi ovo:

1) da prosledimo unete podatke do web servera, tu ih obradimo, proverimo i nakon toga, ukoliko postoji greška, obavestimo korisnika. To možemo uraditi u nekom server-side jeziku (na primer, PHP).

2) da proveru uradimo direktno u korisničkom brauzeru, bez ikakvog kontakta sa web server-om koristeći JavaScript. Uslov je, naravno, da korisnik ima uključen JavaScript u svom brauzeru, što 99% korisnika ima.

Drugi način je daleko bolji jer se sve dešava na korisničkoj mašini, pa je samim tim i brži – vreme se ne gubi u slanju podataka do servera i čekanju da se isti obrade. Iz ovoga sledi i to da je naš server oslobođen od tog posla, pa će brže reagovati na zahteve nekih drugih korisnika.

Gotovo rešenje pogledajte odmah, a onda ću komentarisati deo po deo.

HTML - ništa specijalno, ne bih zalazio u analizu jer je akcenat pre svega u JavaScript kodu.


<html>
<head>
 <title>Car Picker</title>
 <script type="text/javascript" src="script.js"></script>
 <link rel="stylesheet" href="script.css" />
</head>
<body>
<h2 align="center">Car Picker</h2>
<form action="#">
 <p>
 <label for="emailAddr">Enter your email address:&nbsp;&nbsp;&nbsp;&nbsp; <input id="emailAddr" type="text" size="30" />
 </label></br />
 <label for="emailAddr2">Re-enter your email address:<input id="emailAddr2" type="text" size="30" />
 </label>
 </p>
 <p><label for="color">Colors:
 <select id="color">
 <option value="" selected="selected">Choose a color</option>
 <option value="Red">Red</option>
 <option value="Green">Green</option>
 <option value="Blue">Blue</option>
 </select>
 </label></p>
 <p>Options:
 <label for="sunroof"><input type="checkbox" id="sunroof" value="Yes" />Sunroof (Two door only)</label>
 <label for="pWindows"><input type="checkbox" id="pWindows" value="Yes" />Power Windows</label>
 </p>
 <p><label for="DoorCt">Doors:&nbsp;&nbsp;
 <input type="radio" id="twoDoor" name="DoorCt" value="twoDoor" />Two
 <input type="radio" id="fourDoor" name="DoorCt" value="fourDoor" />Four
 </label></p>
 <p><input type="submit" value="Submit" />&nbsp;<input type="reset" /></p>
</form>
</body>
</html>

JavaScript

window.onload = initForms;

function initForms() {
 for (var i=0; i< document.forms.length; i++) {
 document.forms[i].onsubmit = function() {return validForm();}
 }
}
function validForm() {
 var allGood = true;
 var allTags = document.getElementsByTagName("*");

 for (var i=0; i<allTags.length; i++) {
 if (!validTag(allTags[i])) {
 allGood = false;
 }
 }
 return allGood;

 function validTag(thisTag) {
 var outClass = "";
 var allClasses = thisTag.className.split(" ");

 for (var j=0; j<allClasses.length; j++) {
 outClass += validBasedOnClass(allClasses[j]) + " ";
 }

 thisTag.className = outClass;

 function validBasedOnClass(thisClass) {
 var classBack = "";

 switch(thisClass) {
 case "":
 case "invalid":
 break;
 case "reqd":
 if (allGood && thisTag.value == "") {
 classBack = "invalid ";
 }
 classBack += thisClass;
 break;
 default:
 classBack += thisClass;
 }
 return classBack;
 }
 }
}

KORAK 1: Analiza intForm() funkcije.

function initForms() {
 for (var i=0; i< document.forms.length; i++) {
 document.forms[i].onsubmit = function() {return validForm();}
 }
}

Proveravamo sve forme koje imamo na strani koristeci for loop. Uvodimo promenljivu i, i dok je ona manja od broja formi na strani (document.forms se odnosi na sve form objekte na strani, dok je ovo .length ustvari njihov ukupan broj), pozivamo funkciju koja nema deklarisano ime, već samo vraća vrednost funkcije validForm() ukoliko je korisnik kliknuo na form submit. Drugim rečima: Zamislite da je korisnik kliknuo na neku našu formu Tada JavaScript preko onsubmit handler-era poziva funkciju koja vraća vrednost funkcije validForm(). Funkcija validForm() može imati samo dve vrednosti: true ili false! U sledecem bloku koda videćemo šta zapravo validForm() radi.

KORAK 2: Analiza validForm() i validTag() funkcija.

function validForm() {
 var allGood = true;
 var allTags = document.getElementsByTagName("*");

 for (var i=0; i<allTags.length; i++) {
 if (!validTag(allTags[i])) {
 allGood = false;
 }
 }
 return allGood;

Unutar funkcije validForm() imamo promenljive allGood koja je po default-u true, i allTags kojoj dodeljujemo vrednost svih html elemenata na strani. Da smo napisali document.getElementsByTagName(„p“), onda bi se allTags promenljiva odnosila iskljucivo na paragrafe. Mogli smo da stavimo kao parametar bilo koji element. U ovom slučaju, nas interesuju svi elementi, pa nam je zato parametar („*“), jer * = all!

Opet, for loop-om prolazimo kroz sve elemente na stranici i ubacujemo ih kao parametar u funkciju validTag(). validTag() će biti objašnjena u sledećim pasusima – za sada nam je bitno da njena vrednost moze biti samo true ili false. Ukoliko je njena vrednost false, tj, ukoliko (!validTag(allTags[i])), onda ce i nasa promenljiva allGods biti false, pa ce i sama funkcija validForm() biti false jer ta funkcija vraća vrednost promenljive allGood (return allGood;).


function validTag(thisTag) {
 var outClass = "";
 var allClasses = thisTag.className.split(" ");

 for (var j=0; j<allClasses.length; j++) {
 outClass += validBasedOnClass(allClasses[j]) + " ";
 }

thisTag.className = outClass;

validTag() prima parametar allTags[i] iz prethodne funkcije validForm(). Vrednost tog parametra obeležavamo promenljivom thisTag. Da bih malo približio ovo onima koji ne shvataju ovo, pokušaću da kažem i ovako: Rekli smo da f-ja validForm() pretražuje sve elemente na strani. Zamislite da je došla do nekog p taga (dakle paragraf). Ona prosleđuje p tag do f-je validTag(), pa je u tom slučaju thisTag ustvari p. Onda ta funkcija dobije, na primer, tag a kao parametar. U tom slučaju, thisTag ce biti a. I tako dalje, sve do poslednjeg elementa na strani.

Prokomentarišimo sada šta se sve dešava unutar funkcije validTag(). Deklarišemo nove promenljive: outClass koja je po defaultu prazan string i drugu promenljivu – allClasses, koja iz taga koji je trenutno ubačen u funkciju (kao sto smo malopre rekli, to moze biti bilo koji tag) čita njegovu klasu, i ukoliko parametar ima više klasa, onda ih razdvaja (className.split(“ „);) i smesta u niz. Pokažimo to na praktičnom primeru:


<label for="emailAddr2">Re-enter your email address:<input id="emailAddr2" type="text" size="30" />

Vidite kako naša labela ima dve klase:  reqd i emailAddr. U tom slučaju će className.split(“ „); uraditi sledeće: Napraviće niz i smestiti oba stringa (tj, imena obe klase, koja su u našem primeru reqd i emailAddr) u taj niz. Zatim, novim for loop-om „pretresti taj niz“, uzeti svaki njegov clan i ubacivati kao parametar u našu novu funkciju validBasedOnClass(allClasses[j]). Ta funkcija će uraditi proveru da li je clan tog niza (odnosno klasa)  „invalid“. Više reči o tome će biti u narednim pasusima.

Za sada nam je bitno da će na kraju ovog našeg for loop-a vrednost promenljive outClass (za primer prethodne labele) biti „reqd emailAddr“.

KORAK 4: Provera da li imamo „invalid“ klasu:

if (outClass.indexOf("invalid") > -1) {
 thisTag.focus();
 if (thisTag.nodeName == "INPUT") {
 thisTag.select();
 }
 return false;
 }
 return true;

Proveravamo dalje da li ta klasa ( u slučaju sa našom labelom „reqd emailAddr“) u sebi sadrži reč „invalid„, tj, da li string invalid deo (indexOf) outClass-e. Ukoliko jeste, onda cemo taj html tag (labelu), staviti u fokus, kako bismo ispitali da li je nodeName ustvari input tag. Drugim rečima – ukoliko nađemo bar jednu klasu invalid, funkciji vracamo vrednost false, a samim tim ona nece biti procesirana do web servera, vec ce korisniku odmah vratiti adekvatnu gresku. Ukoliko string „invalid“ nije pronađen, onda je sve u redu (korisnik je pravilno popunio formu), f-ja će vratiti vrednost true, pa će podaci iz forme biti prosleđeni Web serveru.

KORAK 3: Analiza funkcije validBasedOnClass(thisClass)

function validBasedOnClass(thisClass) {
 var classBack = "";

 switch(thisClass) {
 case "":
 case "invalid":
 break;
 case "reqd":
 if (allGood && thisTag.value == "") {
 classBack = "invalid ";
 }
 classBack += thisClass;
 break;
 default:
 classBack += thisClass;
 }
 return classBack;
 }

Prokomentarišimo sada funkciju validBasedOnClass(thisClass). Deklarisali smo promenljivu classBack.
Primecujemo da paramatar koji dolazi u funkciju može imati različite vrednosti. On može biti prazan, može biti „invalid“, „reqd“, itd. Za takve situacije je najbolje koristiti switch, koji je nalik if-u. Postoje, dakle, više različitih slučajeva (case). Za slučaj da je parametar koji je dospeo u funkciju prazan string ili „invalid“, odmah izlazimo iz switch-a komandom break. Break bukvalno kaže switch-u: „okej, gotovi smo sa ispitivanjem, to je taj slučaj koji tražim, ne proveravaj ostale mogućnosti.“
Ono sto nas najviše interesuje je slučaj ukoliko je parametar=“reqd“. To znači da je polje sa tom klasom obavezno (korisnik mora da ga popuni ukoliko želi da mu forma bude prosledjena do servera). Ukoliko on ipak nije uneo nista u required polje, tj, vrednost tog polja je prazan string (thisTag.value == „“), vrednost naše promenljive classBack ćemo PROMENITI POMOĆU JAVASCRIPT-a na INVALID. Ovo je ključna tačka jer se odmah zatim desavaju sledece stvari:

  1. Funkcija validBasedOnClass(thisClass) će vratiti vrednost invalid
  2. Onda ta vrednost odlazi do 4. KORAKA, gde u proveri tražimo upravo tu reč. Ukoliko je nađemo, naša forma neće biti procesirana jer će funkcija validTag() vratiti false, samim tim će i promenljiva allGood (deklarisana u validForm()) biti false, a što dalje implicira da naša forma NIJE VALIDNA!

To bi bilo sve za ovaj prvi deo. Drugi deo ću objaviti početkom aprila. Ostalo je još dosta posla koji treba da se završi kako bi ova skripta zaista bila dobra i sasvim funkcionalna.

Ispis i update datuma prvog i poslednjeg dana u nedelji u PHP-u.

utorak, 19. januar 2010.

Pisao sam o sajtu za Anin fitness klub. Iako je završen, shvatili smo da je poprilično dosadno da svakog ponedeljka  ručno menjamo raspored termina treninga. A i ne možemo uvek biti tačni, već često kasnimo, pa datum promenimo u ponedeljak uveče, što zaista deluje neprofesionalno. Zato smo došli na ideju da napišemo skriptu koja će raditi to umesto nas, i tačno na vreme. :)

Aleksandar Saša Babić je preuzeo odgovornost na sebe i napisao odlično parčence koda. :)   Zato reših da ga podelim ovde sa svima, uz njegovu saglasnost naravno, a to će ujedno i biti drugi mini mini php tutorial na blogu (podsetnik:  link ka prvom).

Zadatak: Napraviti skriptu koja će ispisivati datum ponedeljka, datum nedelje, a kada se ta nedelja završi, skripta treba automatski da promeni datum i ponedeljka i nedelje, tako da raspored bude uvek up-to-date!


Ideja: Ceo problem se rešava utvrđivanjem da li je trenutni dan ponedeljak ili ne. Zato, ukoliko je dan kada korisnik poseti sajt ponedeljak, skripta će preko funkcije gettime() ispisati današnji datum, a ako tad nije ponedeljak, već neki drugi dan, skripta će uzeti datum ponedeljka iz te, tekuće nedelje.

Koji je danas dan? Pozivanjem funkcije getdate() možemo to saznati. Ona vraća niz koji se sastoji od sledećih podataka:
Array
(
[seconds] => 40
[minutes] => 58
[hours] => 21
[mday] => 17
[wday] => 2 //dan u nedelji !
[mon] => 6
[year] => 2003
[yday] => 167
[weekday] => Tuesday
[month] => June
[0] => 1055901520
)

Evo i koda:

<?php
$danas = getdate();
//ukoliko je getdate vratio vrednost 1 za wday, to znači da je ponedeljak(0 je nedelja, 1 ponedeljak, 2 utorak...), pa ćemo zato iskoristiti taj datum
//ukoliko nije 1 (to znači da nije ponedeljak, pa ćemo zato uzeti poslednji (vremenski najbliži) ponedeljak, last monday
//moramo iskoristiti i strtotime (ova f-ja ce string last monday prebaciti u timestamp).
$ponedeljak = ($danas['wday'] == 1) ? $danas[0] : strtotime('last monday');
//timestamp ponedeljka pa jos dodajemo 60sekundi X 60 minuta X 24h X 6dana, tj. vreme da bismo dobili nedelju
$nedelja = $ponedeljak + (60*60*24*6);
?>
<h2>Raspored (<?php echo date('d.m.Y', $ponedeljak); ?> do <?php echo date('d.m.Y', $nedelja); ?> </h2>

Pre svega, želeo bih da objasnim da linija:

$ponedeljak = ($danas['wday'] == 1) ? $danas[0] : strtotime('last monday');

vrši isti posao kao i ovih par:

<?php
 if ($danas['wday'] == 1) {
 $ponedeljak = $danas[0];
 } else {
 $ponedeljak = strtotime('next sunday');
 }
?>

Naravno, prvi oblik je mnogo kraći, pa je zato praktičniji. On zapravo znači sledeće:

$variable = (statement) ? "return if true" : "return if false";

Kada smo odredili vrednosti za naše promenljive, ostalo je još da ih konvertujemo u vreme koje čovek može da razume, s obzirom da one prikazuju timestamp.

Timestamp je vreme koje je prošlo od ponoći 1. januara 1970.  u sekundama. Primera radi, 18. januara 2010. u 01.45h $ponedeljak  ima vrednost 1263772800 (toliko sekundi je prošlo od 1. januara 1970).

Konverziju ćemo uraditi funkcijom date(‘d.m.Y’, $neko-vreme), gde je:
d – dan, m-mesec, Y-godina. Naravno, evo kako izgleda konvertovani $ponedeljak: 18.01.2010.

Time smo postigli ono što smo želeli – skripta sama piše i menja datum.

Predstavljamo: Ana Fitness Klub Online

petak, 25. decembar 2009.

Poslednjih 15-ak dana sam bio angažovan oko sajta fitness kluba iz Zaječara, koji vodi Ana Belivuk. Ovo mi je do sada bio jedan od najzahtevnijih projekata – ne zato što je Ana tražila nešto specijalno, već zato što sam u potpunosti ostavio svoj stil i radio po šemi koju je ona sama napravila.

Ana je veoma pozitivna osoba i obožava jarke boje. Od samog starta, kada smo planirali celu priču oko sajta, naglasila mi je da želi belu pozadinu sa što više sličica i boja. Ja, lično, preferiram što manje boja na sajtu, gde dominiraju siva i još jedna, osnovna boja. Međutim, ovde se to nije tražilo.

Nakon par dana od skiciranja i ugovaranja posla, napravio sam jedan template, sa grubo definisanim elementima. To je bilo okej, ali kako je Ana rekla, u glavi je ipak imala neku drugačiju sliku. Zamolio sam je da do detalja sve nacrta na papiru i prosledi Darku, koji je takođe bio uključen u ovaj posao, s obzirom da sam ja već tada bio u Beogradu.

Skicu sam vrlo brzo dobio i shvatio sam da se ono, što smo prvi put napravili, zaista nije mnogo podudaralo sa pravom Aninom željom. Ali, ništa lepše nego kada imate gotovu skicu, definisane boje, raspored i veličine svih elemenata – na vama je da samo to sprovedete u delo. Kada smo odradili redizajn prvobitnog template-a, Ana je bila veoma zadovoljna, jer je to upravo bilo ono što je ona želela. U tom trenutku jedino što nije valjalo je bila pozadina body-a. Iz tog razloga, linkovao sam Ani sajt sa vrlo dobrim izborom pattern-a, i ona je sutradan poslala link do pozadine koju je želela. S obzirom da smo dobili tačno onakav template kakav je ona zamislila, ostale stvari smo vrlo brzo i u hodu rešavali. Tu bih, na kratko, skrenuo temu sa dizajna na funkcionalnost.

Pre svega, želeo bih da kažem da je ovo u stvari mini CMS, prilagođen Aninim potrebama. Za one koji ne znaju, CMS je skraćeno od Content Management System, što zapravo predstavlja sistem za upravljanje sadržajem. Ana je želela da može sama da objavljuje vesti (od kojih će se samo dve, najnovije prikazivati na početnoj strani), dok bi se starije vesti prikazivale u arhivi (koja ne uključuje najnovije dve vesti, vidljive na početnoj). Svaka vest treba da u sebi sadrži i sličicu, koja se takođe bira sa lokalnog računara odakle se objavljuje vest. Isto tako, Ana je osetila potrebu da sama uređuje raspored treninga, kao i početni i krajnji termin održavanja, a sve to je dostupno sa leve strane sajta u ljubičastom pravougaoniku. Tako da se i taj deo direktno preuzima iz baze sajta. Sve ostalo je kodirano ručno u html-u.

Prosto ne mogu, a da ne spomenem problem sa kojim sam se susreo prilikom pravljenja ovog sistema – srpska latinična slova (ž, š, itd) koja su u bazi normalno zapisana se nisu videla na sajtu. E sada, šta je bilo najsmešnije u celoj situaciji (ovo je malo advanced level, pa ko se ne bavi web programiranjem, neće razumeti o čemu govorim, pa ovaj pasus može slobodno da preskoči):

Ukoliko dodam vest preko admin panel-a, a zatim odem na početnu stranicu sajta da pogledam kako ta vest izgleda, imam šta i da vidim – sadržaj vesti se ispisuje sve dok ne dođe do nekog našeg slova i tu stane. Dakle, bukvalno ispred prvog našeg slova koje treba da echo-uje, on prestaje. Pogledam odmah phpmyadmin i vidim da vest nije lepo upisana ni u bazu – umesto naših slova, vide se oni konvertovani znakovi. Proveravam dalje i vidim da su mi sve tabele u bazi lepo podešene – encoding utf8_unicode_ci. Hm…Čudno!

Testiram dalje i uradim INSERT nad news tabelom u okviru phpmyadmin-a, i tada su se sva slova lepo videla u bazi. Međutim, kada pogledam početnu stranu sajta, i dalje sve isto – naša slova ne vidi, pa to ti je. Neko bi rekao – pa problem je u encodingu početne strane – sigurno nije podešena na UTF8. Međutim, nije ni to u pitanju – stranica ima upravo taj encoding, a kao dodatni dokaz mi je bio fakt da su se naša slova na indeksu, kucana u html-u, lepo videla. Razmišljam, proveravam sve po ko zna koliko puta – ne vidim gde je greška. Odustajem, šaljem mail Nemanji Avramoviću i odlazim na spavanje (u 04.00h), nadajući se da će me sutra ujutru čekati mail sa nekim savetom. Naravno, to se i desilo. Linkovao mi je TOP temu sa ES-a, u kojoj je bio odgovor na sve moje muke. Pri samom konektovanju na bazu, dopisao sam dve linije (kao što je tamo naglešeno) i voila….indeks strana RADI!!! Podaci iz baze ( sa naglaskom na naša slova) se prikazuju korektno. Ali, waaaait! Problem je samo polovično rešen. Zapravo, vesti se prikazuju dobro ako i samo ako se upisuju u bazu iz phpmyadmin-a. Ukoliko se to radi preko formulara iz admin panela sajta, i dalje dolazimo do istog problema.

Kontam dalje – okej, mora da postoji neki problem u prenosu podataka iz aplikacije do baze. Jedino logično u ovoj situaciji jeste da strana u admin panel-u, na kojoj se nalazi formular za dodavanje vesti nije propisno encodovan. Što zapravo i jeste bio slučaj – pogledam prvo u Firefox-u opcijom View->Еncoding, gde stoji Western. Dalje, pogledam source te stranice, gde između head tagova nigde meta tagova za character encoding. Nakon dodavanja i te linije – sve je konačno proradilo.

Ah…Zamalo da zaboravim. Postojao je još jedan problem (više vezan za dizajn) koji mi je bespotrebno oduzeo bar sat vremena. kao što se vidi, ceo sajt je centriran. Tačnije, smešten je u div-u pod nazivom container, koji ima margin: 0 auto. Međutim, dragi Internet Explorer 6 to nije umeo da protumači i umesto da centrtira sajt, on ga je prilepio uz levu ivicu. Gledao sam i gledao i nikako da shvatim zbog čega JEDINO IE6 ne centrira sajt kao i svi ostali brauzeri. Nakon nekoliko pokušaja, došao sam do odgovora preko Google-a (jaaaaako bitno):

Da bi margin: 0 auto radilo u IE6, na početku tog dokumenta mora da stoji DOCTYPE deklaracija!!! Pogledam svoj source – naravno, ja to i nisam napisao, već mi ceo kod počinje html  tagom. Ubacim traženo i naravno, centriranje je proradilo i u IE6.

Ovo su sitnice, koje znaju da debelo zagorčaju život. Priznajem, delimično i mojom krivicom, jer sve mora pravilno biti definisano na strani. Ali, iz cele situacije sam izvukao neka nova znanja i pouke, tako da mi neće pasti na pamet da ostavljam neku stranu bez jasno napisanih tagova.

Nakon 15-ak dana rada, veoma sam zadovoljan kako sajt izgleda, kako radi itd. Boje su, po mom mišljenju, veoma dobro uklopljene, a sa time se slaže i ciljna grupa posetioca – kako mi je Ana rekla, njeni vežbači su prezadovoljni sajtom, te na naš račun stižu samo pozitivne kritike. U nadi da će se i Vama dopasti i da ćete pronaći korisne informacije na njemu, ostaje mi da još jednom samo zabeležim adresu: www.ana-fitness.com. Dobro došli.

P.S.  Zahvaljujem se sledećim ljudima koji su sve vreme davali savete i ideje, ali i radili testove funkcionalnosti:

Darko Stratijev, co-worker.

Vukašin Sadžak, koji je bio i ostao moj glavni kritičar u svim projektima na kojima sam radio.

Stefan Jocić, nemoguće je reći u jednoj rečenici koliko saveta sam za ovaj projekat dobio od njega, kao i veliku podršku u kasnim noćnim satima prilikom rešavanja pomenutih problema.

Vladimir Stoiljković, koji je posebno pomogao oko izrade kontakt forme.

Nemanja Veljković, Aleksandar Mitrović, Martać Ivan koji su svakodnevno komentarisali dizajn celokupnog sajta i davali konkretne savete za određene dizajn dileme.

Direktno editovanje fajlova preko FTP-a pomoću Notepad++

četvrtak, 10. decembar 2009.

notepadSvako ko se bavi Web developmentom je došao u situaciju da, kada postavi gotov sajt na server, vremenom opazi da neki deo treba da se prepravi. Dug i dosadan način za to bi bio da se nakačite preko nekog FTP klijenta na server, zatim da sačuvate u kompjuteru fajl koji želite da uredite, uradite potrebne modifikacije i na kraju – ponovni upload fajla na server.

Nedavno sam, zahvaljujući Aleksandru Babiću, otkrio mnogo jednostavniji način – direktno editovanje na serveru pomoću Notepad++. Inače, ovo je svakako moj omiljeni text-editor i nije mi jasno kako mi još ranije nije palo na pamet da iskoristim ovu fenomenalnu mogućnost. Umesto toga, ja sam radio online prepravke iz cPanel-a. Ali, sada je tome kraj.

Prvo što treba da uradite je da skinete dodatak za Notepad++ koji se zove FTP_Synchronize i isti prekopirate u Notepad++ plugins folder. Nakon toga, pokrenite Notepad++, i videćete ikonicu kao na slici.

np++

Klikom na tu ikonicu, pojavljuje se prozor gde ćete videti novu ikonicu sa nazivom Open settings dialog gde treba da unesete:

Profile Name: Bilo šta, što će Vama lično služiti za prepoznavanje te konekcije,

Address: standarna FTP adresa Vašeg servera (hostname),

Port: 21,

i naravno username i password.

Nakon ovoga bi trebalo da sve lepo funkcioniše.  Vratite se jedan prozor unazad i u FTP Folder prozoru kliknite na prvo dugme sa leve strane, koje služi za konekciju i woilaaaa…..Ući ćete u root vašeg hosta!

Happy coding & editing! :)

Kako izgleda proces postavljanja WordPress teme na zvanični sajt

petak, 30. oktobar 2009.

Kao što sam ranije pisao, veliki sam fan WordPress-a i smatram da je to najbolje rešenje za CMS. Iz tog razloga sam rešio da dam jedan mali doprinos celokupnoj WordPress zajednici tako što ću dizajnirati besplatan template. Tačnije, ideja mi je bila da Starter Web Template bude dostupan i za WordPress.

To nije bio nikakav problem i trebalo je svega dva popodneva da se to uradi. Međutim, sve je to bilo u vreme kada sam se pripremao (i psihički i fizički) za fakultet i odlazak u Beograd da nisam stigao da objavim svoj rad na zvaničnom WordPress sajtu, u sekciji za teme.

Inače, kada sam došao u Beograd i malo se osvestio, pozajmio sam lap top od druga (jer ja i nemam internet), kako bih konačno uploadovao svoj template. Međutim, tu je bilo raznih peripetija i shvatio sam koliko je moj template bio u stvari nezavršen.  Time je, ujedno, WordPress filozofija još više narasla u mojim očima. Dakle, da bi se vaš template našao u njihovoj biblioteci, potrebno je da bude savršen, inače, neće ga prihvatiti. Kada kažem savršen, ne mislim na neki specijalan dizajn, već na ispravan kod i u potpunosti ispoštovane norme koje je WordPress postavio. Njihova želja nije da imaju sve teme ovoga sveta, već sve 100% funkcionalne teme ovog sveta. Dozvolite da objasnim šta to znači:

  1. Vaš folder sa kreiranom WordPress temom mora sadržati bar dva osnovna fajla: index.php i style.css. U suprotnom, tema neće raditi. Index.php je veoma fleksibilan i može prikazati sve (stranice sa postovima, postove pojedinačno, statične strane ponaosob, arhivu itd), ukoliko nedostaju fajlovi tema usko namenjeni za nabrojane stvari.  Ipak, u praksi se uvek koriste dodatni fajlovi radi povećanja funkcionalnosti: header.php, sidebar.phpfooter.phpcategory.phppage.php, archive.php, comments.php i drugi. Zato, gledajte da, kada dizajnirate temu, iskoristite sve ove mogućnosti. Postoji još jedna neophodna stvar koju vaš folder sa temom mora imati – to je screenshot.png fajl – slika Vaše teme. Bez ovoga, takođe, nećete uspeti da postavite template na njihov sajt.
  2. Pomenuo sam da tema mora sadržati style.css. Ovaj fajl je jako bitan i morate posebno voditi računa tu. Style.css fajl mora da ima deklarisana svojstva za float: left i right i na samom početku mora da ima sledeće linije (posebno obratite pažnju na Tags, ja sam nekoliko puta to prepravljao da bi bilo pravilno, jer npr. ne možete staviti i orange i white, već se opredeliti za jednu boju):
  3. /*
    Theme Name: Rose
    Theme URI: the-theme’s-homepage
    Description: a-brief-description
    Author: your-name
    Author URI: your-URI
    Template: use-this-to-define-a-parent-theme–optional
    Version: a-number–optional
    Tags: three-columns, flexible-width, orange, light
    .
    General comments/License Statement if any.
    .
    */

  4. Folder ne sme imati fajl tipa thumbs.db – inače, takođe ćete imati problem.

To su tri stvari, koje bih ja izdvojio kao važne za ovaj deo. Ukoliko ste sve to sredili, možete zipovati temu i otići na formu za upload. Nakon toga, ljudi iz WordPress-a će videti šta ste vi to njima spremili. Ja sam pratio posete na mom blogu i video da su oni proverili link teme koji sam im ja stavio u style.css. Zatim, preveli su preko gugla kompletan tekst i videli da nešto nije u redu.

S obzirom da je Starter Web Template namenjen drugima, svako može da ga skine odavde i iskoristi u svojim projektima (u ovom ili izmenjenom izdanju) i ima prava da izmeni footer u potpunosti (što uključuje i brisanje mog imena), ali nema prava da obriše linije (komentare) iz source-a koje vode ka pravom dizajneru teme.

Ovo je ključna rečenica kojom sam ja prekršio GPL licencu i zbog toga Starter Web Template, sa ovim postavkama ne žele da uvrste u njihovu biblioteku tema. Meni je, lično, veoma krivo zbog toga, ali eto, na taj način funkcioniše WordPress. Mene je sve ovo mnogo oduševilo – koliko su funkcionalni i praktični. Rezimiraću još jednom: kada uploadujete zipovanu temu, ona se, odmah po završetku uploada raspakuje na njihovom serveru i kreće automatizovana provera svih fajlova koji se nalaze unutra. Ukoliko je to u redu, onda skripta otvara style.css i proverava da li je onaj početni deo pravilno napisan. Ukoliko je sve to prošlo, proveravaju se fajlovi kako bi se uvidelo da li postoje neophodne WP funkcije. A ukoliko i to prođete, celu temu proverava i prava osoba, da se uveri da je sve u redu i na kraju, Vaša tema postaje deo njihovog sajta, spremna za download. Yeeey! :D

Starter Web Template za WordPress

nedelja, 20. septembar 2009.

Pre svega, dobro došli na blog koji sada izgleda potpuno drugačije. Kao što sam i obećao, Starter Web Template od danas podržava i WordPress blog platformu. I evo, live demo možete videti upravo na ovom blogu.

Ukoliko Vam se dopalo xhtml/css izdanje, siguran sam da ćete biti zadovoljni i ovim za WordPress, jer je skoro sve ostalo identično. Jedino mesto gde sam napravio malu promenu jeste deo iznad footer-a. Umesto nekih korisnih informacija sa sličicama, sada je tu dinamični sidebar gde možete postaviti neki od Vaših omiljenih widget-a  – idealno (za oko) bi bilo ukoliko stavite tačno 4.

Pomenuo bih još jednu očekivanu novinu. S obzirom da je za blog bitno da postoji evidencija o datumu svakog unosa, rešio sam da izbegnem klasičan prikaz i napravim malo zanimljiviji dizajn u obliku malog kalendara i na njemu prikažem dan i mesec objavljivanja. Kalendarčić se nalazi sa leve strane naslova svakog zapisa.

Indeks stranica, takođe, nije sa osnovnim WordPress postavkama, već je modifikovana sa ciljem bržeg učitavanja i smanjenja ostvarenog protoka kod posetioca bloga. Iz tog razloga, samo prvi zapis na svakoj strani se prikazuje u potpunosti, dok se ostalih (u mom slučaju 9) prikazuju skraćeno i bez slika (ukoliko ih ima).

I za kraj, skrenuo bih pažnju i na komentare, odnosno izgled njihovog rednog broja. Tu je, ponovo, došlo do odstupanja od klasičnog WordPress prikaza i napravljeno nešto novo u skladu sa dizajnom cele teme.

Zaista bih voleo da ostavite komentar o vašem generalnom utisku na osnovu prikazanog na ovom blogu. Još draže bi mi bilo ukoliko biste mi dali neki savet ukoliko smatrate da bi nešto trebalo da se doda/prepravi. Meni je ostalo još par dana testiranja raznih stvari na ovoj temi – kako bih se 100% uverio da je sve u redu, pa ću rado podeliti sa svima ovaj template (što uključuje i objavljivanje na glavnom WordPress sajtu).

Starter Web Template

nedelja, 13. septembar 2009.

starter_web_template

Starter Web Template je jednostavan i veoma brz CSS template koji se sastoji iz zaglavlja, sadržaja, bočne trake i podnožja – veoma sličan WordPress temi sa jednom bočnom trakom sa desne strane. Ipak, za sada ne postoji verzija koja podržava WordPress, ali s obzirom da imam dovoljno slobodnog vremena, do kraja raspusta ću napraviti  template i za pomenuti CMS.

Što se tiče validnosti, Starter Web Template je uspešno prošao test i za xHTML i za CSS. Takođe, nema grešaka ni na najpopularnijim brauzerima – testirana je na Firefox-u 3.5.2, Internet Explorer-u 7, Operi 9 i na Google Chrome.

Inače, Starter je, kao što sam napomenuo, tema koja nema puno detalja, boja i slika – sve se svodi na veoma jednostavan ali elegantan izgled čija je glavna karakteristika brz prikaz u brauzeru, ali i usability.

S obzirom da je Starter Web Template namenjen drugima, svako može da ga skine odavde i iskoristi u svojim projektima (u ovom ili izmenjenom izdanju) i ima prava da izmeni footer u potpunosti (što uključuje i brisanje mog imena), ali nema prava da obriše linije (komentare) iz source-a koje vode ka pravom dizajneru teme.

I za kraj – ovaj template možete uživo videti ovde.

Kako napraviti preglednu tabelu pomoću PHP-a i CSS-a?

četvrtak, 3. septembar 2009.

Ovo je moj prvi tutorial na blogu. Dobro…mini, mini, mini tutorial. :)
Zapravo, ništa teško, niti glomazno. Cilj mi je da pokažem jedno od rešenja za sledeći problemčić: izvući podatke iz baze, smestiti ih u html tabelu tako da prvi red bude u jednoj boji, drugi u drugoj, treći ponovo u prvoj, četvrti u drugoj i tako do kraja. Evo kako treba izgledati tabela u brauzeru:

tabela-konacno

Dakle,  ovde je glavni problem namestiti da boje dva susedna reda tabele budu različite. E pa evo kako sam ja to rešio (ovo je potpuno detaljno uputstvo).

Prvo, treba da se konektujemo na MySQL (tabela u bazi ima tri polja: id, ime, prezime):

mysql_konekcija

A evo i koda koji će odraditi posao:

tabela

Dakle, pre nego što ciklus ispisa redova započne, deklarisao sam promenljivu $boja i dodao joj vrednost 1. Zatim, ispis počinje uslovom – ukoliko je 1 vrednost te promenljive (što u ovom prvom slučaju i jeste), taj red će imati pozadinu po svojstvima CSS klase svetliji-red. Odmah nakon ispisa prvog reda, promenljiva $boja dobija vrednost 2. Pošto je taj red ispisan, skripta kreće sa novim redom. Ponovo se proverava da li boja ima vrednost 1. Međutim, pošto taj uslov nije sada ispunjen, red će imati pozadinu  po svojstvima CSS klase tamniji-red i odmah nakon završetka ispisa, promenljivoj boja se dodeljuje vrednost 1 kako bi sledeći red bio identičan prvom redu. Taj proces se vrti naizmenično sve do kraja.

Evo i CSS-a koji sam iskoristio za ovu priliku:

css

Raspao se kod….:(

subota, 22. avgust 2009.

Biću veoma kratak…jer trenutno i nisam u stanju da bilo šta više zapišem. Celog leta (oko 2 meseca u proseku po 3h) sam proveo uz kompjuter kako bih napravio sajt za gimnaziju. Na mom PC-u je Windows, server Appache. Danas je, posle dosta truda, delovalo sve perfektno – cela aplikacija radi ono što želim da radi. Rešio sam da je testiram na hostingu na kome će uskoro biti postavljena i javno, međutim doživeo sam razočarenje:

Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent (output started at /home2/pakito/public_html/pakito.iz.rs/…/…/index.php:1) in /home2/pakito/public_html/pakito.iz.rs/…/…/sesija.php on line 10

Warning: Cannot modify header information – headers already sent by (output started at /home2/pakito/public_html/pakito.iz.rs/…/…/index.php:1) in /home2/pakito/public_html/pakito.iz.rs/…/…/header_admin.php on line 3

Zbog ovoga sam prso. Pod Windowsom radi sve sjajno, a kad se digne na Linux, dobije se jedan veeeliki q! Znam šta je u pitanju – session_start() funkcija mora biti prva u skripti, ne sme ništa da dođe do browsera pre ovoga i čini mi se da i jeste tako…ali, samo mi se čini. Nešto ne valja. Negde ne valja. Samo, ja pojma nemam gde….Nemam pojma koliko!

Trenutno ne znam ništa, iako sam proveravao ceo dan. Nervozan sam, mnogo! Radiš na nečemu, trudiš se, mučiš….i sad….nevaljašno!

Negde sam se ponovio….to sigurno, a ima nekoliko mesta gde se kod ponavlja (što u principu nije najzahvalnije), ali zašto onda radi na Windows-u, a ovamo neće???

Nemam pojma….i rešio sam da se prvo malo smirim – dan, dva, videću koliko mi treba, pa onda da sednem i sredim stvar. Ovako tempiran mogu samo još lošiji kod da napravim….

DOPUNA:

Sve je u redu. Aplikacija radi sada i pod Linux-om. Ceo problem je bio u BOM-u, koji se nekako promuvao jer neke stranice nisu bile u encodnig-u bez BOM-a.

XSS napad

nedelja, 16. avgust 2009.

Uf kakav trip za dva dana. Kada sam se vratio iz grada sinoć, upao sam malo na internet, kao i obično, kako bih proverio svoje omiljene sajtove. Ulogujem se na blog, pa u Kontrolni panel bloga i imam šta da vidim – izađe JavaScript prozor sa porukom XSS – slika. Nisam imao pojma šta je, ali u svakom slučaju, nije mi delovalo kao nešto dobro. Kada sam proverio, video sam da je u pitanju Cross-Client Scripting.

Ima jedan zaista dobar članak na srpskom koji govori baš o ovom problemu. Uglavnom, može doći do ove vrste napada ukoliko sadržaj na sajtu unet spolja (preko neke forme na primer) nije pravilno filtriran. Najlakše je tako nešto proveriti funkcijom htmlentities(), za koju sam svakako čuo, ali interesantno da me mrzelo da je koristim kada sam pišem nekakav kod, već samo proveravam unose sa mysql_real_escape_string() iako ta funkcija proverava nešto sasvim drugo – nevezano za ovaj problem. Iz tog razloga, dobro je što mi se ovo desilo, da shvatam opasnost koja vreba i iz client-scripting jezika, a ne samo iz server-side jezika, kao što sam mislio i da počnem da koristim htmlentities.

Nego, da se vratim na problem – xss prozor se stalno pojavljivao kada uđem u WassUp plugin. Na svim drugim stranicama Kontrolnog panela, nije bilo nikakvih opasnih signala. Googlao sam, ali nisam uspeo da pronađem rešenje za problem, jer za WordPress nije obrađena ova tema. Doduše, na zvaničnom sajtu ovog popularnog CMS-a sam video da verzija 2.8.2 rešava problem iz prethodne verzije vezan za XSS napade. Međutim, kod mene je verzija 2.8.4, tako da sam sa te strane zaštićen. Pretpostavio sam da je došlo do neke rupe na hostingu i odmah proverio Darkov blog, međutim, kod njega je sve radilo najnormalnije. Iz toga, zaključio sam da je moj blog bio samo jedna od meta pronađena preko Gugla, s obzirom da je moj domen aktivan i vidljiv na Guglu, ua razliku od Darkovog.

Definitivno utvrdivši da sam ranjen preko WassUp plugin-a, pogledao sam malo dokumentaciju o njemu, i tek tada opazio da na adresi http://wordpress.org/extend/plugins/wassup/ u zvaničnom opisu skroz na vrhu stoji: !USE THIS CODE AT YOUR OWN RISK! Nigde nisam uspeo da pronađem zbog čega je to tako napisano, ali u svakom slučaju mi je još jasnije bilo da je WassUp taj koji je zeznuo stvari. Pogledao sam sve njegove foldere na hostu i video još jedno iznenađenje – svim fajlovima je stajao chmod 755 umesto 644. Kako je došlo do te promene nije mi jasno, ali shvatam da je sa ovim dozvolama neko mogao da upisuje skripte u fajlove. Tada sam pokušao da vratim dozvole kao što su po defaultu, ali time nsiam dobio ništa – i dalje se javljala poruka u panelu. Nakon toga, reinstalirao sam plugin, međutim i dalje bez poboljšanja.

Tada sam primetio još jednu novinu – ulogujem se u admin panel, pa otvorim novi tab i kucam pakito.iz.rs/wp-admin i ono me redirektuje na wp-login.php, iako se predhodno nisam ni izlogovao, niti zatvorio firefox. Sve više i više sam verovao da je neki mnogo bitniji fajl, zaražen malicioznim kodom, te sam rešio da reinstaliram ceo Wordpress. Napravih back up uploads foldera, foldera sa temom koju koristim, kao i back up čitave baze. Nakon toga, obrisao sam sve – i fajlove i bazu.

Reinstalacija je prošla sa nekim minimalnim problemčićima…ali ništa strašno.

Sada je sve u redu, mada nisam instalirao WassUp i ne znam da li ću, s obzirom da sam shvatio da je najverovatnije on napravio problem. Ko zna zašto je sve ovo dobro. Ustvari, naučio sam da je htmlentities() jako bitna funkcija i da je nikako ne smem zaobići,  iako u ovom slučaju nije do toga problem, ali makar sada shvatam šta može da izazove njen nedostatak.