Responsive webdesign met de @content functie uit Sass 3.2

Ik ga er in deze post vanuit dat je vaker met Sass hebt gewerkt. Enige voorkennis wat betreft mixins en variabelen in Sass is vereist.

Sass 3.2, op dit moment nog in pre release, heeft een nieuwe functie die het mogelijk maakt om blokken CSS als ‘content’ mee te sturen in een mixin. Deze @content functie is daarom uitermate geschikt om in te zetten bij het opzetten van een responsive structuur met behulp van media queries.

Voorheen kreeg elk breakpoint een eigen bestand, een partial. Een partial, bedoeld om te worden geïmporteerd, begint altijd met een _ (underscore). Mijn bestandstructuur zag er toen zo uit (versimpeld om het voorbeeld te verduidelijken):

css
    scss
        mediaqueries
            _mobile.scss
            _tablet.scss
            _desktop.scss
        screen.scss
    screen.css
index.html

Screen.scss bevatte de volgende mediaqueries.

    @import mediaqueries/mobile;

    @media only screen and (min-width: 767px) {
        @import "mediaqueries/tablet";
    }

    @media only screen and (min-width: 992px) {
        @import "mediaqueries/desktop";
    }

In dit voorbeeld pas ik het ‘mobile first’ principe toe. Ik gebruik de mobiele stijlen als basis en voeg hier met behulp van media queries de stijlen voor tablets en desktops aan toe. Meer over dit prinicpe kun je lezen in dit boek, ik ga hier nu namelijk niet verder op in.

Op zich niets mis met deze opzet. Je selectors met hun properties en values zijn alleen verspreid over meerdere bestanden. Zou het niet handiger zijn als je je media queries bij je selector kunt houden? Per selector krijg je dan een beter overzicht van de verschillende staten van een element.

De nieuwe opzet van screen.scss:

nav {
    float: left;
    width: 500px;

    @include respond-to(tablet) {
        width: 250px;
    }

    @include respond-to(desktop) {
        float: none;
    }
}

Ik gebruik hier een mixin waarbij ik de variabele gebruik om aan te geven voor welke media query de stijlen bedoeld zijn. Deze mixin kan zo vaak gebruikt worden als nodig en is als volgt opgebouwd:

@mixin respond-to($media) {
    @else if $media == tablet {
        @media only screen and (min-width: 767px) {
            @content;
        }
    }
    @else if $media == desktop {
        @media only screen and (min-width: 992px) {
            @content;
        }
    }
}

Ik gebruik hier een if/else statement om de juiste media query te selecteren. De @content kopieert de stijlen die in de @include worden gedefinieerd.

Je kunt Sass 3.2 Alpha installeren met het volgende commando:

gem install sass --pre

De nieuwe @content functie zorgt er voor dat we meer helderheid in onze responsive structuur kunnen aanbrengen. Niet meer zoeken naar media queries en selectors in andere bestanden maar alle stijlen van een selector gewoon netjes bij elkaar. Bijna sexy nietwaar?

Iets niet duidelijk? Laat een reactie achter.

Posted in Uncategorized | Tagged | Leave a comment

Meerdere Google Calendars synchroniseren op je mobiel

Meerdere Google Calendars synchroniseren op je mobiel is mogelijk.

Ga met je mobiel naar http://m.google.com/sync. Daar kun je per device aangeven welke kalender je wilt synchroniseren.

In het geval van een iPhone moet je je Google Account wel al als exchange account hebben toegevoegd.

Posted in Google, iPhone | Leave a comment

Oplossing voor wanneer een transparante link over een flash object niet werkt

Gebruik een transparante gif als achtergrond afbeelding voor je link:

.flash-wrapper a { background: url(x.gif) no-repeat -1px -1px; }

Voorwaarde is wel dat de wmode parameter van je flash object op ‘transparent’ staat. Anders kun je sowieso geen HTML elementen over een flash objecten plaatsen.

Posted in CSS, Flash, HTML | Leave a comment

Handleiding voor het installeren van Node JS en Node.io op Mac OSX 10.7

Alle begin is moeilijk. Zo ook wanneer je Node JS en Node.io aan de praat probeert krijgen op je Mac.

Dit zijn de stappen die ik heb ondernomen om het geheel werkend te krijgen op mijn OSX 10.7 (Lion) installatie.

Stap 1: Installeer Xcode
Xcode kun je downloaden via de Mac App Store. Enige wat je nodig hebt is een Apple ID.
http://itunes.apple.com/nl/app/xcode/id497799835?mt=12.

Stap 2: Installeer Homebrew
Homebrew is een package manager waarmee we zometeen Node JS kunnen installeren.
Open een Terminal en voer het volgende command uit:

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

Voor een uitgebreidere installatie omschrijving zie:
https://github.com/mxcl/homebrew

Stap 3: Installeer Node
In dezelfde terminal die we in stap 2 hebben gebruikt voer je het volgende command uit:

$ brew install node

Als het goed is geeft Homebrew een melding met je NODE_PATH. Deze hebben we zometeen nodig.

Stap 4: Controleer of Node succesvol is geïnstalleerd
Voer onderstaand commando uit in de Terminal:

$ node -v

Wanneer je nu een versienummer te zien krijgt is Node goed geïnstalleerd.

Stap 4: NODE_PATH instellen
Het instellen van je NODE_PATH is nodig zodat alle Node modules weten waar ze Node zelf kunnen vinden. Voer onderstaand commando uit in de Terminal. Dit opent de nano teksteditor waarmee we ons .bash_profile bestand kunnen bewerken.

$ nano ~/.bash_profile

Kopier vervolgens onderstaande regel in de nano editor:

export NODE_PATH=/usr/local/lib/node_modules

Sla het bestand op met Ctrl+X, Yes, Enter.

Stap 5: Installeer NPM (Node Package Manager)
Voer het volgende command uit in de Terminal:

$ curl http://npmjs.org/install.sh | sh

Als het goed is krijg je “It worked” te zien. Kan zijn dat er ook een WARN melding komt maar dat is niet erg.
Een uitgebreidere installatie omschrijving zie:
https://github.com/isaacs/npm#readme

Stap 6: Controleer of NPM succesvol is geïnstalleerd
Voer onderstaand commando uit in de Terminal:

$ npm -v

Wanneer je nu een versienummer te zien krijgt is NPM goed geïnstalleerd.

Stap 7: Installeerd Node.io
Voer onderstaand commando uit in de Terminal. De -g staat voor global. Je kunt namelijk ook node_modules alleen lokaal installeren. Met de -g parameter kunnen we straks node.io aanroepen vanuit elke pad.

$ sudo npm install -g node.io

Stap 8: Controlerer of Node.io succesvol is geïnstalleerd
Voer onderstaand commando uit in de Terminal:

$ node.io -v

Wanneer je nu een versienummer te zien krijgt is Node.io goed geïnstalleerd.

Stap 9: Doe een dansje
Happy coding!

Posted in Node JS, Node.io, OS X | Leave a comment

OS X Lion: Bibliotheek/Library map zichtbaar maken.

Wanneer je in Lion via Finder op zoek gaat naar je persoonlijke Bibliotheek map zul je deze in eerste instantie niet vinden. Dit komt omdat Apple er voor gekozen heeft om deze standaard te verbergen. Met behulp van Terminal (Programma’s >Hulpprogramma’s) kun je de Bibliotheek echter zichtbaar maken. Typ in Terminal daarvoor het volgende commando en druk op Enter.

chflags nohidden ~/Library/

Na het uitvoeren van dit commando is je Bibliotheek map direct zichtbaar. Mocht je deze weer onzichtbaar willen maken typ dan het volgende commando en druk op enter:

chflags hidden ~/Library/

 

Posted in Lion, OS X | Leave a comment

Alexander – Truth

Waarom ik nooit eerder van deze artiest heb gehoord is mij een raadsel. Wat een briljant nummer met een fantastische video. Echte soul, vanuit het hart geschreven. Met hier en daar wat country, pop en reggae invloeden een nummer dat gemakkelijk de hele dag op repeat kan blijven staan. De beste man mag er dan wel uitzien als een hippie maar vanaf vandaag is Truth van Alexander Ebert mijn favoriete nummer. Misschien dat het even duurt voordat je de rest van zijn cd Alexander kan waarderen maar voor liefhebbers van de indie stroming zeker de moeite waard!

Download het album Alexander via iTunes: http://itunes.apple.com/us/album/alexander/id421075914

Via zijn website kun je trouwens een extra versie van Truth feat. The RZA downloaden. Deze kun je ook beluisteren op Soundcloud. Als bonus kun je ook een remix van Truth door de White Arrows downloaden.

Posted in Music | Leave a comment

Custom jQuery :parents selector

Stel je hebt de volgende HTML waar je de elementen met de class .foo en .bar wilt selecteren maar alleen als deze niet .baz als parent hebben.


<div class="foo" /><!--match-->
<div class="bar" /><!--match-->
<div class="baz" /><!--geen match-->
    <div class="foo" /><!--geen match-->
</div>

Je zou dit kunnen oplossen met de volgende selector:

$('.foo:not(.baz .foo),.bar:not(.baz .bar)');

Bovenstaande selector is niet bepaald elegant te noemen en is bijzonder traag als je deze gebruikt in een gecompliceerde html structuur.

Een betere oplossing is om een custom selector te maken:

jQuery.expr[':'].parents = function(a,i,m){
    return jQuery(a).parents(m[3]).length < 1;
};

$('.foo,.bar').filter(':parents(.baz)');

Een werkend voorbeeld:

Posted in Javascript, jQuery | Leave a comment

jQuery events: stop met het gebruik van ‘return false’

Meestal een van de eerste dingen die je leert als je met jQuery events aan de slag gaat is het stoppen van het standaard gedrag van een browser. In de uitleg voor het click event kun je het volgende tegen komen:

$('a.clickme').click(function() {
    $('#mydiv').show();
    return false; // zorgt ervoor dat de browser de link niet volgt
});

Deze functie toont het #mydiv element en stopt daarna het standaard gedrag van een browser door de href van de link niet te volgen.

Het gebruik van return false is hier eigenlijk niet goed en veel beginners zullen door dit voorbeeld return false gaan gebruiken als ze het standaard gedrag van een browser willen stoppen. Ik zal twee belangrijke onderwerpen over het stoppen van browser events behandelen:

  • Gebruik de juiste methode: return false vs. preventDefault,  stopPropagation en stopImmediatePropagation.
  • Bovenaan, in het midden of onderaan: waar in de event callback moet je het standaard gedrag van de browser stoppen?

Let op: wanneer ik het heb over event bubbling dan bedoel ik dat events eerst worden uitgevoerd op het originele DOM element en vervolgens omhoog op elk parent element in de DOM structuur. Events bubbelen niet naar siblings of child elementen. Wanneer events naar beneden bubbelen heet dit event capturing.

Gebruik de juiste methode

De belangrijkste reden dat return false op deze manier wordt gebruikt is omdat het lijkt te doen wat we willen bereiken. Links worden niet gevolgd, formulieren worden niet gesubmit, etc. Waarom zouden we het dan niet gebruiken?

Wat return false precies doet

Wanneer return false wordt aangeroepen gebeuren er drie dingen:

  • event.preventDefault()
  • event.stopPropagation()
  • Stop de uitvoering van de callback

Maar wacht even, zul je vast denken. Ik heb alleen maar de eerste actie nodig om standaard browser gedrag te stoppen…

De enige van bovenstaande drie acties die nodig is om het standaard van een browser gedrag te stoppen is preventDefault(). Tenzij je het bubbelen van het event (propagation) wilt stoppen kan return false voor verwarring zorgen. Een voorbeeld om het wat duidelijker te maken:

De HTML voor het voorbeeld:

<div class="artikel">
    <h2><a href="#">Titel</a></h2>
    <div class="content">...</div>
</div>

Wanneer er op de link in de h2 wordt geklikt vullen we de div.content met tekst:

$('.artikel h2 a').click(function() {
	$(this).parent().next().html('Tekst voor in content');
	return false;
});

Tot nu toe gaat het goed. Maar we willen ook graag de class “active” toevoegen aan elke div.artikel waar op wordt geklikt (of wanneer er op een child element van div.artikel wordt geklikt). Daarom maken we een extra handler voor het click event:

$('.artikel').click(function() {
	$(this).addClass('active');
});

Werkt dit wanneer we op de link in het h2 element klikken? Nee! De reden waarom dit niet werkt is omdat we return false hebben gebruikt. return false betekent namelijk event.preventDefault(); event.stopPropagation(); en het click event zal dus nooit omhoog bubbelen naar div.artikel waardoor het click event nooit zal worden uitgevoerd.

Wat willen we dan wel?

preventDefault()
In de meeste gevallen waar je voorheen return false voor zou gebruiken is e.preventDefault() een betere keuze. Wanneer je preventDefault gebruikt moet je de event parameter wel beschikbaar stellen in je callback:

$('a.clickme').click(function(e) {
	e.preventDefault(); // e == ons event
});

Dit doet precies wat we willen zonder dat andere elementen het click event niet meer ontvangen.

stopPropagation()
Soms wil je alleen het bubbelen van het event (propagation) stoppen. Een voorbeeld:

<div class="artikel">Een stukje tekst met <a href="#">een link</a> en nog wat meer tekst.</div>

Stel, je wilt dat er iets gebeurd wanneer er ergens in het div element wordt geklikt maar je wilt ook dat de link wordt gevolgd als er op wordt geklikt.

$('div.artikel').click(function() {
	// doe iets
});

$('div.artikel a').click(function(e) {
	// het standaard browser gedrag wordt niet gestopt
	// en het event bubbelt niet omhoog
	e.stopPropagation();
});

Als we in dit voorbeeld return false hadden gebruik zou het click event op div.artikel nooit worden uitgevoerd maar de gebruiker zal ook nog naar de link worden gestuurd.

stopImmediatePropagation()
Deze methode stopt de uitvoering van het event, ook voor alle andere handlers. Alle events voor een bepaald element worden uitgevoerd in de volgorde waarin ze zijn gezet. Een voorbeeld:

$('div a').click(function() {
	// doe iets
});

$('div a').click(function(e) {
	// doe nog iets
	e.stopImmediatePropagation();
});

$('div a').click(function() {
	// dit wordt nooit uitgevoerd
});

$('div').click(function() {
	// dit wordt nooit uitgevoerd
});

Dit voorbeeld lijkt een beetje teveel van het goede maar je zult dit regelmatig tegen gaan komen. Hoe meer ingewikkelde code je schrijft hoe vaker nieuwe onderdelen events aan elementen zullen gaan hangen. Het is dan bijzonder handig als je weet hoe stopImmediatePropagation werkt!

return false
Gebruik return false alleen als je het resultaat van preventDefault() en stopPropgation() wilt en je code het toelaat om het standaard gedrag van een browser pas aan het einde van je callback te stoppen.

BOVENAAN, IN HET MIDDEN OF ONDERAAN

Omdat je tot nu toe altijd return false hebt gebruikt stond dit altijd aan het einde in je functie omdat hier na verder geen code meer hoefde te worden uitgevoerd. Met e.preventDefault() hebben we meer opties. Het kan op elke plek in de callback worden uitgevoerd. Maar waar kunnen we het dan het beste plaatsen?

1. Tijdens de ontwikkelfase moet het (bijna) altijd bovenaan staan
Wanneer je een AJAX formulier wilt versturen en dit geeft een Javascript error wil je natuurlijk niet dat het formulier je naar de volgende pagina stuurt voordat je de fout hebt gevonden.

2. In een live omgeving en je volgt het progressive enhancement principe, zet het dan onderaan in de callback of aan einde van je code.
Als je de gebruiksvriendelijkheid van een pagina wilt verbeteren door het gebruik van Javascript dan heeft het click event van je link of het submit event van je formulier als het goed is de juiste server side fallbacks voor wanneer een browser geen Javascript ondersteund (of uit heeft staan). Het voordeel hier is echter niet voor wanneer Javascript uit staat maar voor wanneer je code een fout bevat als Javascript aan staat. Een voorbeeld:

var data = {};
$('a').click(function(e) {
	e.preventDefault(); // stop het standaard gedrag

	// zorgt voor een fout want 'data.link' bestaat niet
	$('body').append(data.link);

	// De link op de a als server side fallback werkt nu niet meer en voor de gebruiker gebeurd er nu niets!
});

Nu een voorbeeld wanneer we preventDefault() onderaan plaatsen:

var data = {};
$('a').click(function(e) {
	// zorgt voor een fout want 'data.link' bestaat niet
	$('body').append(data.link);

	// Deze regel wordt nog bereikt
	// Maar de href op de link wordt als fallback gebruikt

	e.preventDefault(); // stop het standaard browser gedrag
});

Hetzelfde geld voor het submit event voor formulieren, mits je een juiste fallback hebt gebruikt. Reken er nooit op dat je code altijd werkt. Het is veel beter om een goede fallback te hebben dan er vanuit gaan dat er nooit fouten zullen optreden!

3.  In een live omgeving en alle functionaliteit maakt gebruik van Javascript
Het hoeft niet persé op de eerste regel te staan maar het moet zo vroeg mogelijk in je code logica worden aangeroepen. Wanneer een functionaliteit ten eerste al is toegevoegd met Javascript dan zou een fallback niet eens echt nodig moeten zijn. In dit geval kun je het daarom het beste zo vroeg mogelijk aanroepen zodat je geen onnodige # karaters in je URL krijgt of je pagina op en neer springt. Zorg er natuurlijk wel altijd voor dat je gebruikers genoeg feedback krijgen wanneer er iets fout gaat!

CONCLUSIE

Denk er aan dat je return false alleen gebruikt als het echt nodig is en zorg er voor dat je het standaard gedrag van een browser op de juiste plek in je callback stopt. Zet je code zo flexibel mogelijk op en stop met het onnodig gebruiken van return false!

Posted in Javascript, jQuery | Leave a comment

2 manieren om meer uit je gmail adres te halen

Gmail heeft 2 verborgen manieren om meer uit je e-mail adres te halen. Als je een gmail adres kiest kun je namelijk meer krijgen dan alleen jouwnaam@gmail.com. Hier zijn twee manieren om je gmail adres aan te passen en toch gewoon je e-mail te ontvangen:

  • Plak een plus teken (“+”) gevolgd door een willekeurige combinatie van woorden en letters aan het einde van je email adres. Is jouw e-mail adres bijvoorbeeld ‘janpieter@gmail.com’ dan kun je daar ‘janpieter+nieuwsbrieven@gmail.com’ van maken. Deze alias komt gewoon in je normale inbox terecht.
  • Voeg op elke gewenste plek in je e-mail adres een punt (“.”) toe. Gmail herkent een punt namelijk niet als een karakter. Je kunt daarom zeggen dat je e-mail adres ‘jan.pieter@gmail.com’ of ‘jan.pie.ter@gmail.com’ is zonder je zorgen te maken dat je e-mail niet aankomt.

Het is nu erg handig om nog gemakkelijker filters toe te passen op de verschillende varianten van je e-mail adres. Zo kun je automatisch je inkomende e-mail labelen of archiveren. Ook kun je nu gemakkelijker controleren of je e-mail adres is doorgegeven zonder dat je daar toestemming voor hebt gegeven.

Posted in Gmail | Leave a comment

Ping uit iTunes verwijderen

Wil je Ping uit iTunes verwijderen dan heb je 2 opties.

Optie 1 is via een klein programmaatje genaamd No-Ping. Open het programmatje en klik op hide Ping en iTunes zal herstarten zonder Ping. Met show Ping kun je Ping weer activeren. No-Ping verwijdert de Ping-knoppen en de Ping-zijbalk. Wil je ook de Ping optie in het navigatiemenu verwijderen dan zul je de gehele iTunes store moeten uitschakelen.

Een alternatief is Secrets. Hiermee kun je ook de Ping-knoppen en Ping-zijbalk verwijderen.

Optie 2 zijn de handmatige Terminal commando’s.

Om de zijbalk te verwijderen geef je het volgende commando en herstart je daarna iTunes:

defaults write com.apple.iTunes disablePingSidebar 1

Om de zijbalk weer te tonen geef je het volgende commando en herstart je daarna iTunes:

defaults write com.apple.iTunes disablePingSidebar 0

Om de Ping-knop achter de muzieknummers weg te halen geef je het volgende commando en herstart je daarna iTunes:

defaults write com.apple.iTunes hide-ping-dropdown -bool TRUE

Om de Ping-knop weer te tonen geef je het volgende commando en herstart je daarna iTunes:

defaults write com.apple.iTunes hide-ping-dropdown -bool FALSE
Posted in iTunes, Ping | Leave a comment