Новата ни платформа за онлайн магазини – geeneric.com

От известно време разработваме платформа за онлайн магазини базирана на WordPress и WooCommerce.
Може да създадете вашият онлайн магазин безплатно на geeneric.com

Пишете ми какво мислите за платформата – отворен съм към всякакви идеи за подобрения.

Да спрем да се заблуждаваме с разпознаването на пипащи се (touch) устройства

До всички JS дживелъпъри: Време е да спрем да се самозаблуждаваме. Това, че потребителят има устройство, което поддържа пипане (touch) не значи, че ще го използва само по този начин. Не знаете за какво говоря? Ето:

 var clickEventToUse = ( 'ontouchstart' in window ? 'touchend' : 'click' )

Все още не знаете? Представете си лаптоп с touchscreen (все по-голям брой лаптопи напоследък). Този код принуждава потребителя да използва устройството си само с пипане и прави библиотеката неизползваема за мишка и клавиатура. Сега си представете, че потребителя има втори монитор, който не поддържа touch. Да – за да извършите определено действие трябва да си преместите прозореца на другия екран и да започнете да го пипате. Много извратено! А fix-а може да е нещо супер просто:

function doSomething() {
    // don't look, do something
}
$( 'selector' ).on( 'click', function( e ) {
    doSomething();
}).on( 'touchend', function( e ) {
    e.preventDefault(); // we don't want the click triggered second time, do we?
    doSomething();
});

Време е да оправим положението!

Пускане на асинхронни ajax рекуести към масив от url-и и обработването им наведнъж

Днес имах много интересен случай, в който трябваше да вземем няколко SVG файлове с ajax и после да ги обработим наведнъж когато всички рекуести са готови.

Знам за $.when но съм го използвал само когато броя на рекуестите са фиксиран брой.

Нещо като това тук:

$.when( $.ajax( 'first.svg' ), $.ajax( 'second.svg' ) ).done( function( ajax1, ajax2 ) {
    // do stuff with both things.. as ajax1[0] is the svg document
    // for the first.svg and ajax2[0] is the svg document for the 
    // second.svg
});

Ясно е, че ще ползваме нещо сходно и за това слагаме всеки от ajax извикванията в масив, че да можем да ги добавяме динамично.

// svgUrlArray is an existing array with all the urls of the svgs

// we create a new array with all the ajax calls
var svgAjaxArray = [];

for( var svgIndex = 0; svgIndex < svgUrlArray.length; svgIndex++ ) {
    svgAjaxArray.push( $.ajax( svgUrlArray[ svgIndex ] ) );
}

След това подаваме масива на $.when

$.when( svgAjaxArray ).done( function() {
    // this is executed a bit too early 
});

И хендлъра на done събитието е извикан прекалено рано. Защо?

Защото Array не е Deffered обект – той е просто масив и стойността му е готова за използване веднага (точно като Deffered обект, който се resolve-а веднага при създаването си). И за това done callback-а се извиква веднага.

И какво ни е най-лесното решение тогава?

$.when.apply( $, svgAjaxArray ).done( function() {
    // Now we're talking ;)
    // You must use the arguments variable to get all the entries
    // because you don't know what is the length of the ajaxArray
});

Вече може да обработваме произволен брой от асинхронни заявки и да ги обработваме след като всички са приключили. Array!

Случайни наблюдения над новогодишните цели

Както много народ на тая планета и аз си поставям новогодишни цели. За съжаление успеваемостта ми на тези цели странно-статистически се върти около 30%, колкото гледам е и на Влади рейта, съдейки по неговата публикация.

Тази година реших да променя начина и периода на поставяне на новогодишните цели по 2 причини:

1. Извод до който достигнах тази година е, че не е напълно лошо, че има неща от новогодишните си желания и обещания които не си изпълнил. В моя списък част от целите са станали я безсмислени, я вече са от нищожно значение за мен поради други фактори. И това май е нормално, все пак са вече на цяла 1 година.

2. Тези които продължават да са смислени, но непостигнати (и съответно единственото логично нещо е просто да ги преместиш в новия списък) са неща които изискват доста воля, борбЪ и не винаги резултатите са лесно видими. Точно тези неща най-лесно се изоставят когато те грабне водовъртежа.

Тези ми 2 (две) наблюдения ме подтикват към следните промени:

1. Промяна в поставянето на самите цели:

  • Първо поставям генерални цели или каквито там първи ми дойдат на акъла (като да съм щастлив, успешен…)
  • Пиша си какво за мен е да си / да се чувстваш такъв и как си го представям
  • Тук-таме се питам защо да видя дали няма някоя скрита причина да искам нещо
  • Вече си имам цели и конкретни причини защо искам да ги постигна.

2. План (план за целите винаги имам, но е тотално несъобразен с останалия живот)

  • Тегавите цели искат план както „Козътъ си сака пръч“
  • Планът е съобразен с текущия график
  • и е реалистичен

3. Ревизия (хъхъ) всеки месец.

  • За да ми държат влажно ще си преглеждам целите всеки месец
  • Саморазрешил съм си да добавям и махам цели
  • Планът се прави наново всеки месец

Това ще ми е схемата тая година.. да видим какво ще излезе 🙂

Как да улесним кодърския ни живот със Sublime Text 2

Днес (на 21. Март 2013) в init Lab ще проведем workshop за това как да улесним живота си използвайки хитрините които ни предоставя Sublime Text 2.

Ето ги и слайдовете за презентацията:

 

 

Update на WooCommerce до версия 2 и липсваща информация за продукт в front-end-а

WooThemes пуснаха новият WooCommerce 2.0 наскоро и ъпдейтването изглеждаше доста съблазнително с новия интерфейс и другите красоти в него.

Все пак ъпдейтването не е най-доброто нещо което може да се направи особено ако темата ти е направена за 1.6

Като резултат – след ъпдейта информация като цена и подобни липсваше на началната страница на сайта по някаква причина. Разбира се в администрацията всичко изглеждаше окей и очебийният извод е, че начинът по който е направена темата (дело на самите WooThemes) не работи с новата версия. Също така проверих, но все още нямаше ъпдейт за тази тема.

Хората които са писали тема за по-старата версия най-вероятно са използвали класът WC_Product за да вземат данните за определен продукт. Проблемът тук е, че вече не може да създадете такава инстанция по postID. Най-вероятно това е свързано с новосъздадената функция get_product(), която е слабо документирана в официалната документация и никъде не се упоменава, че заменя конструктора на WC_Product класа.

В моя случай в темата направена от WooThemes имах следния код:

//inside the loop
$_product = &new WC_Product( $loop->post->ID );

Това явно не работеше и за това го смених с новата функция get_product()

$_product = get_product(  $loop->post->ID );

Това е.

Според мен би било добре ако те си ъпдейтваха поне собствените wp теми за да поддържат новата версия.

Дати, време и iOS Safari

Safari на iOS е един от най-добрите мобилни браузъри. Въпреки това има едно нещо в него, което често ме кара да се чудя защо web-app-а ми не работи – JS Date обектът.

Във всеки нормален браузър можеш да създадеш Date обект от низ просто така:

var myDate = new Date('2013-01-21T13:46:20');

Но в Safari (iOS) това просто дава JS грешка.

За да го оправите трябва да използвате добрия стар split() и да направите нещо като това:

//First we split the date string
var iosDateArr = '2013-01-21T13:46:20'.split('[- :T]');
//And use the constructor with 6 args
cDate = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);

Забележете че месеца е намален с 1. Това е защото в този конструктор месеците започват от 0 за Януари и са до 11 за Декември.

Успех с JS програмирВането и по-малко подобни проблеми 🙂

Да помогнем на Камен от StartUP

Update: За съжаление Камен Почина 🙁

Наскоро разбрах, че мой приятел – Камен Сарафов е болен от рядка форма на рак.

Пичът е стойностен човек, който помага усилено за стартъп обществото в България и ще е нелепо да загубим такава личност.

Повече информация на сайта му – kamensarafov.com, а може и директно да дарите през PayPal.

Вече има и дарителки номер – ако искате да помогнете изпратете смс с текст DMS KAMEN на 17 777 на цена 1 лв.

Geolocation на html5 app не работи ако е във fullscreen mode на iOS6

Тези дни видях поредния проблем на iOS6 относно webapps – просто не можеш да използваш getCurrentPosition() ако апликейшъна е добавен на началния екран. Функцията просто виси и не вика никой от callback функциите които са и подаден (нито error, нито success).

Изглежда, че това се случва само ако апликейшъна е във fullscreen mode – т.е. следния мета таг е добавен:

<meta content="yes" name="apple-mobile-web-app-capable" />

Решение?
Махнете го… (lame)

За да подобрите ползваемостта може да скриете address bar-а когато страницата зареди. И гугъл правят същото в html5 версията на google maps. (Работи само при телефони, които като скролнеш се скрива address bar-a).
Само добавете:

    window.scrollTo(0, 1);

Ако бях малко по-подозрителен бих си помислил, че е поредното анти-гугъл-мапс-нещо.

Фолоу ми! 🙂

!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=“//platform.twitter.com/widgets.js“;fjs.parentNode.insertBefore(js,fjs);}}(document,“script“,“twitter-wjs“);