Category Archives: технология

SVG filters and CSS animations don’t play together well in WebKit

от Гонзо
лиценз CC BY-NC-SA

There is one particular day in my life that went into reading everything I could find about applying SVG filters on HTML content in Webkit/Blink and pulling my hair why didn’t my code work. See, I had an element with a SVG filter applied as a URI reference and the filter didn’t appear in Chrome and Opera. I tryed embedding the filter definition into the HTML – didn’t work, I tryed recreating the filter with the filter functions available in CSS – could’t create the same effect, but filters did work. Thet I noticed that the filters shows up while the JavaScript is loading, and after disabling JS throu DevTools the filter was there. And after toggling every single piece of JavaScript on the website on and off I managet to pinpoint the cause of my trobbles – a function that applied a class to the body that triggered an animation on a element that is siblink to the one with the SVG filter applied. Then I remembered reading about Chrome not using the GPU for SVG filters applied with URI, but using it for the shortcut functions in CSS. And then I knew – when applying the animation, Chrome rendered the whole container with the GPU and the SVG filter disappeard. And I did try to use 2d functions for the animation, but Chrome still used the GPU and broke the filter. So, if you ever try to use complex SVG filters together with CSS animation, be prepared for trouble!

I know what you did onbeforeunload

от Гонзо
лиценз CC BY-NC-SA

There are a couple of questions on StackOverflow about distinguishing download links in onbeforeunload event handler, the usual use case being skipping loading animation. The simple solution is to use the download attribute on the link itself, but this can’t be applied for forms. I had the same problem and fortunately I found a solution.

What I did was the obvious thing of checking the properties of the event object, passed to the handler. In Firefox there is explicitOriginalTarget property and when the event is triggered by a form submission, the property is a reference to the submit button (if the form is submitted by pressing the button). In Chrome there is no such property, but there is another one that does the job – srcDocument.activeElement. This also points to the submit button of the form. Internet Explorer on the other hand does not have any of these shortcuts, so I had to use the long reference event.currentTarget.document.activeElement.

So what I did was add a data-download attribute to the form and check for it in the onbeforeunload handler like this:

window.onbeforeunload = function (e) {
  var target = e.currentTarget.document.activeElement;
  if ( target.form ) {
    target = target.form;
  }
  if ( ('getAttribute' in target) && 
       (target.getAttribute('download') != undefined || 
        target.getAttribute('data-download') != undefined) ) {
    return;
  }
  // Show loading spinner or do whatever you need to.
};

The above code does two things – polyfill browsers that don’t support the download attribute and apply similar logic to forms. It works in IE 9, 10, 11 and Edge, latest Firefox and Chrome.

Responsive header images with WordPress

от Гонзо
лиценз CC BY-NC-SA

Големите картинки, заемащи почти целия екран от доста време са на мода, но освен да впечатляват потребителя, те могат и доста да го изнервят докато чака да се заредят. Проблемът става съвсем явен когато потребителя разглежда сайта на екрана на телефона си, особено ако на мястото на което се намира няма 3G покритие. За решаването на този проблем на помощ идват отзивчивите картинки.

Годината е вече 2016та, най-популярните браузъри от доста време поддържат srcset, sizes и picture, така че няма причина да не ги използваме. А с новата версия 4.4 на WordPres това е още по-лесно. Не че с предишните беше трудно, просто трябваше да се инсталира разширението RIGC Responsive Images.

И така, постановката е проста, в горната част на сайта, под главата или като част от нея, искаме да поставим голяма картинка, която да заема цялата ширина на екрана. Освен това сайтът ще е с отзивчив дизайн, все пак е 2016 година вече. До тук нищо сложно, но като погледнем картинката с пропорции 16:9 на екрана на телефона в портретен режим и виждаме, че нещо е е така. Тогава сигурно бихме искали картинката също да е в портретен режим или поне да отива към квадрат, може би да увеличим основния елемент в нея. За да решат този проблем, хората от Responsive Images Comunity Group измислиха елемента picture.

Веднага ви давам пример:

<picture>
   <source media="(min-width: 45em)" srcset="large.jpg">
   <source media="(min-width: 32em)" srcset="med.jpg">
   <img src="small.jpg" alt="">
 </picture>

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

За да направим заглавната картинка в WordPress да използва елемента picture първо трябва да накараме WordPres да създава варианти на картинката с необходимите ни размери:

function image_sizes() {
   add_image_size( 'image-big', 1920, 1080, true );
   add_image_size( 'image-medium', 1024, 768, true );
   add_image_size( 'image-small', 480, 480, true );
 }
 add_action( 'after_setup_theme', 'image_sizes' );

След това идва интересната част. Тук предполагам, че темата вече поддържа custom-header. В предишните версии на WordPress заглавната картинка се показва обикновено с функцията header_image(). Но в най-добрия случай с тази функция ще получите img елемент с атрибути srcset и sizes, което не е това, което искаме. За да можем да използваме дефинираните от нас размери на картинки първо трябва да вземем ID на картинката и след това да използваме wp_get_attachment_image_src() за искания размер. Ако търсите начин да вземете ID на заглавната картинка в codex-а, няма да намерите (поне аз не успях), но един преглед на кода на WordPress веднага ще ви посочи get_custom_header() като решение на проблема. Накрая получаваме това:

<?php
 $header = get_custom_header();
 ?>
 <picture>
 <?php
 $src = wp_get_attachment_image_src()( $header->ID, 'image-big' )[0];
 ?>
 <source media="(min-width: 1024px)" src="<?php echo esc_attr($srcset); ?> />
 <?php
 $src = wp_get_attachment_image_src()( $header->ID, 'image-medium' )[0];
 ?>
 <source media="(min-width: 480px)" src="<?php echo esc_attr($srcset); ?> />
 <?php
 $src = wp_get_attachment_image_src()( $header->ID, 'image-small' )[0];
 ?>
 <img src="<?php echo esc_attr($src); ?>" />
 </picture>

Това е добре, но има един недостатък – една и съща картинка се сервира при доста голям диапазон от размери на екрана и съответно в доста случаи ще натовари клиента с излишен трафик и браузъра с по-тежко преоразмеряване на голяма картинка. Решението е на всеки source елемент вместо една картинка със src да подадем набор от размери чрез srcset. Тук на помощ идва функцията wp_get_attachment_image_srcset, която е нова в WordPress 4.4, в по-ранни версии може да се използва чрез разширението RICG Responsive Images. Тя връща srcset атрибут със всички дефинирани размери картинки със същата пропорция като подадения като втори параметър размер.

<?php
 $header = get_custom_header();
 ?>
 <picture>
 <?php
 $srcset_value = wp_get_attachment_image_srcset( $attachment_id, 'header-image-small' );
 $srcset = $srcset_value ? ' srcset="' . esc_attr( $srcset_value ) . '"' : '';
 ?>
 <source media="(min-width: 1024px)" <?php echo $srcset; ?> />
 <?php
 $srcset_value = wp_get_attachment_image_srcset( $attachment_id, 'wide-big' );
 $srcset = $srcset_value ? ' srcset="' . esc_attr( $srcset_value ) . '"' : '';
 ?>
 <source media="(min-width: 600px)" <?php echo $srcset; ?> />
 <?php
 $srcset_value = wp_get_attachment_image_srcset( $attachment_id, 'square-medium' );
 $srcset = $srcset_value ? ' srcset="' . esc_attr( $srcset_value ) . '"' : '';
 ?>
 <source <?php echo $srcset; ?> />
 <img src="<?php echo esc_attr(wp_get_attachment_image_src($attachment_id, 'header-image-base', false)[0]); ?>" />
 </picture>

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

Малко полезни разширения

Вече споменах RIGC Responsive Images, официалното разширение добавящо поддръжка за отзивчиви картинки в WordPress. От версия 4.4 вече е част от самия WordPress, но можете да го използвате, за да активирате лесно picturefill или заради добавянето на подобрена компресия на картинките.

Докато работите върху сайта и се опитвате да прецените какви точно пропорции на картинките ще подхождат на различните екрани и какви размери картинки да генерирате, неизбежно ще ви се наложи да променяте набора от размери, които искате WordPress да генерира. Тогава на помощ идват разни разширения, които регенерират различните размери картинки. След няколко проби аз се спрях на Image Regenerate & Select Crop.

Когато започнете да качвате картинки бързо ще забележите, че автоматичното оразмеряване не винаги работи добре и често ще имате нужда ръчно да отрежете картинка така, че да се вижда най-добре дадена част от нея. Тук на помощ идва Manual Image Crop – това разширение ви позволява ръчно да изберете как да се отреже всеки регистриран размер на картинката.

LTO barcode labels

от Йордан Радунчев
лиценз CC BY

Не е достатъчно да се прави бекъп редовно. Необходимо е архивираните данни да са лесно достъпни и бързо откриваеми, представяте ли си да се наложи да претърсите 50 касети по 2.5TB, докато откриете файла, който ви е необходим? Модерните системи за бекъп поддържат подробни каталози на архивираните данни - кое на коя касета се намира. За това е важно касетите да са надлежно надписани. Най-добре с баркод, който самата система за архивиране може да чете и обработва. Всеки производител на касети за бекъп предлага и етикети за тях. Цветни, нарязани, готови за лепене. Почти идеални, само с един недостатък: невъзможност за "персонализиране". Няма как да се кодира собствена схема за обозначаване на касетите. Не е гот. Естествено има и много комерсиален софтуер за генериране и печатане на баркодове. Естествено има и много безплатен и свободен такъв. Като barcode. С него и малко bash магия ще си напечатате колкото си искате етикета за бекъп касетите по каквато си искате схема. Етикета на моите касети за ежедневни архиви започва с D (daily), има петцифрен пореден номер и, съгласно възприетите практики, завършва с L6, понеже е LTO6. Този bash код ми генерира една страница А4 с 57 етикета на нея:

for ((i=1; i<=57; i++)); do printf "D%05dL6n" $i; done | 
barcode -u mm -t 3x20 -g 79x17 -o label.ps -e code39 -p 210x297 -m 3,2 -c

Изглеждат ето така:

LTO6 Labels - Daily

Github, отвори се!

от Йордан Радунчев
лиценз CC BY

Един alias в моя alias_git, който може да ви се стори интересен и полезен, може да се използва и като добър пример за използването на pipes на командния ред в Линукс, и като илюстрация на sed. С този alias от командния ред отварям в браузъра github страницта на репозиторито в което работя в момента.

alias gh="git config --get remote.origin.url | sed 's/git@/https:///g;s/:///g;' | xargs /usr/bin/chromium %U 1>/dev/null 2>&1 &"

Отделните стъпки са следните:

Взимам URL-а на репозиторито така както е дефинирано в config-а:

git config --get remote.origin.url

Със sed заменям ':' с '/' и 'git@' с 'https://' в URL-а:

sed 's/git@/https:///g;s/:///g;'

Резултата подавам на chromium с помощта на xargs:

xargs /usr/bin/chromium %U 1>/dev/null 2>&1 &

Разбира се, има какво да се подобрява - например какво се случва, ако го използвам в обикновена директория, а не в репозитори? Правилно - отваря ми празен браузър. А може да се сложи проверка и да не се отваря изобщо нищо. Ето нещо над което да поработите.

Васил Левски – украинец?!

от Йордан Радунчев
лиценз CC BY

От няколко дни сме свидетели на борбата на украинците - борят се да изтръгнат родината си от прегръдката на руската мечка, борят се да останат част от Европа, а не отдел от азиатския департамент на имперската канцелария. Всички следим новините от там, наясно сте, да не ви обяснявам и да изпадам в патетични излияния.

В Украйна, както е известно на всеки български патриот и родолюбец (а дали?), има огромно множество хора, които се определят като българи по националност и етническо самосъзнание. Толкова огромно, че правото им да се наричат българи е признато от държавата и си имат собствено политическо представителство в парламента, както и редица други права като училища на български и т.н. В събота, в предаване по БНТ (или бТВ), водещия включи директно по скайп един от българските депутати в украинския парламент. Естествено по повод събитията в Украйна след решението на парламента им да завие към Русия, вместо към Европа. Първият още въпрос беше - А какво мислят българите в Украйна, каква е тяхната позиция? И от отговора аз лично получих едновременно просветление относно исконната същност на българската душевност и сърдечен удар. Българските депутати в украинския парламент... подкрепят решението за по-тесен съюз и обвързване с Русия, за сметка на влизането на Украйна в ЕС. Толкоз. Защо? Защото по времето на СССР имали сигурност, имало грижа на държавата за тях, имало отворени читалища във всяко село, имало работа, имало ред - за всичко това се грижела СССР. И тука ми светна. Чакай! Този отговор съм го чувал! Това е стандартната мантра на всеки червен носталгик, осъзнат или латентен комунист, у нас, в България! Тези хора са наистина българи, Господи! Макар и от векове откъснати от България, че как да мислят друго? Те са българи.

Нали сте говорили с червени носталгици? Всичко, в края на всичко, се свежда до едно, всеки пример за това колко анти-човешка идеология е комунизма се парира с едно: Абе да бе, абе може да е било сякакво при Живков, ама поне е имало СИГУРНОСТ, поне НЕ НИ СЕ Е НАЛАГАЛО ДА МИСЛИМ за работа, НЕ НИ СЕ Е НАЛАГАЛО ДА МИСЛИМ за прехрана. Това е, драги. Това е истината - българина най-МРАЗИ да мисли. Той мечтае да не му се налага да МИСЛИ. Някой друг да мисли за него - за читалищата му, за културните му домове, за работата му, за всичко. Ама за всичко! Нали помните оня виц за Тодор Живков, в който открива нова детска градина? "Партията ви направи детска градина, хо хо хо!" - "Ама, другарю Живков, ние деца нямаме..." - "Е па и деца ше ви направи партията хо хо хо хо!" И всички дружно се смеем... Ама не е виц. Не съм убеден, че е виц. Това е еманация на най-дълбокото и съкровено желание на българина. ДА НЕ МИСЛИ ЗА НИЩО. Като прасе в кочина. Сипват му помия, чистят му от време на време, макар и рядко, лайната. На завет е. Е, не са идеални условията, може и по-добре да се живее, нали... ама НЕ НИ СЕ НАЛАГА ДА МИСЛИМ! Ако трябва по-добре да живеем, ще ни се наложи да мислим сами за себе си. Да, там някакви някъде по света по-добре живеят, ама пък то живот ли е тяхното бе - НАЛАГА ИМ СЕ ДА МИСЛЯТ!!

И в България, и в Украйна и на всякъде по света българинът си е българин. Можеш да го присадиш в какви ли не условия, ще вирее... издръжлив е. И при комунизъм, и при капитализъм, и при монархия, и при демокрация, и на течение... Само не го карай да мисли! Сакън. Истинският българин не мисли! Мрази да мисли. И не мисли.

Да ме прощават патриотите, но всичките им кумири - и Паисий, и Раковски, и Ботев, и Левски, и Бенковски, и Захари Стоянов - всички те очевидно не са българи. Всички вкупом не издържат теста по българщина. Те са имали отчетливо изразени вредни склонности към мислене. Толкова ярка анти-българска черта. Били са украинци... най-вероятно. Приличат на украинци - поне по любовта им към и жаждата им за Свобода. А може и папуаси да са... Но определено не са българи. И аз не съм българин.

2676

от Ясен Праматаров
лиценз CC BY

Не успявам да остана достатъчно дълго насаме с празния екран, за да пиша. А имам за какво да разказвам. Пътувания през лятото, училище, работа… и уволнение… и пак работа, но за себе си. Много неща, но трудно започвам – все няма време или ако има време, нямам сили и спя. За да не е само мрънкане това започване, ще кажа, че мобилните програми – конкретно за Android – са готино предизвикателство. Много дълго отлагано, но за всяко нещо си идва времето. Реших и стратегия за учене – пиша това, което ми липсва на момента. Или го има, но е несвободно, не е във f-droid… другояче казано, пак ми липсва.

Етап две – приключване на сагата ми с търсене на нов лаптоп. Старият е на пределна възраст, но на почти никой нов не му харесвам копчетата. Има някои модели с прилични клавиатури – без омразния цифров блок, с групирани F-ове и с разположение на специални клавиши, с каквото съм свикнал. Но пък са все със слаби процесори внесените бройки… Трудно е, но скоро ще трябва да реша.

Too many folders too little time

от Йордан Радунчев
лиценз CC BY

Напоследък все повече затъвам в Microsoft среда и се налага да се оправям със всякакви казуси в нея. Последно се наложи да намеря лесен начин да се даде достъп на група потребители в Exchange до дърво от папки в мейлбокс. Проблема е, когато имате добре развита структура от папки и подпапки в един мейлбокс - абсурдно е да цъкате на всяка една папка и да давате достъп до нея потребител по потребител. Майкрософт са проявили здрав разум и са имплементирали Exchange Management Shell - среда, в която можете да автоматизирате със скрипт такива задачки (и която поразително наподобява bash, дори заимства негови функции и команди - защо ли?).

И така, имате си един мейлбокс с подобна струкутра в него:

  \RootFolder
                \SubFolder1.0
                               \SubFolder1.1
                                               \SubFolder1.1.1
                               \SubFolder1.2
                \SubFolder2.0

Като дълбочината и разклонеността на дървото е без значение. Задачата е да дадем достъп на група потребители до всички папки под RootFolder (или под SubFolder1.0, или под SubFolder1.1 - принципа е същия). След кратко ровене из Нета от няколко парчета код се получи следния скрипт:

$mbox="Shared.Mailbox"
$usrs=( "User.Name1", "User.Name2", "User.NameN")

ForEach($fldr in (Get-MailboxFolderStatistics $mbox | Where { $_.FolderPath.Contains("RootFolder") -eq $true })) {  
    $fldrname = $mbox + ":" + $fldr.FolderPath.Replace("/","\");

    #Remove existing permissions
    ForEach($itm in (Get-MailboxFolderPermission $fldrname | select User,AccessRights)) {
        if (($itm.User -notlike "Default") -and ($itm.User -notlike "Anonymous")) {
        Remove-MailboxFolderPermission $fldrname -User $itm.User -confirm: $false
        }
    }

    #Add new permissions
    ForEach ($usr in $usrs){
        Add-MailboxFolderPermission $fldrname -User $usr -AccessRights NonEditingAuthor
  }
}

Некои съображения... Понеже използвам Add-MailboxFolderPermission, а той не променя вече съществуващи права за достъп на потребител, а само добавя нови такива, се налага първо да изчистя всички права за достъп до папката - защото ако се опитам да дам достъп на потребител, който вече има достъп до папката, то Add-MailboxFodlerermission ще се възмути и ще изплюе грешка... Което не е фатално, скрипта ще продължи нататък със следващия потребител от списъка usrs, но ще изглежда грозно на екрана хехехе. Пък и в конкретния случай, за който ми трябваше, този подход ме устройва, защото освен да се даде достъп до папките на някои потребители, се налага и да се премахне достъпа до тях на други потребители - та с един куршум отстрелях два заека (кажете после, че не ме мързи). Ще ви подскажа обаче, че за промяна на права за достъп се използва Set-MailboxFolderPermission - ако ви трябва друг подход, оправяйте се :) За параметрите на Add-MailboxFolderPermission и компания питайте Гугъл и Майкрософт.

2520

от Ясен Праматаров
лиценз CC BY

WordPress 3.6 е свежо обновление, признавам. Интересни стъпки, може би най-вече с визуалните промени. Не мога още да свикна с новия изглед Twenty Thirteen, макар че на много други блогъри ще им потекат лигите. Най-интересно ми е продължаващото развитие с различните формати на публикациите. Далеч e от гъвкавостта в Drupal, но пък май нарочно ги правят така. Още не свиквам – твърде ненастройваеми ми стоят.

Dual head setup с Linux

от Йордан Радунчев
лиценз CC BY

Dual head setup е работна станция (десктоп, лаптоп) с включени към нея два екрана. Идеята е да се увеличи площта на работния плот, като така стане възможно да имате отворени повече приложения И да ги следите едновременно, защото прозорците им не се припокриват.

Dual Head Setup

Когато говорим за десктоп, трябва да е ясно, че се нуждаете от видеокарта, която има два изхода, или специален сплитер. Този вариант не е предмет на тази статия.

Друго приложение на този сетъп е при изнасяне на презентации с лаптоп - мултимедийния проектор играе ролята на втори дисплей, на който може да прехвърлите слайдовете за публиката, докато на основния дисплей на лаптопа сте отворили бележките си.

Как се прави това под Линукс? Лесно. Повечето мейнстрийм графични среди за Линукс ви предлагат инструменти с които да направите необходимите настройки. Обикновено след като включите външен дисплей към извода на лаптопа си, в аплета за настройка на дисплея се появяват и двата - вградения и външния - и имате възможност да ги управлявате от там.

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

Използва се xrandr - приложение разработвано и поддържано от freedesktop.org, базирано на RandR X протокола. Много накратко казано това е протокол за откриване, конфигуриране и прочие на дисплеи. xrandr е част от стандартния Xorg пакет, така че се намира на всяка машина с инсталиран X.

Нашия сценарий е прост - презентатор с линукс лаптоп и мултимедиен проектор. Първата стъпка е да включите проектора към VGA извода на лаптопа. След това да прегледате как го намира Xorg:

09:14:40 yradunchev:~ $ xrandr -q   
Screen 0: minimum 320 x 200, current 1024 x 600, maximum 4096 x 4096   
  LVDS1 connected 1024x600+0+0 (normal left inverted right x axis y axis) 195mm x 113mm   
     1024x600       60.0*+   
     800x600        60.3     56.2     
     640x480        59.9     
  VGA1 connected (normal left inverted right x axis y axis)   
     1440x900       59.9 +   75.0     
     1280x1024      75.0     60.0      
     1280x960       60.0      
     1152x864       75.0      
     1024x768       75.1     70.1     60.0      
     832x624        74.6      
     800x600        72.2     75.0     60.3     56.2      
     640x480        72.8     75.0     66.7     60.0      
     720x400        70.1      
09:14:43 yradunchev:~ $     

Както виждате, xrandr -q ще покаже всички дисплеи, които открива, както и всички възможни режими на работа, които те предлагат. LVDS1 e основния, вградения дисплей на лаптопа, а VGA1, логично, е проектора включен към VGA изхода на лаптопа. За да го използвате, издавате следната команда към xrandr:

09:34:50 yradunchev:~ $ xrandr --output VGA1 --mode 1440x900 --right-of LVDS1

Това ще "добави" екрана на проектора към десктопа ви, в дясно от основния - това значи, че ако мръднете в с мишката надясно от дясната граница на основния екран на лаптопа, ще се озовете на екрана на проектора. Можете просто да завлачвате прозорци от основния екран надясно, за да ги видите на проектора. Когато пожелаете да изключите сигнала към проектора:

10:20:10 yradunchev:~ $ xrandr --output VGA1 --off

И шоуто приключва. Из Интернет можете да намерите шел скриптове, които можете да закачите за някоя клавишна комбинация или функционален/мултимедиен бутон на лаптопа си, и с тяхна помощ да включвате и изключвате външния екран в различни комбинации с основния. Тук няма да давам такъв, това ще ви е за домашно. :)