You are viewing an old version of my website. Its contents may not be accurate anymore.
It is still here for archival reasons. Here's the latest and up-to-date version.

 
 

Welkom bij TheHotSeat, pseudoniem voor een Gentse freelance webontwikkelaar. Maar bovenal een blog over webdesign, webontwikkeling en (digitale) vormgeving

view comments

Transistor: radio op de iPhone

21 Nov 2009

Tussen klantopdrachten en freelancewerk door werkten David en ik de afgelopen maanden aan Transistor, onze eerste iPhone applicatie. David als developer, en ik als ontwerper.

transistor iphone app screenshot

Transistor is een eenvoudige radio app geworden waarmee je naar de meestbeluisterde Belgische radiozenders kan tunen op je iPhone en iPod Touch. Het programma is vanaf nu gratis beschikbaar in de iTunes App Store. Transistor is verkrijgbaar in het Nederlands, Frans en Engels en je kan er de onderstaande radiozenders mee streamen.

Nederlandstalige radiozenders:

  • Radio 1
  • Radio 2
  • Studio Brussel
  • Klara
  • MNM
  • Nostalgie
  • Top Radio
  • Be One

Franstalige radiozenders

  • La Première
  • Viva Cité
  • Musiq3
  • Classic 21
  • Pure FM
  • Nostalgie
  • NRJ
  • Fun Radio

Heb je dus zo’n fancy gsm of iPod, laat dan zeker eens weten wat je er van vindt. Het ontwerpen van de user interface van zo’n iPhone programmaatje was trouwens een erg leuke ervaring. Maar daar vertel ik je later wel eens meer over. En nu downloaden maar!

6 reacties


view comments

Een dynamisch schuifregister in code

28 Jan 2009

In een vorige blogpost kon je lezen over het hoe en waarom van een schuifregister. In dit artikel vatten we de koe bij de horens en gebruiken we CSS en jQuery om een dynamisch schuifregister te maken. Voor wie op hete kolen zit: dit is het resultaat en hier vind je een iets stijlvollere variant.

In den beginne was er HTML

We starten met een eenvoudige htmlpagina: een artikel met daaronder lezersreacties. Als je de bron van die webpagina bekijkt, dan zie je dat ik de plaatsen waarnaar het register moet verwijzen heb aangeduid met een id en een class. In dit geval gaat het om twee h1-tags, maar je zou evengoed een combinatie van andere htmltags kunnen gebruiken:

<h1 id="artikel" class="registerknop">Zwart gat</h1>
<
h1 id="reacties" class="registerknop">Reacties</h1

jQuery maakt het wat pittiger

jQuery maakt voor elk element met de class ‘registerknop’ een aanduiding in het schuifregister. Hoe dat in zijn werk gaat kan je hieronder meevolgen. Tussen de code vind je heel wat uitleg, maar ook straks kom ik er nog even op terug.

$(document).ready(function(){
  
//bereken de paginahoogte
  
var pageHeight = $('body').height();
  
//bereken de hoogte van het browservenster
  
var windowHeight = $(window).height();
  
//lengte schuifbalk tov de paginahoogte
  //de pijltjes van de scrollbar nemen ongeveer 41 pixels in beslag
  
var scrollBreuk = (windowHeight-41)/pageHeight;
  
//voor elk element dat de class registerknop meekreeg
  
$('.registerknop').each(function(i{
    
//als het het eerste element betreft
    
if(== 0{
      
//maak een htmllijst aan
      
$('body').prepend('<ul id="schuifregister"></ul>');
    
}
    
//wat is de id van dit element
    
var id = $(this).attr('id');
    
//de positie van dit element vanaf de top van de pagina
    
var yPos = $(this).offset().top;
    
//waar de schuifbalk moet zijn om het element te zien
    //Math.round zorgt voor een afgerond getal zonder decimalen
    //de +3 zorgt voor een net iets hogere scrollbarpositie op Mac (is mooier)
    
var scrollPos Math.round(yPos scrollBreuk) + 3;
    
//voeg een list item aan de lijst toe voor het huidige element
    //accesskey is de eerste letter van de id
    
$('#schuifregister').append('<li><a accesskey="' id[0] '" href="#' id '">' id '</a></li>');
    
//plaats het nieuwste list item op de juiste schuifbalkpositie
    
$('#schuifregister li:last-child').css('top'scrollPos 'px');
  
});
}); 

Zoals je kan zien zoeken we eerst de hoogte van de schuifbalk ten opzichte van de browservensterhoogte. We trekken 41 pixels af van de hoogte van het browservenster omdat dat de ruimte is die de pijltjes van de schuifbalk zelf innemen op een Mac:

de schuifbalk is niet even hoog als de vensterhoogte

Die ingenomen hoogte varieert trouwens een beetje op Windows én de plaatsing is anders. Om goed te zijn zou je die waarde (41) dus moeten laten afhangen van het besturingssysteem van de gebruiker, maar zover heb ik het in dit voorbeeld niet gedreven. (Het kan dus zijn dat dit schuifregister niet helemaal accuraat werkt op Windows computers!)

Soit, terug naar het stukje code van hierboven: nadat we enkele vaste waarden in variabelen hebben opgeslagen, gaat het script op zoek naar elk html element met registerknop als class. Als zo’n element gevonden wordt dan wordt een htmllijst aangemaakt (ul) waarin per registerknop een list item (li) verschijnt. De htmllijst is makkelijk vorm te geven met CSS en kan ontelbaar veel list items bevatten. Zoals je kan zien in het stukje code kan je het schuifregister ook via accesskeys bedienen. (De code hiervoor is weliswaar niet waterdicht.)

De plaatsing van elk list item wordt in het voorlaatste regeltje code afgehandeld.

Plaatsing en vormgeving met CSS

Hoewel we jQuery gebruiken om de plaatsing van elk list item via CSS in te stellen, is de belangrijkste opmaak toch wel apart in een stylesheet terug te vinden. De CSS die nodig is om het schuifregister vorm te geven heb ik telkens in de head sectie van de htmlpagina geplaatst:

ul#schuifregister { 
  
list-stylenone
}
ul
#schuifregister li { 
  
positionfixed
  
font-size.9em
  
right0
  
backgroundurl(pijl.pngno-repeat center right
  
padding-right15px
  
text-transformcapitalize

Het meest opmerkelijke stukje is hier het instellen van de fixed position. Hierdoor blijft elk list item mooi in positie staan als de schuifbalk schuift.

De andere CSS-code die ik in een externe stylesheet heb geplaatst is niet zo belangrijk voor het schuifregister op zich maar zorgt voor de opmaak van de rest van de pagina-elementen. We mogen onszelf nu trouwens wel al eens op de borst kloppen: dit is ons resultaat.

Meeschalen met het browservenster

Het komt aardig in de buurt maar mist nog iets: als de gebruiker het browservenster kleiner of groter maakt, dan klopt de aanduiding van het schuifregister niet meer. Maar met behulp van een vleugje jQuery kunnen we dit makkelijk oplossen: we gieten onze code in een functie toonRegister() die we uitvoeren wanneer het venster geschaald wordt.

Belangrijk is dat we hierbij telkens eerst het schuifregister ook verwijderen om na verloop van tijd geen honderden schuifregisters te zien. Ik schreef hier de welluidende functie verbergRegister() voor:

$(document).ready(function(){
  
//voer de functie toonRegister() uit als de pagina geladen is
  
toonRegister();
    
  
//als het browservenster geschaald wordt
  
$(window).resize(function(){
    verbergRegister
();
    
toonRegister();
  
});

  
//de code van hierboven in een functie gestopt
  
function toonRegister() {
    
var pageHeight = $('body').height();
    var 
windowHeight = $(window).height();
    var 
scrollBreuk = (windowHeight-41)/pageHeight;
    (...)
  
}
    
  
function verbergRegister() {
    
//verwijder de htmllijst en hiermee het volledige schuifregister
    
$('#schuifregister').remove();
  
}
}
); 

Dit is het resultaat. Schaal gerust je browservenster eens door de rechterbenedenhoek vast te nemen en te verslepen. Je zal zien dat de plaatsing van de aanduidingen in het schuifregister telkens mee aangepast wordt aan de nieuwe afmetingen van het venster. Nice!

Een vleugje finesse

Eigen aan blogs en dynamische websites is dat je als ontwerper niet kan voorzien hoe lang de teksten zullen zijn die je klant op zijn website plaatst. Nu lijkt het een beetje onnozel om een schuifregister te hebben op een pagina waar niet gescrold moet worden (deze bijvoorbeeld). Wat meer is: de aanduidingen zijn niet meer helemaal juist. Daarom heb ik nog een bijkomende controle toegevoegd in het stukje javascriptcode die er voor zorgt dat het schuifregister niet getoond wordt wanneer alle belangrijke elementen duidelijk zichtbaar zijn op de pagina:

function toonRegister() {
  
(...)
  
//als alles mooi zichtbaar is dan moet er geen schuifregister te zien zijn
  
if($('.registerknop:last').offset().top windowHeight{
    
$('.registerknop').each(function(i{
    
(...)
  
});

Het resultaat

Dit is het resultaat van het experiment. Bekijk ook deze iets stijlvollere variant. In de broncode vind je nog eens alle code op een rijtje.

Het is een makkelijk aanpasbaar en stijlbaar schuifregister geworden. De gebruiker kan bovendien heel snel doorheen de pagina navigeren met behulp van accesskeys.

Ik ben benieuwd naar jullie bevindingen. Vind je zo’n schuifregister duidelijk en gebruiksvriendelijk? Of denk je dat het net verwarrend werkt?

7 reacties


view comments

Zend Framework en jQuery formuliervalidering

2 Dec 2008

Hoewel ik voldoende vertrouwd ben met php en javascript, voel ik me in de eerste plaats een ontwerper. Dat is ongetwijfeld de reden waarom ik zo hou van frameworks want als ik toch de programmeerkant opga dan laten ze me toe om snel robuuste code te schrijven. Sinds enkele maanden ben ik voor een klant intensief bezig met het Zend Framework voor php en jQuery voor javascript.

Het project waaraan ik werk maakt uitvoerig gebruik van HTML-formulieren (via Zend_Form) en dus is het valideren van de gegevens die een eindgebruiker invult een noodzaak. Een voorbeeldje van formuliervalidering vind je hieronder. Als de gebruiker op de ‘Aanmelden’ knop klikt zonder een paswoord in te vullen, dan wordt het formulier niet verzonden maar verschijnt er een boodschap op het scherm. Het paswoordveld is immers verplicht in te vullen.

een loginscherm met een valideringsmelding

Het Zend Framework zorgt voor goede validering aan de serverkant, maar ik twijfelde over hoe ik de validering zou aanpakken aan de clientkant.

Javascript en php

De meest voor de hand liggende oplossing is natuurlijk het schrijven van javascriptfuncties die de formuliervalidering aan de clientkant voor hun rekening nemen. Maar ik hou er niet van om twee keer code te schrijven met hetzelfde einddoel: één keer in php en één keer in javascript. In een project dat in de maanden na lancering ongetwijfeld nog heel wat aanpassingen zal ondergaan lijkt het me niet aangewezen om telkens zowel de php-code als de javascriptcode te moeten wijzigen wanneer er iets verandert aan een formulier.

Laat Zend_Form de validering maar doen!

Ik heb er dan maar voor gekozen om alles wat betreft formuliervalidering te laten afhandelen door het Zend Framework. Dankzij een jQuery ajax oproep naar de Zend_Form isValidPartial() functie ben ik toch in staat om een gebruiksvriendelijke en snelle validering per formulierveld op het scherm van de gebruiker te tonen.

In de indexAction() van mijn controller regelt het onderstaande stukje code de server-side validering. Niets nieuws voor wie ooit al eens Zend_Form heeft gebruikt. De isValid() functie checkt de input en geeft een foutmelding weer op het scherm van de gebruiker als die ongeldige gegevens in het formulier heeft ingebracht. Pas wanneer alle input geldig is wordt het formulier echt verzonden en de database geüpdatet.

if($this->_request->isPost()) {
  $formData 
$this->_request->getPost();
  if(
$form->isValid($formData)) {
    
//update database
  
else {
    $form
->populate($formData);
  
}

Het nadeel van bovenstaande code is dat de validering pas gebeurt nadat het formulier wordt verzonden. De gebruiker moet dus wachten op een paginavernieuwing alvorens te weten of zijn ingevulde gegevens geldig of ongeldig waren. ‘So nineties!’, hoor ik je roepen. Dat komt inderdaad niet overeen met de snelle responstijd die een gebruiker vandaag verwacht van een webapplicatie.

jQuery to the rescue!

jQuery zal er voor zorgen dat de ingevulde gegevens van elk veld gevalideerd worden op de server net na het invullen van het veld via een Ajax oproep. Zo weet de gebruiker meteen of het veld goed ingevuld is of niet, en dat zonder te moeten wachten op een paginavernieuwing.

jQuery roept daarvoor telkens een tweede action aan in mijn Zend Framework controller. Ik heb die validateformpartial genoemd:

public function validateformpartialAction() {
  
if($this->_request->isPost()) {
    $formData 
$this->_request->getPost();
    if(
$form->isValidPartial($formData)) {
      
//update database
      
$this->view->result true;
    
else {
      
//geeft foutief ingevulde velden weer met hun foutmelding
      
$this->view->messages $form->getMessages(); 
      
$this->view->result false;
    
}
  }

Het verschil zit in de aangeroepen functie: isValidPartial() laat toe om enkel het doorgegeven stukje formdata te valideren. Heb je dus een formulier dat uit 5 velden bestaat en je wil maar 1 veld valideren dan kan dat via isValidPartial(). getMessages() geeft de fouten weer per veld. (Meer informatie over getMessages vind je in de Zend Framework handleiding.)

Belangrijk is wel dat je via je javascript functie enkel json (of xml) terugkrijgt van die Zend Framework action. Je moet dus Zend_Layout en Zend_View uitschakelen voor die ene action. Dat kan makkelijk in de initAction() van je controller dankzij de AjaxContext helper:

$ajaxContext $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('validateformpartial','json')->initContext(); 

Alles wat je in de validateformpartialAction() als variabele aan de view meegeeft (via $this->view->variableName) wordt dan meteen door die functie als json geretourneerd. Dat maakt het makkelijk om die variabelen in jQuery op te vangen en er iets mee te doen. Zo kan je bijvoorbeeld via jQuery per veld tonen welke fout de gebruiker gemaakt heeft tijdens het invullen van het formulier.

Ter vervollediging is hier de jQuery ajax functie die de waarde van het ingevulde formulierveld doorstuurt naar de validateformpartialAction van daarnet uit de Zend Framework controller:

$.ajax({
  type
"POST",
  
//dataString is een string in dit formaat: &naam=johnny&beroep=bouwvakker
  //je geeft dus de value van alle ingevulde formuliervelden die je wil valideren mee
  
data$dataString,
  
//baseUrl bevat het pad naar je webapplicatie
  
urlbaseUrl "/controllernaam/validateformpartial",
  
dataType"json",
  
//showSpinner toont een grafisch element dat de gebruiker er op wijst dat er iets aan het gebeuren is
  
beforeSend: function(){ showSpinner(); }
  
//handleResponse verwerkt de teruggekregen json data en toont de gebruiker het resultaat van de validering
  //hideSpinner() verbergt het grafische element
  
success: function(json){ handleResponse(json); hideSpinner(); }
}); 

That’s it. Door de vele requests naar de server is het misschien niet de meest aangewezen manier om formuliervalidering te doen voor grootschalige webapplicaties, maar voor het project waar ik aan werk is het zeker voldoende. Het systeem zal zelfs op hoogdagen nooit door meer dan 100 gebruikers tegelijk gebruikt worden.

Het grote voordeel is dat de formvalidering overgelaten wordt aan Zend_Form. Eén regeltje wijzigen in je Form class is dus voldoende om zowel je formulier, de ajaxvalidering als de php validering up-to-date te brengen. Geen dubbel javascript valideringswerk dus. Het maakt mijn applicatie een stuk makkelijker te onderhouden.

1 reacties


view comments

Een stijlvol zoekformulier met xhtml en css

23 Sep 2008

Toen ik aan deze website werkte, wilde ik een zoekfunctie die qua ontwerp mooi aansloot bij de rest van de hoofding. Het resultaat kan je zien in de rechter bovenhoek. In deze blogpost kan je lezen hoe de zoekfunctie vormgegeven werd met html en css.

De zoekfunctie is uiteraard een html formulier en daar zit nu net het addertje onder het gras: elke browser heeft zo zijn eigen manier om knoppen en tekstveldjes weer te geven.

Omdat ik het uitzicht van de zoekfunctie in alle grote hedendaagse browsers identiek wilde, heb ik de knop en het tekstveldje vervangen door een afbeelding. Beeldjes worden door elke browser wel identiek weergegeven natuurlijk.

Hieronder vind je de xhtml. Je zal zien dat die vrij eenvoudig is en enkel de basiselementen bevat voor een standaard zoekformulier. Beweeg je muis over het gele vlak om de volledige code te zien:

<div id="omgeving">
 <
div id="search_box">
  <
form method="post" action="#">
   <
fieldset>
    <
input type="text" id="keywords" name="keywords" />
    <
input type="image" src="zoeken-knop.gif" id="submit" alt="Zoeken" title="Zoeken" />
   </
fieldset>
  </
form>
 </
div>
</
div

De buitenste div (‘omgeving’) zorgt straks voor de donkere achtergrond. De submitknop vervangen we zoals je nu al kan zien door een beeldje (zoeken-knop.gif). De bovenstaande htmlcode ziet er zo uit in Firefox:

zoekformulier firefox

Niet erg verrassend natuurlijk. De kern van de vormgeving zit in de css. Om de ruimte voor en na het formulier en de fieldset te doen verdwijnen zette ik de padding van die elementen eerst op 0.

formfieldset {
 padding
0;

De donkere fijne rand die je rondom het formulier ziet is altijd zichtbaar bij een fieldset maar is eenvoudig te verwijderen:

formfieldset {
 padding
0;
 
border0;

De rand en de witruimte rondom de fieldset en het formulier zijn nu verdwenen. Vervelend is wel nog dat op Mac tekstveldjes omrand worden met een blauwe lijn wanneer je ze aanklikt:

outline mac

Dit effect past niet in de huidige vormgeving van de website. Gelukkig kunnen we het snel verwijderen: (Weet wat je doet! Zie lezersreacties op dit artikel.)

input {
 outline
0;

Het donkere vlak waarin het zoekformulier zit is vormgegeven met hele eenvoudige css:

div#omgeving {
 
background-color#333;
 
height80px;
 
width400px;
 
padding30px 0 0 40px;

Dit leverde me het volgende resultaat op:

met zwarte achtergrond

Het tekstvakje zelf moet natuurlijk nog aangepast worden. Het ziet er veel te wit uit en heeft een lelijke rand die dan nog eens verschilt van browser tot browser. Mijn eerste idee was om het tekstveldje zelf via css te gaan stylen, maar op die manier kreeg ik het beeldje van het vergrootglas nooit in het tekstveld zelf. Daarbij kwam dat er nog altijd veel verschillen merkbaar waren tussen de verschillende browsers. Daarom heb ik de volledige zoekfunctie in een div gestopt en aan die div een achtergrondafbeelding meegegeven:

div#search_box {
 
width146px;
 
height22px;
 
backgroundurl(zoeken-achtergrond.gif);
 
margin0;

Hieronder zie je het resultaat. Omdat de search_box niet breed genoeg is om zowel het invulveld als de submitknop weer te geven, springt de submitknop naar een volgende regel.

te smal

Ik moest het invulveld dus kleiner maken. Via de background en border properties zorgde ik er ook voor dat de witte achtergrond en de randen weg zijn. Het invulveld is er nu nog wel samen met al zijn functionaliteit, maar is eigenlijk onzichtbaar geworden.

div#search_box #keywords {
  
width110px;
  
backgroundnone;
  
bordernone;

Dit is nu ons resultaat:

invulveld onzichtbaar

Door de submitknop wat css mee te geven kon ik die ook op z’n plaats doen springen. De float zorgt er voor dat de knop naast het invulveld kan blijven staan.

div#search_box #submit {
  
floatright;
  
margin5px 9px 0 0;
  
width15px;
  
height14px;

Zo ziet het formulier er nu uit wanneer er een zoekterm ingegeven wordt:

form met zoekterm

Het formulier ziet er nu goed uit, alleen staat de tekst daar nog een beetje te zweven. Die moet nog een aantal pixels opgeschoven worden om mooi uitgelijnd te zijn met de submitknop en het invulveld. Ook mag het corps wat groter. Door hier ook een float mee te geven blijven de twee elementen mooi naast elkaar staan en mogen ze indien nodig mekaar een beetje overlappen.

div#search_box #keywords {
  
floatleft;
  
padding0;
  
margin3px 0 0 6px;
  
width110px;
  
backgroundnone;
  
bordernone;
  
font-size.8em;

En dan is dit ons resultaat! Ik was er best tevreden mee en het ziet er identiek uit op Internet Explorer 7 (Windows), Firefox 3 (Windows en Mac), Safari 3 (Windows en Mac), Chrome 1 (Windows) en Opera 9 (Windows):

ziet er goed uit

Alle grote browsers geven het formulier dus identiek weer… behalve Internet Explorer 6 (Win) natuurlijk. Die is nu eenmaal altijd de boosdoener. IE6 geeft het formulier zo weer:

IE6 geeft fout weer

De search_box div lijkt te hoog te zijn waardoor IE6 het achtergrondbeeldje herhaalt. Dit is eenvoudig op te lossen door ‘no-repeat’ aan de background mee te geven:

div#search_box {
  
width146px;
  
height22px;
  
backgroundurl(zoeken-achtergrond.gifno-repeat top left;
  
margin0;

Het formulier ziet er niet alleen goed uit, het blijft ook heel functioneel en gebruiksvriendelijk. Hier kan je het formulier in actie zien, in de broncode vind je nog eens alle code op een rijtje.

4 reacties


Over logo TheHotSeat 

foto Thomas Byttebier pijltje TheHotSeat is Thomas Byttebier, freelance webdesigner en user interface designer.
Op deze website blog ik over alles wat met webdesign en digitale vormgeving te maken heeft. Meer informatie over mij. @bytte op Twitter.

RSS Feed TheHotSeatLaatste blog posts

Laatste reacties

Categorieën

AlleExpressionEngineiPhoneTransistorMarketingSEOOntwerpTypografieOntwikkelingjQueryPHPZend FrameworkOpiniesOverigePhotoshopWebomgeving