Dodanie linku nad animacją flash

Animację flash należy umieścić w divie. Dodatkowo należy utworzyć div o pozycji absolutnej i rozmiarze animacji flash. W zdarzeniu onclick dla diva obsłużyć otwieranie linku w nowym oknie przeglądarki.

<div id="flashContent" style="position:relative">
  <div>
  <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
width="619" height="116" id="dziendziecka" align="middle">
       <param name="movie" value="/pliki/dziendziecka.swf" />
       <param name="quality" value="high" />
       <param name="bgcolor" value="#ffffff" />
       <param name="play" value="true" />
       <param name="loop" value="true" />
       <param name="wmode" value="window" />
       <param name="scale" value="showall" />
       <param name="menu" value="true" />
       <param name="devicefont" value="false" />
       <param name="salign" value="" />
       <param name="allowScriptAccess" value="sameDomain" />
       <!--[if !IE]>-->
       <object type="application/x-shockwave-flash" data="/pliki/dziendziecka.swf"
width="619" height="116">
            <param name="movie" value="/pliki/dziendziecka.swf" />
            ....
            <param name="allowScriptAccess" value="sameDomain" />
       <!--<![endif]-->
            <a href="http://www.adobe.com/go/getflash">
              <img src="http://www.adobe.com/images/shared/download_buttons/
get_flash_player.gif"

alt="Pobierz odtwarzacz Adobe Flash Player" />
            </a>
       <!--[if !IE]>-->
       </object>
       <!--<![endif]-->
  </object>
  </div>
  <div style="position:absolute;background:transparent;width:619px;height:116px;
left:0;top:0;cursor:pointer" onclick="window.open('/pliki/dziendziecka.pdf','_blank')">

  </div>
</div>

Jak przyspieszyć WordPress

Poniżej kilka trików które pozwoliły mi przyspieszyć bloga z 32/22 w PageSpeed Insigth do 90/100 – oczywiście to zależy od strony, ilości zdjęć, szybkości serwera itp, wszystko ma znaczenie.
I to jest blog ze zdjęciami (blog.grzegorztomicki.pl), jak dla mnie bardzo zacnie 🙂

1. Będziemy potrzebować dostęp do .htaccess
W którym dodajemy (nie będę opisywał co dokładnie jest w nim robione bo wszystko można znaleźć opisane w internecie)

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
#</IfModule>



<IfModule mod_deflate.c>
  # Compress HTML, CSS, JavaScript, Text, XML and fonts
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE application/x-font
  AddOutputFilterByType DEFLATE application/x-font-opentype
  AddOutputFilterByType DEFLATE application/x-font-otf
  AddOutputFilterByType DEFLATE application/x-font-truetype
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE font/otf
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/xml

  # Remove browser bugs (only needed for really old browsers)
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
  Header append Vary User-Agent
</IfModule>

<IfModule mod_expires.c>
  ExpiresActive on

# Perhaps better to whitelist expires rules? Perhaps.
  ExpiresDefault                          "access plus 1 month"

# cache.appcache needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
  ExpiresByType text/cache-manifest       "access plus 0 seconds"



# Your document html
  ExpiresByType text/html                 "access plus 0 seconds"

# Data
  ExpiresByType text/xml                  "access plus 0 seconds"
  ExpiresByType application/xml           "access plus 0 seconds"
  ExpiresByType application/json          "access plus 0 seconds"

# RSS feed
  ExpiresByType application/rss+xml       "access plus 1 hour"

# Favicon (cannot be renamed)
  ExpiresByType image/x-icon              "access plus 1 week"

# Media: images, video, audio
  ExpiresByType image/gif                 "access plus 1 month"
  ExpiresByType image/png                 "access plus 1 month"
  ExpiresByType image/jpg                 "access plus 1 month"
  ExpiresByType image/jpeg                "access plus 1 month"
  ExpiresByType video/ogg                 "access plus 1 month"
  ExpiresByType audio/ogg                 "access plus 1 month"
  ExpiresByType video/mp4                 "access plus 1 month"
  ExpiresByType video/webm                "access plus 1 month"

# HTC files  (css3pie)
  ExpiresByType text/x-component          "access plus 1 month"

# Webfonts
  ExpiresByType font/truetype             "access plus 1 month"
  ExpiresByType font/opentype             "access plus 1 month"
  ExpiresByType application/x-font-woff   "access plus 1 month"
  ExpiresByType image/svg+xml             "access plus 1 month"
  ExpiresByType application/vnd.ms-fontobject "access plus 1 month"

# CSS and JavaScript
  ExpiresByType text/css                  "access plus 1 year"
  ExpiresByType application/javascript    "access plus 1 year"
  ExpiresByType text/javascript           "access plus 1 year"

  <IfModule mod_headers.c>
    Header append Cache-Control "public"
    Header unset ETag
    FileETag None
  </IfModule>

</IfModule>

2. Instalujemy „BJ Lazy Load”
Jest to plugin do „wolnego” ładowania się obrazków więcej na https://wordpress.org/plugins/bj-lazy-load/

3. Instalujemy „WP Super Cache”
Włączamy w nim w zakładce „Easy” na Caching on (Recommended) – więcej na https://wordpress.org/plugins/wp-super-cache/, czy działa można sprawdzić na stronie na samym dole powinien pojawić się mniej więcej taki wpis.

<!--HTML compressed, size saved 9.28%. From 64384 bytes, now 58410 bytes-->
<!-- Dynamic page generated in 0.974 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2016-01-01 11:42:46 -->


4. Najtrudniejsza część instalujemy „Above The Fold Optimization”

Nie włączamy go.
Klikamy na zakładkę „Extract Full CSS” pojawia się lista wszystkich css które są na stronie oraz textarea z połączonymi wszystkimi plikami css „Full CSS” – textarea.

Kopiuję Ctrl + C do strony https://jonassebastianohlsson.com/criticalpathcssgenerator/

Na tej stronie w pole:
1. URL podaję adres blog lub specyficznej strony na naszym blogu,
2. W „FULL CSS” wklejam cały nasz wygenerowany css.
3. Klikamy „Create Critical Path CSS”, po dłuższej chwili (w zależności od tego jak duży jest css w moim wypadku wszystkie połączone cssy są wielkości ponad 0,5MB) pojawia się okno textarea „CRITICAL PATH CSS” a w nim dostosowane css które kopiuję do pliku header.php od razu pod ,
oczywiście można to zrobić ładniej ale że jestem lazy to mi się nie chciało 🙂

Uwaga z tego skróconego css usuwamy wszystkie @font-face eot,ttf itd czcionki.

5. Wygląd -> Edytor -> otwieramy Funkcje motywu (functions.php)
Na samym końcu dodaję:

<?php
function remove_head_scripts() {
   remove_action('wp_head', 'wp_print_scripts');
   remove_action('wp_head', 'wp_print_head_scripts', 9);
   remove_action('wp_head', 'wp_enqueue_scripts', 1);

   remove_action( 'wp_head', 'rsd_link');
   remove_action( 'wp_head', 'wlwmanifest_link');
   remove_action( 'wp_head', 'wp_generator');
   remove_action( 'wp_head', 'start_post_rel_link');
   remove_action( 'wp_head', 'index_rel_link');
   remove_action( 'wp_head', 'adjacent_posts_rel_link');
   remove_action( 'wp_head', 'wp_shortlink_wp_head');

   add_action('wp_footer', 'wp_print_scripts', 5);
   add_action('wp_footer', 'wp_enqueue_scripts', 5);
   add_action('wp_footer', 'wp_print_head_scripts', 5);
}
add_action( 'wp_enqueue_scripts', 'remove_head_scripts' );

?>

Powyższa funkcja przenosi cały script do sekcji footer

Dodaję również jedną przydatną rzecz czyli kompresję html – usuwanie zbędnych spacji, nowych linii itd, również dodajemy w function.php na samym dole

<?php
class WP_HTML_Compression
{
    // Settings
    protected $compress_css = true;
    protected $compress_js = true;
    protected $info_comment = true;
    protected $remove_comments = true;

    // Variables
    protected $html;
    public function __construct($html)
    {
     if (!empty($html))
     {
         $this->parseHTML($html);
     }
    }
    public function __toString()
    {
     return $this->html;
    }
    protected function bottomComment($raw, $compressed)
    {
     $raw = strlen($raw);
     $compressed = strlen($compressed);
     
     $savings = ($raw-$compressed) / $raw * 100;
     
     $savings = round($savings, 2);
     
     return '<!--HTML compressed, size saved '.$savings.'%. From '.$raw.' bytes, now '.$compressed.' bytes-->';
    }
    protected function minifyHTML($html)
    {
     $pattern = '/<(?<script>script).*?<\/script\s*>|<(?<style>style).*?<\/style\s*>|<!(?<comment>--).*?-->|<(?<tag>[\/\w.:-]*)(?:".*?"|\'.*?\'|[^\'">]+)*>|(?<text>((<[^!\/\w.:-])?[^<]*)+)|/si';
     preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
     $overriding = false;
     $raw_tag = false;
     // Variable reused for output
     $html = '';
     foreach ($matches as $token)
     {
         $tag = (isset($token['tag'])) ? strtolower($token['tag']) : null;
         
         $content = $token[0];
         
         if (is_null($tag))
         {
             if ( !empty($token['script']) )
             {
                 $strip = $this->compress_js;
             }
             else if ( !empty($token['style']) )
             {
                 $strip = $this->compress_css;
             }
             else if ($content == '<!--wp-html-compression no compression-->')
             {
                 $overriding = !$overriding;
                 
                 // Don't print the comment
                 continue;
             }
             else if ($this->remove_comments)
             {
                 if (!$overriding && $raw_tag != 'textarea')
                 {
                     // Remove any HTML comments, except MSIE conditional comments
                     $content = preg_replace('/<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->/s', '', $content);
                 }
             }
         }
         else
         {
             if ($tag == 'pre' || $tag == 'textarea')
             {
                 $raw_tag = $tag;
             }
             else if ($tag == '/pre' || $tag == '/textarea')
             {
                 $raw_tag = false;
             }
             else
             {
                 if ($raw_tag || $overriding)
                 {
                     $strip = false;
                 }
                 else
                 {
                     $strip = true;
                     
                     // Remove any empty attributes, except:
                     // action, alt, content, src
                     $content = preg_replace('/(\s+)(\w++(?<!\baction|\balt|\bcontent|\bsrc)="")/', '$1', $content);
                     
                     // Remove any space before the end of self-closing XHTML tags
                     // JavaScript excluded
                     $content = str_replace(' />', '/>', $content);
                 }
             }
         }
         
         if ($strip)
         {
             $content = $this->removeWhiteSpace($content);
         }
         
         $html .= $content;
     }
     
     return $html;
    }
     
    public function parseHTML($html)
    {
     $this->html = $this->minifyHTML($html);
     
     if ($this->info_comment)
     {
         $this->html .= "\n" . $this->bottomComment($html, $this->html);
     }
    }
   
    protected function removeWhiteSpace($str)
    {
     $str = str_replace("\t", ' ', $str);
     $str = str_replace("\n",  '', $str);
     $str = str_replace("\r",  '', $str);
     
     while (stristr($str, '  '))
     {
         $str = str_replace('  ', ' ', $str);
     }
     
     return $str;
    }
}

function wp_html_compression_finish($html)
{
    return new WP_HTML_Compression($html);
}

function wp_html_compression_start()
{
    ob_start('wp_html_compression_finish');
}
add_action('get_header', 'wp_html_compression_start');
?>

6. Najważniejsza część pracy nad przyspieszeniem strony to oczywiście modyfikacja zdjęć.
Zdjęcia powinny mieć kompresję ustawioną na 70%, usunięcie wszystkich metadanych ze zdjęć, powinny być zapisane jako progressive, wielkość dostosowana do wielkości miejsca w którym się pojawiają zdjęcia.

7. W przyszłości zdjęcie przerobię na nowe rozwiązania dla wersji mobilnych
Więcej na https://scottjehl.github.io/picturefill/examples/demo-01.html oraz https://ericportis.com/posts/2014/srcset-sizes/

Tego rozwiązania używa między innymi theguardian.com a to wygląda mniej więcej tak (to jest jeden plik tylko że w różnych wielkościach):

<picture>
<!--[if IE 9]><video style="display: none;"><![endif]-->
<source media="(min-width: 1300px)" sizes="1300px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=1300&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=10e2200031125f835392892e9f813634 1300w">
<source media="(min-width: 1140px)" sizes="1140px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=1140&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=13d6ffcf420fb95bff93b5ca7a418f8e 1140w">
<source media="(min-width: 980px)" sizes="1125px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=1125&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=63fa2db8b2dccfc0ab408e25551c32e6 1125w">
<source media="(min-width: 740px)" sizes="965px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=965&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=c85b88b5fa49b0854485bd720d689155 965w">
<source media="(min-width: 660px)" sizes="725px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=725&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=048d9b371a22cebba3bb7dcd8e2d619c 725w">
<source media="(min-width: 480px)" sizes="645px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=645&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=97c169eb0122c0552b270a4be96e0410 645w">
<source media="(min-width: 0px)" sizes="465px" srcset="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=465&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=b4476e761590a0a1175cb66c5bfd8a8d 465w">
<!--[if IE 9]></video><![endif]-->
<img class="maxed responsive-img" itemprop="contentUrl" alt="Francesca Chaouqui" src="https://i.guim.co.uk/img/media/2fa72163af4712211cbf9abd929cc377d4af267b/0_0_4928_2957/master/4928.jpg?w=300&amp;q=85&amp;auto=format&amp;sharp=10&amp;s=c69f163a8116e3ac4ad7cc8170a1ad11">
</picture>

A poniżej wynik mojej pracy.

desctop

mobile

W webpagetest też jest bardzo pozytywnie 🙂

webpage

jQuery UI Autocomplete highlight

Mamy sobie prosty formularz. Do podpowiedzi użyjemy pluginu jquery autocomplite. Chcemy również dodać wyboldowanie podpowiedzi.
Dokładnie uzyskać taki efekt „meble, Waszawa” gdzie highlight jest zmianą koloru na czarny i wyboldowaniem.

<form id="search" action="/" method="GET" role="search">
    <fieldset>
        <input id="query" type="text" name="query" value="" maxlength="255" autocomplete="off" placeholder="Produkt, usługa, miasto, ulica">
        <button type="submit" id="button-search"></button>
    </fieldset>
</form>

A teraz trochę js 😉

$("#query").autocomplete({
        'minLength': 2,
        'delay': 0,
        create: function () {
            $(this).data('ui-autocomplete')._renderItem = function (ul, item) {
                var re = new RegExp("^" + this.term, "i") ;
                var t = item.label.replace(re,"<span class='highlight'>" + this.term + "</span>");

                return $( "<li></li>" )
                    .data( "item.autocomplete", item )
                    .append(t)
                    .appendTo( ul );
            };
        },
        source: function (request, response) {
            //escapeRegex - /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"
            var re = $.ui.autocomplete.escapeRegex(request.term);
            var matcher = new RegExp("^" + re, "i");

            $.getJSON("/autocomplete/?what=" + encodeURIComponent(request.term), function (searchWord) {
                var match = $.grep(searchWord, function (item, index) {
                    return matcher.test(item);
                });
                response(match);
            });
        },
        open: function (e, ui) {
            //autocomplete przesuwamy o 1px to góry, aby pozbyć się ramki
            $(".ui-autocomplete:visible").css({top: "-=1"});
        }
    });

A tak wygląda wynik naszej pracy.

autosuggest

Gulp.js – menadżer zadań

Gulp.js jest menadżerem zadań opartym na node, w skrócie mamy kilka czynności do zrobienia w projekcie. I żeby nie robić tego ręcznie gulp wykonuje za nas te operacje.
Oprę się na małym projekcie, chcę less zamienić na css, skopiować do foldera css, zminimalizować i zmienić jego nazwę na style.min.css

1. Instalacja

Do tego oczywiście potrzebny najpierw jest zainstalowany node, jak już jest zainstalowany to instalujemy gulp.

// najpierw instalujemy globalnie – zainstaluje się w folderze C:\Users\Uzytkownik\AppData\Roaming\npm\node_modules\gulp

npm install -g gulp

// następnie instalujemy lokalnie w moim wypadku wchodzimy do D:\xampp\htdocs\test-gulp i tam instalujemy gulp jak i pluginy

npm install gulp --save-dev

Teraz aby móc z gulp skorzystać należy utworzyć plik konfiguracyjny gulpfile.js – musi być on umieszczony w katalogu głównym naszego projektu.

W naszym projekcie będziemy korzystać z gulp-less, gulp-minify-css oraz gulp-rename możemy je zainstalować pojedynczo jak i za jednym razem jak kto woli.

// wszystko instalujemy lokalnie

npm install gulp-less gulp-minify-css gulp-rename install --save-dev

Struktura naszego projektu:
mamy folder „test-gulp” w nim foldery css oraz less, w less jest plik style.less 🙂
W test-gulp znajduje się plik gulpfile.js (nasze taski) oraz package.json (plik generujemy automatycznie lub ręcznie 😉 – zawiera on dependencies itd.)

test-gulp/
|  css/
|  less/
|  |  style.less
gulpfile.js -- ad3
package.json -- ad2

2. Tworzymy package.json

Aby utworzyć package.json należy w konsoli lokalnie uruchomić npm init

Pojawi się nam coś takiego:

———————–
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install –save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (test-gulp)
———————–

Naciskamy enter do pojawienia się „Is this ok? (yes)
wpisujemy y + enter

i mamy w naszym projekcie package.json

3. Konfiguracja gulpfile.js

/**
 * umieszczamy nasze pakiety które nam są potrzebne do projektu
 */

var gulp        = require('gulp'),
    less        = require('gulp-less'),  // less -> css
    minifyCSS   = require('gulp-minify-css'),  // css -> minify css
    rename      = require('gulp-rename');  // zmiana style.css na style.min.css


/**
 * tworzymy task (zadanie) wszystkie pliki less
 * zamieniamy na css
 * z css usuwamy br, nowe linie itd. czyli poczciwe minify
 * style.css zmieniamy nazwę na style.min.css
 */

gulp.task('less', function() {
    return gulp.src('less/*.less')
        .pipe(less())
        .pipe(minifyCSS())
        .pipe(rename({suffix: '.min'}))
        .pipe(gulp.dest('css')); // miejsce docelowe pliku css
});

/**
 * Watch Files For Changes - czyli obserwator zmian? (dziwnie to brzmi po polsku :))
 */

gulp.task('watch', function() {
    gulp.watch('less/*.less', ['less']);
});

/**
 * Default Task - domyślne zadania?
 */

gulp.task('default', ['less', 'watch']);

5. Uruchamianie

Aby zmiany w plikach były na bieżąco kompilowane należy uruchomić będąc w naszym folderze (test-gulp) w konsoli wpisując gulp.
Od tego momentu każda zmian na less będzie skutkowała wygenerowanie pliku style.min.css w folderze css.

Oczywiście każdy task może być uruchamiany osobno, wystarczy w konsoli także lokalnie wpisać gulp less

6. Podsumowanie

Gulp może robić z naszych plików zip, kopiować na serwer itd. 🙂
Więcej na stronie gulp plugins

W następnym artykule pokaże jak można to samo skonfigurować w Intelij IDEA.

Jak ukryć swój adres e-mail na stronach www

1. CSS pseudo elementy

a.

<style>
  span:after {
    content: attr(data-domain);
  }
  span:before {
    content: attr(data-user);
  }
</style>
<span data-user="greg" data-domain="gmail.com">@</span>

b. inne wykorzystanie pseudo elementu do before dodajemy jeszcze w unicode @

<style>
  span:after {
    content: attr(data-domain);
  }
  span:before {
    content: attr(data-user) "\0040";    /* symbol unicode @ */
  }
</style>
<span data-user="greg" data-domain="gmail.com"></span>

c. inne rozwiązanie, za klasą after (span) dodajemy pseudo element w unicode @

  .after:before {
    content: "\0040";    /* symbol unicode @ */
  }
greg<span class="after">gmail.com</span>

d. odwrotny kierunek

<style>
  .reverse {
    unicode-bidi: bidi-override;
    direction: rtl;
  }
</style>
<span class="reverse">moc.liamg@gerg</span>

2. Użycie javascript

a. „onclick” event

<a href = "mailto:gregATgmailDOTcom" onclick = "this.href=this.href.replace(/AT/,'&#64;').replace(/DOT/,'&#46;')">Napisz maila do mnie ;)</a>

b. tablica

<span id="email"></span>
<script>
  var parts = ["greg", "gmail", "com", "&#46;", "&#64;"];
  var email = parts[0] + parts[4] + parts[1] + parts[3] + parts[2];
  document.getElementById("email").innerHTML=email;
</script>

3. I sposób na wp + php

<?php echo antispambot("greg@gmail.com"); ?>

oraz coś na koniec, zakodowany adres który po wklejeniu do html da nam greg@gmail.com – można to zrobić na pod tym adresem 😉

&#103;&#114;&#101;&#103;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;

Wyłączenie intergracji SKYPE z telefonami na stronach

Często gęsto bywa tak że posiadamy na stronie numery telefonów i powiedzmy ktoś wchodzi na stronę ze skypem ustawionym na ingerencję w numery telefonów.
Wtedy przerabiane są wszystkie telefony na wygląd skypowy, jednym słowem wszystko się „rozjeżdża” 🙁

Wystarczy dodać w sekcji head dodać jedną linijkę kodu i mamy delikwenta z głowy:

<head>
<meta name="SKYPE_TOOLBAR" content="SKYPE_TOOLBAR_PARSER_COMPATIBLE" />
</head>

Tabele w RWD

Powiedzmy że posiadamy tabelę z rezerwacjami hotelowymi.
Jeżeli zmniejszymy rozdzielczość na wielkość znaczka pocztowego – powiedzmy 320px to nic nie będzie widać i tutaj z pomocą przychodzi CSS.
Poniższe rozwiązanie działa od IE8 no i oczywiście w nowych przeglądarkach 😉

Przykładowa a tak wygląda tabela.

<section class="reservation-box">
    <table class="table-reservation">
        <thead>
        <tr>
            <th>Nazwisko i imię</th>
            <th>Telefon</th>
            <th>Adres e-mail</th>
            <th>Liczba wizyt</th>
            <th>Data ostatniej rezerwacji</th>
        </tr>
        </thead>
        <tbody>
        <tr class="reservation-row-item">
            <td data-title="Nazwisko i imię">Pałczyński stefan</td>
            <td data-title="Telefon">14725836</td>
            <td data-title="Adres e-mail">palczynski.stefan@gmail.com</td>
            <td data-title="Liczba wizyt">0</td>
            <td data-title="Data ostatniej rezerwacji">nie odbyła się</td>
        </tr>
        <tr class="reservation-row-item">
            <td data-title="Nazwisko i imię">Miałczyński Cezary</td>
            <td data-title="Telefon">69522999</td>
            <td data-title="Adres e-mail">mcezik@tet.pl</td>
            <td data-title="Liczba wizyt">1</td>
            <td data-title="Data ostatniej rezerwacji">28 stycznia 2014</td>
        </tr>
        <tr class="reservation-row-item">
            <td data-title="Nazwisko i imię">Tomaczek Andrzej</td>
            <td data-title="Telefon">32999222</td>
            <td data-title="Adres e-mail">tomaczekandrzej@jawa.pl</td>
            <td data-title="Liczba wizyt">1</td>
            <td data-title="Data ostatniej rezerwacji">20 stycznia 2015</td>
        </tr>
        </tbody>
    </table>
</section>

Jak widać tabela jak tabela, wygląda normalnie ale pojawiło się coś w komórkach „data-title” – atrybuty, te same nazwy co w sekcji thead > th.

<tr class="reservation-row-item">
    <td data-title="Nazwisko i imię">Pałczyński stefan</td>
    <td data-title="Telefon">14725836</td>
    <td data-title="Adres e-mail">palczynski.stefan@gmail.com</td>
    <td data-title="Liczba wizyt">0</td>
    <td data-title="Data ostatniej rezerwacji">nie odbyła się</td>
</tr>

Po co to powiecie? Zaraz wyjaśnię.

Zacznijmy od podstawowego stylu dla tabeli aby jakoś wyglądała ona po „ludzku” 😉

.reservation-box table {
    font-family: "open sans";
    width: 100%;
    border: 1px solid #e7e7e7;
    border-collapse: collapse;
    border-spacing: 0;
}

.reservation-box table thead {
    text-align: left;
    background-color: #f8f8f8;
    font-size: 13px;
    border-bottom: 1px solid #e7e7e7;
}

.reservation-box table td, .reservation-box table th {
    padding: 7px;
}

.reservation-box table [data-title] {
    border-bottom: 1px solid #e7e7e7;
}

Jak widać nic szczególnego na razie.
Druga część kodu css odpowiada za RWD tabeli.

— RWD zacznie się od 768px

@media (max-width: 768px)
</code>
-- Zmieniamy czcionkę na mniejszą można użyć co kto uważa
-- może być rem, vm, vmin czy zwykłe px - więcej info w google ;)
<code>
.reservation-box table {
    font-size: 0.8rem;
}

— usuwamy thead nagłówek tabeli jest już zbędna przy tej szerokości okna

.reservation-box thead {
    display: none;
}

— wszystkie td ustawiamy na display: block
— ustawiamy relative, odsuwamy od lewej tekst na 39% – to już zależy od was
— jeżeli chcemy aby za długi tekst się obcinał do … kropek dodajemy:
— text-overflow ellipsis
— white-space nowrap
— overflow hidden

.reservation-box td {
    display: block;
    border: none;
    position: relative;
    padding-left: 39% !important;
    text-align: left;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
}

— w tym miejscu do tr dodałem większy border
— aby podkreślić gdzie kończy się odstęp między rekordami

.reservation-box tr {
    border-bottom: 2px solid #a3a3a3;
    width: 100%;
}

.reservation-box tr [data-title] {
border-bottom: 1px solid #e7e7e7;
}

— najważniejsza część „magii” 😉
— do td został dodany pseudo-element before właśnie to on robi całą magię
— a mianowicie z atrybutu data-title szczytuje nazwy kolumn które ustawiliśmy przy td
— tutaj dajemy position absolute i dla tego wyżej w td było position relative 🙂
— ustawiamy szerokość na 31%, czcioneczka na bold aby było widać że to coś innego niż zwykły tekst w komórce
— dodajemy przy zbyt długich nazwach w data-title zanikanie tekstu,
— przy zmniejszaniu szerokości okna powinny znikać ostanie litery
— i pojawić się … (np. Data ostatniej… – działa to od IE8 więc bez obaw)

.reservation-box tr.reservation-row-item td:before {
    position: absolute;
    font-size: 0.8rem;
    top: 0;
    left: 0;
    width: 31%;
    padding: 8px 8px 8px 10px;
    text-align: left;
    font-weight: bold;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    content: attr(data-title);
    border-right: 1px solid #e7e7e7;
}

Poniżej tabela w rozdzielczości większej niż 768px

przed

Oraz po zmniejszeniu szerokości okna:

po

O wiele lepiej wygląda w RWD 😉

Poniżej cały kod CSS.

.reservation-box table {
    font-family: "open sans";
    width: 100%;
    border: 1px solid #e7e7e7;
    border-collapse: collapse;
    border-spacing: 0;
}

.reservation-box table thead {
    text-align: left;
    background-color: #f8f8f8;
    font-size: 13px;
    border-bottom: 1px solid #e7e7e7;
}

.reservation-box table td, .reservation-box table th {
    padding: 7px;
}

.reservation-box table [data-title] {
    border-bottom: 1px solid #e7e7e7;
}

@media (max-width: 768px) {

    .reservation-box table {
        font-size: 0.8rem;
    }

    .reservation-box thead {
        display: none;
    }

    .reservation-box td {
        display: block;
        border: none;
        position: relative;
        padding-left: 39% !important;
        text-align: left;
        text-overflow: ellipsis;
        white-space: nowrap;
        overflow: hidden;
    }

    .reservation-box tr {
        border-bottom: 2px solid #a3a3a3;
        width: 100%;
    }

    .reservation-box tr [data-title] {
        border-bottom: 1px solid #e7e7e7;
    }

    .reservation-box tr.reservation-row-item td:before {
        position: absolute;
        font-size: 0.8rem;
        top: 0;
        left: 0;
        width: 31%;
        padding: 8px 8px 8px 10px;
        text-align: left;
        font-weight: bold;
        text-overflow: ellipsis;
        white-space: nowrap;
        overflow: hidden;
        content: attr(data-title);
        border-right: 1px solid #e7e7e7;
    }

}

Sortowanie polskich znaków w javascript

function MySort(alphabet)
{
    return function(a, b) {
        var index_a = alphabet.indexOf(a[0]),
        index_b = alphabet.indexOf(b[0]);

        if (index_a === index_b) {
            if (a < b) {
                return -1;
            } else if (a > b) {
                return 1;
            }
            return 0;
        } else {
            return index_a - index_b;
        }
    }
}

var items = ['świat','ł', 'k', 'ą', '*sdf', '!sdf', '@asdf', '_asd', '.sadf', '(sadf', ')sadf', '#sadf', '^asdf', '&asdf', '%asdf', '-sadf', '=sadf', '+sadf', '-sdf', 'sef'],
sorter = MySort('*!@_.()#^&%-=+01234567989aąbcćdeęfghijklłmnńoóprsśtuwyzźż');

console.log(items.sort(sorter));

html5 placeholder w IE7 i IE8

    // set placeholder values
       $('[placeholder]').each(function() {
        if ($(this).val() == '') // if field is empty
        {
            $(this).val($(this).attr('placeholder'));
        }
    });
    // focus and blur of placeholders
    $('[placeholder]').focus(function() {
        if ($(this).val() == $(this).attr('placeholder')) {
            $(this).val('');
            $(this).removeClass('placeholder');
        }
    }).blur(function() {
        if ($(this).val() == '' || $(this).val() == $(this).attr('placeholder')) {
            $(this).val($(this).attr('placeholder'));
            $(this).addClass('placeholder');
        }
    });

    // remove placeholders on submit
    $('[placeholder]').closest('form').submit(function() {
        $(this).find('[placeholder]').each(function() {
            if ($(this).val() == $(this).attr('placeholder')) {
                $(this).val('');
            }
        })
    });

Należy oczywiście sprawdzić czy placeholder jest wspierane przez przeglądarkę.

if (!("placeholder" in document.createElement("input"))) {
    odpalPlaceHolder(); // tutaj odpalamy funkcje która obsługuje placeholder
}

Można również użyć modernize jeżeli oczywiście używamy już w projekcie.

if(!Modernizr.input.placeholder) {
 // custom placeholder code
}

SVG animacja

Najpierw styl którym nadajemy kolor wykresów.

<style>
    rect {
        fill:red;
    }
</style>

Teraz umieszczamy svg w stronie.

<svg width="500px" height="300px">
    <g transform="scale(1, -1) translate(0, -300)">
        <rect x="0" y="0" height="30%" width="15%">
            <animate attributeName="height" from="0" to="30%" dur=".5s"/>
        </rect>
        <rect x="20%" y="0" height="10%" width="15%">
            <animate attributeName="height" from="0" to="10%" dur=".5s"/>
        </rect>
        <rect x="40%" y="0" height="20%" width="15%">
            <animate attributeName="height" from="0" to="20%" dur=".5s"/>
        </rect>
        <rect x="60%" y="0" height="70%" width="15%">
            <animate attributeName="height" from="0" to="70%" dur=".5s"/>
        </rect>
        <rect x="80%" y="0" height="40%" width="15%">
            <animate attributeName="height" from="0" to="40%" dur=".5s"/>
        </rect>

    </g>
</svg>

Mały update, tutaj znajduje się odnośnik do strony na której można sprawdzić zgodność svg z przeglądarkami.