@font-face loader

Zilele trecute am avut nevoie să fac mici ajustări la o pagină în funcție de starea fonturilor custom. Pentru că uneori aceste fonturi sunt mult diferite de orice fallback, iar până în momentul încărcării există un flash enervant.

Cum Typekit nu a fost o opțiune în acest caz, a trebuit să caut alternative. Și am găsit WebFont Loader. Câteva linii de cod scrise în head și aveam totul la locul lui:

var fontsAreLoaded = false;
WebFont.load({
  custom: {
    families: ['UbuntuCondensedRegular'],
    urls: [ 'assets/fonts/custom-font.css' ]
  },
  active: function(){ fontsAreLoaded = true; }
});

Read the rest of this entry »

Cum să numești selectorii CSS

Una din persoanele cu care am colaborat în trecut, mi-a pus doar denumiri de genul red-arrow, green-bullet etc. Totul a fost bine până când clientul a venit cu mici modificări ce țin de culori. Rezultatul arată cam așa:

  • red-cross.png este albastru (o nuanță de fapt)
  • red-bullet.png este verde
  • black-arrow-right.png este galben
  • black-bg.png este gri
  • .red-button este tot albastru
  • .white-button este un gri închis

Și tot așa. Am o mulțime de imagini și selectori CSS care nu (mai) au nici o legătură cu realitatea.

Cum poți preveni astfel de rezultate?

Read the rest of this entry »

Pentru că am fost cuminte, Emag mi-a dat o reducere de 15% la accesoriile și consumabilele pentru imprimante.

Problema este că în momentul de față eu nu am nevoie de nimic pentru imprimantă iar voucher-ul este valabil doar până la 1 mai. Prin urmare, dacă este cineva care are nevoie:  Read the rest of this entry »

Mici proiecte personale

În ultima vreme am început să învăț puțin Backbone și am tot făcut diverse plugin-uri, mergând pe sloganul „scratch your own itch

  1. Un plugin de WordPress ce permite inserarea unei galerii cu video (doar youtube momentan) + imagini în header (sau mă rog, oriunde). Momentan rămâne privat din motive de drepturi de autor.
  2. Youtube Playlists – o modalitate foarte simplă de a integra un playlist Youtube în site-ul tău WordPress. Evident, nu va funcționa cu videos private.
  3. Youtube Embed – un fel de wrapper JS pentru API-ul Youtube.
  4. Per project builds – un plugin pentru Sublime Text 3 ce permite mai multe build-uri pentru un proiect dar și listarea/selectarea unui anume build. Util în cazul în care ai task-uri grunt + un deploy de symfony + alte chestii mărunte.

Renunță la prefixe!

Atunci când încerci să profiți de cele mai noi tehnologii din browsere, va trebui să te descurci inclusiv cu adăugarea prefixelor. O să-ți arăt o modalitate foarte simplă prin care poți evita repetarea codului de cinci ori ( -moz, -webkit, -ms, -o și varianta fără prefix).

CSS

Dacă te încăpățânezi să nu folosești un preprocesor CSS atunci treci peste această parte. Altfel, pentru SASS, poți folosi:

div{ 
  @each $prefix in -moz-, -webkit-, -ms-, -o-, '' {
    #{$prefix}transition-delay:   0s;
  }
}

Rezultatul compilat va fi totuși repetat de cinci ori, dar… altfel nu se poate (decât dacă vrei să folosești -prefix-free).

Mixins

SASS, printre altele, oferă și un fel de funcții (care se numesc mixins). În cazul în care folosești multe proprietăți ce au nevoie de prefixe, poți folosi următorul mixin:

@mixin prefixFree( $key, $value ){
  @each $prefix in -moz-, -webkit-, -ms-, -o-, '' {
    #{$prefix}#{$key}: $value;
  }
}

Pe care îl poți folosi astfel:

div { @include prefixFree( transition, (0.2s opacity ease-in, 0s margin-left linear 0.22s) ); }

JavaScript

Nu putem scăpa de un loop nici aici. M-am inspirat Exemplul este copiat din polyfill-ul pentru requestAnimationFrame*

var vendors  = [ 'ms', 'moz', 'webkit', 'o' ];
for( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x ){
  window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
}

* Dacă ai ceva animații în pagină este musai să le faci cu RAF. De cele mai multe ori vei avea parte de o calitate crescută a animației (smoothness, CPU)

Selector context VS. .find()

Nu de puține ori am văzut cod scris așa:

var parinte = $('#parinte'), 
    alt_parinte = $('#alt-parinte');
parinte.find('.copil');
alt_parinte.find('.alt-copil');

Chiar dacă nu este nimic greșit în acest cod, .find() s-ar putea scrie ceva mai pe scurt, folosind o chestie ce se numește selector context

var parinte = $('#parinte'), 
    alt_parinte = $('#alt-parinte');
$('.copil', parinte)
$('.alt-copil', alt_parinte);

Intern, jQuery folosește cea de-a doua metodă ca scurtătură pentru prima. Teoretic, .find() ar fi mai rapid. Practic, din testele făcute de mine în Firefox și Chrome, diferențele de performanță sunt atât de mici încât sunt neglijabile.

Pe de altă parte, la fiecare select contextual salvezi câte șase caractere. Poate nu pare mult, dar la o aplicație ceva mai complexă poți avea lejer câteva zeci (poate chiar sute) de apelări .find().

Ieri am decis că ar fi cazul să încerc ceva nou: Bing. Am setat chrome să folosească Bing ca motor de căutare implicit și tot ce am căutat am încercat să caut prin sus-numitul motor de căutare. Doar că… socoteala de acasă nu se potrivește cu cea online și am început să observ două chestii:

  1. Relevață ce tinde spre zero. Nu, nu contează că sunt autentificat sau că folosesc Chrome. Cu IE10 sunt FIX aceleași rezultate.
  2. Dacă dezactivezi safe search, Bing Imagini îți găsește o grămadă de porn pentru multe cuvinte.

Chiar dacă google îmi urmărește absolut orice mișcare online, cel puțin pot găsi ce caut.

Ieri a trebuit să fac un preloader pentru un site ce conține foarte multe imagini (peste 50 bucăți, fiecare de minim 100kb). Am zis că dacă tot fac preloader, să fac și un indicator. Și dacă tot le-am făcut, hai să pun și pe blog :)

jQuery(document).ready(function($){
  var allImages     = $('img'),
      totalImages   = allImages.length,
      loadedImages  = 0,
      preloader     = $('<div class="preloadImages">Loading <span></span>%</div>').appendTo('body');

  $(allImages).each(function(i, img){
    var preload = new Image();
    preload.onload = function(){
      $('span', preloader).text( Math.round( loadedImages / totalImages * 100 ) );
      loadedImages = loadedImages + 1;
      if( loadedImages >= totalImages ){
        preloader.fadeOut();
      }
    }
    preload.src = img.src;
  });
});

Este atât de simplu!

Câștigătorii concursului

Dimineață m-am trezit cu chef de dat premii :)

Câștigătorii, în ordinea numerelor de pe tricou, sunt:

2013-01-01_12h00_10

  • George
  • Vlad
  • Alin Nicorici
  • TzaCaNeL
  • Iankulov Miodrag
  • Daniel
  • Cami
  • BeBe
  • Flavius
  • Călin

Codurile vor fi trimise după ce se confirmă adresa de email (este posibil să fi intrat în Spam). Data limită pentru confirmare este de 7 ianuarie. Dacă după această dată nu primesc nici un semn voi rula un nou query pentru codurile rămase (deși sper să nu fie cazul).

Dacă crezi că ai scris adresa de email greșit, lasă un comentariu aici cu adresa corectă.

Vă mulțumesc tuturor pentru participare.

De ce sunt freelancer?

Motivul principal pentru care eu sunt freelancer este că nu-mi plac oamenii! :D

Acum, ceva mai serios: am fost angajat într-un singur loc ca programator dar mulți dintre cunoscuții mei ce lucrează ca programatori au aceleași probleme la locul de muncă:

  • Ședințe inutile, incredibil de lungi;
  • Bugetul pentru documentație (cărți, cursuri etc) este foarte mic, de cele mai multe ori fiind zero;
  • Best tools money can buy? E doar un mit. Cei mai mulți lucrează cu un singur monitor între 19-22inch, 2Gb RAM, video on board și un Celeron (cei mai norocoși au un i3, doar pentru că Celeron-ul a crăpat).
  • Birouri comune, ceea ce înseamnă că șansele să intri în flow sunt la fel ca bugetul pentru cărți. Adică mici. Plus că tot timpul se găsește cineva să te întrebe ceva sau să îți arate ceva sau …

Pe lângă astea, se mai adaugă programul de lucru și deplasarea până la sediul firmei. În funcție de orașul în care lucrezi, pierzi una sau chiar două ore pe drum. Și ești obligat să fii prezent opt ore la firmă. Vreau să văd și eu un programator care este productiv mai mult de șase ore/zi pe o perioadă de timp mai mare de două-trei zile :)