NoBabis – rozšíření do Chrome a Opery proti Babišovým médiím

Jak jste nepochybně zaznamenali, potvrdilo se, že (zatím) ministr financí Babiš hrubě ovlivňoval média, která vlastnil, dodával jim informace o jeho protivnících a naopak nechal tutlat nějaké jiné informace, kdy se mu to hodilo.

Nevěřím, že by se papírovým převedením médií pod nějaký jeho svěřenecký fond něco změnilo, nevěřím ani, že by se něco změnilo vyhozením přistiženého redaktora (zejm. bez vyvedení zodpovědnosti dalších lidí nad ním).

Proto jsem se rozhodl tato média nesledovat. Mám ale problém, za těch mnoho let jsem si zvykl na zpravodajství Babišových Lidovek a iDnes do té míry, že už to do adresního řádku prostě píšu automaticky.

A proto jsem vytvořil malé rozšíření do Chrome a Opery, které při pokusu o přechod na kteroukoliv homepage v doménách idnes, lidovky.cz, expres.cz a playtvak.tv přesměruje na některý jiný server (náhodně irozhlas.cz, aktualne.cz, forum24.cz, echo24.cz a seznam.cz/zpravy, které podle mě dnes drží prapor vysoké úrovně a důvěryhodnosti). Jiné menší a specializované servery (zatím) nepřesměrovávám, protože nesouvisí se zpravodajstvím.

Třeba se bude hodit i vám, poskytuji volně ke stažení, úpravám i čemukoliv dalšímu. Pozor, normálně není možné instalovat tyto soubory z jiných než oficiálních stránek, takže si soubor stáhněte, otevřete si stránku s rozšířeními a soubor na ni přetáhněte, pak už by mělo jen stačit povolit instalaci.

Jinak záměrně přesměrovávám jen homepage – když bych někde chtěl kliknout na konkrétní článek, tak bych si jej rád bez otravování přečetl. Kdybych někdy z nějakého důvodu potřeboval vidět homepage, vždy ji mohu otevřít v anonymní okně.

P.S.: vyzkoušejte také Android aplikaci Bez Andreje, která vám pomůže v prodejně rozpoznat potraviny, které vyrábí Babišovy firmy.

WordPress – konec problémů s psaním hranaté závorky

Jestli používáte aktuální verze WordPressu a nejste úplní začátečníci, tak jste nejspíš chtěli někdy napsat nějaký shortcode (jestli neznáte, to je něco jako „makro“ připravené nějakým vývojářem tématu či šablony použitelné v rámci textů příspěvků, uvozené nějakým magickým slovem v [hranatých závorkách], více viz Shortcode API).

Jenže WordPress někdy od verze 4.něco používá pro wysiwyg editor aktualizovanou verzi TinyMCE, která obsahuje i fullscreen plugin – vychytávku, která když v editoru zmáčknete Ctrl+Alt+F (nebo pravý alt + F), tak vám jej zvětší na plné okno, aby vás nic nerušilo.

A to je právě ten problém, protože stejná klávesová zkratka je na české, slovenské, polské a bůhvíjakých dalších klávesnicích vyhrazená pro napsání levé hranaté závorky, bez které se ten shortcode nedá moc napsat (vynechám hacky jako přepínání klávesnic či napsání jinde a zkopírování).

Reportoval jsem to jako bug WordPressu, tam mě s tím poslali k … TinyMCE, tak jsem to reportoval i tam, uvidíme, jestli to upraví.

Nicméně neplačte, řešení existuje a je primitivní, stačí jedna pidiaakcička do vašeho functions.php souboru, případně pro ty, pro které je i to příliš složité, jsem z toho připravil i plugin. Tak si vyberte:

Úprava – přidání do functions.php:

// This is all the magic. Simply called on TinyMCE Init and removing CTRL+ALT+F shortcut defined in default TinyMCE package
add_action( 'wp_tiny_mce_init', function () {
?>
<script>
 jQuery( document ).on( 'tinymce-editor-init', function( event, editor ) {
 editor.shortcuts.remove( 'meta+alt+f' );
 }
 );
</script>
<?php
});

Plugin

Plugin je zatím ke stažení zde. Dal jsem jej ke zveřejnění v oficiálním seznamu pluginů, pak to tu aktualizuji.

Licence

Jestli máte neodbytnou potřebu mi poděkovat, ocením, když o této stránce dáte vědět na svém Facebooku, Twitteru, Google plus, blogu či třeba domovní nástěnce. Jo a jestli to tu neznáte – možná se vám bude hodit pár dalších podobně užitečných tipů.

Disclaimer

A samozřejmě – jestli vám můj kód sežere kočku či zapálí dům, tak mi nevolejte.

Kontrola/oprava/úprava vložených hodnot v Google Sheets díky Apps Script

Google před asi 3 měsíci v tichosti odstranil jeden z posledních nedostatků Google Sheets App Script oproti VBA u MS Excelu a tím byla faktická nemožnost kontroly vkládaných dat skriptem (nicméně existuje alespoň dost mocná možnost Data/Ověření platnosti včetně možnosti vlastního vzorce).

Problém byl, že zde sice existovala událost onEdit(e), vracející novou hodnotu, problém byl, že zde chyběla ta původní hodnota a událost onEdit nastala až po provedení změny, tj. když se vám nová hodnota z nějakého důvodu nezdála, nemohli jste vrátit původní hodnotu (vynechám ošklivý hack, kdy jste si ukládali při otevření hodnotu všech buněk a porovnávali s nimi).

A to se právě změnilo a událost onEdit nyní obsahuje i původní hodnotu a teď někdy se to i dostalo do nápovědy.

Praktický příklad – řekněme, že nechceme povolit zadání větší hodnoty než 100, v opačném případě tam chceme vrátit původní hodnotu (není to tak úplně praktický příklad, protože zrovna tohle snadno vyřešíte tím Ověřením platnosti, ale pro ilustraci to postačí).

function onEdit(e){
 var range = e.range;
 if ( e.value > 100 ) range.setValue(e.oldValue); 
}

Nebo tedy trochu jiný příklad – řekněme, že po změně hodnoty chcete do poznámky k dané buňce napsat, kdy byla změněna a jaká byla původní hodnota.

function onEdit(e){
 var range = e.range;
 var note = range.getNote();
 note = (note) ? note+"\n" : note; 
 range.setNote(note+e.oldValue + ' (do ' + Utilities.formatDate(new Date(), "GMT+1", "d. M. yyyy HH:MM:ss") + ')');
}

Jen upozorním, že onEdit se spouští pro úpravu kterékoliv buňky, tj. pakliže budete chtít vliv omezit jen pro některé buňky, musíte testovat, zdali onen e.range je mezi nimi, což je mimo téma tohohle postu (prozradím, že bohužel Apps Script nemá obdobu MS VBA Application.Intesect, takže to je netriviální a musí se na to jít přes ověřování pozice e.range vůči definovaným okrajům).

WordPress: vytvářejte snadno podstránky aktuální stránky

Pakliže používáte WordPress jako CMS pro firemní web, pak nejspíše používáte Stránky, které mají na rozdíl od Příspěvků hierarchii. Běžně tak potřebujete vytvořit podstránku k nějaké stránce. Je to triviální, prostě při vytváření stránky vyberete v pravém menu Nadřazenou stránku a hotovo.

Jenže když těch stránek máte hodně, musíte tu nadřazenou hledat, navíc mnoho lidí má jiný pracovní a myšlenkový postup – jsou na webu na té nadřazené stránce a řeknou „ha, k téhle stránce by se hodila nějaká podstránka“, nebo prostě vytváří nový web a pracují prostě stylem „Teď vytvořím Úvodní stránku. Publikuju jí. Zkontroluji. A teď k ní potřebuju podstránku“.

Proto jsem pro vás připravil drobný kód pro vaše functions.php, které přidá do záložky Akce ve vaší Navigační liště (Admin Bar) volbu „Přidat podstránku“. Po kliknutí na tento odkaz se vám otevře okno pro založení nové stránky a automaticky předvyplní Nadřazenou stránku tou, ze které jste přišli.

// přidá odkazy do admin baru
function kapler_admin_bar_menu($wp_admin_bar) {
global $post;
 // jen když jsem na Stránce a aktuální uživatel má právo editovat stránky a má právo k té nadřazené stránce
 if (is_page() && current_user_can( 'edit_page', $post->ID )) {
 $args = array(
 'id' => 'add_subpage',
 'title' => _('Vytvořit podstránku'), 
 'href' => admin_url( 'post-new.php?post_type=page&parent='.$post->ID ),
 'parent' => 'new-content'
 );
 $wp_admin_bar->add_node($args);
 }
}
add_action('admin_bar_menu', 'kapler_admin_bar_menu');

// když je editační stránka page s předvyplněným parent, nastaví jej
function kapler_admin_head() 
{
 // vkládat jen u Stránek a jen když je vyplněný parametr parent
 if( !empty($_GET['post_type']) && $_GET['post_type']=='page' && !empty( $_GET['parent'] ) ) {
 ?>
 <script type="text/javascript">
 jQuery(document).ready( function($) 
 {
 $('#parent_id').val(<?php echo $_GET['parent']; ?>);
 });
 </script>
 <?php
 }
}
add_action( 'admin_head-post-new.php', 'kapler_admin_head' );

Štastné Vánoce 🎄

Stromeček 🎄 či dárek 🎁, jako symbol Vánoc. Srdíčko ❤ či hvězdička ⭐, ohýnek 🔥 či zatržítko ✓ ✔ ✅ … to všechno jsou některé ze stovek symbolů, které jsou součástí rozšířené znakové sady velká části fontů.

Tyto symboly jsou ale kouzelné! Jestli čtete tento článek na mobilu, či jej třeba sdílíte na Facebooku nebo Twitteru, možná si všimnete, že tyto znaky jsou automaticky nahrazeny obrázky. Původně se tak dělo jen u smajlíků, proto se jim také říká emotikony či emoji.

Ale tím jejich kouzlo nekončí, některé z těchto symbolů se totiž dostanou i do titulků či popisků (a dokonce i URL, jestli to váš publikační systém podporuje), které jsou pak součástí SERP – úryvků, které vyhledavač zobrazí ve výsledcích vyhledávání. A opět – zobrazíte-li si takový výsledek na mobilu, budou takové emoji nahrazené obrázky.

A v tom spočívá i další kouzlo těchto obrázků – jsou výrazné, ve zmeti okolních znaků zaujmou na první pohled, výsledek s takovým symbolem tak bude mít nejspíš vyšší míru prokliku (CTR). Jen do PPC je nejspíš neprotlačíte.

A ještě jedno jejich kouzlo vám prozradím – můžete je použít i ve jméně odesílatele či v předmětu e-mailu a opět se tak nejspíš magicky zvýší míra otevření (open-rate). Možnosti jsou ohromné, ať nabízíte autodíly 🚗, mobily 📱 či vybavení domu 🏠, nebo jen oznamujete časově omezenou akci 🔥 a dárek 🎁 ke každé objednávce.

Vybírejte z existujících symbolů např. na této stránce, a nezapomeňte – ani s kouzly se to nesmí přehánět.

Přeji magické svátky

WordPress – odkazujte na součet či průnik štítků

WordPress má tuším asi 2 roky jednu nepříliš známou a dokumentovanou, ale přesto občas velmi užitečnou fičuru – možnost odkazovat na výpis článků, které mají více vyjmenovaných štítků (resp. termínů libovolné taxonomie), či na výpis článků, které mají kterýkoliv z vyjmenovaných štítků.

Použití je přitom velmi intuitivní, pouhým přidáním požadovaných tagů do URL adresy, oddělenými buď čárkou nebo symbolem plus. Konkrétně tedy např. :

  • http://kapler.cz/tag/google-sheets+funkce/ – články, které jsou označeny tagem Google Sheets a zároveň tagem Funkce (tedy dotaz s AND operátorem), tedy všechny mé články o funkcích pro Google Sheets (ale ne např. o funkcích pro Excel)
  • http://kapler.cz/tag/google-sheets,excel/ – články, které mají kterýkoliv z tagů Google Sheets či Excel (tedy dotaz s OR operátorem), tedy všechny mé články o těchto tabulkových procesorech.

Z  dalších praktických příkladů – představte si, že máte web s texty písní na WordPressu, který používá vlastní taxonomii Zpěvák. S tímto trikem tak můžete snadno zobrazit všechny písničky, kde zpívá nějaké konkrétní duo (či vícero) zpěváků, nebo všechny písně, které zpívá kterýkoliv z nich.

Nebo si představte, že máte na WordPressu vytvořený eshop s taxonomiemi pro výrobce či parametry výrobků – bez složitých hacků tak můžete udělat pokročilé filtrování produktů.

P.S.: jestli jste autor takového webu a chcete pro tuto funkci váš web trochu vytunit, můžete upravit chování funkcí the_archive_title() a the_archive_description(), které zobrazují název resp. popis  štítku/kategorie – standardně totiž zobrazují název/popis jen prvního termínu (reportoval jsem to jako chybu, takže možná bude upraveno).

Jak používat (velmi rychlá) VBA makra v MS Office

Znám hodně lidí, typicky různí účetní, ekonomové atp., kteří používají makra v aplikacích MS Office, aniž jim rozumí. Prostě jim někdo ukázal funkci Zaznamenat makro a Spustit makro a oni ji používají. A to je skvělé.

Vážně. Dal bych nevím co, aby takovýhle makro rekordér obsahovala každá aplikace a považuji za zásadní nedostatek Google Apps, že ač obsahují mají svou obdobu maker – Apps Script, makro rekordér neobsahují.

Úvod pro laiky

Následuje úvod pro laiky, zkušení přeskočte až na tučný nadpis níže:

Poznámka: panel Developer/Vývojář, ve kterém se s Makry pracuje, musíte v novějších verzích Office extra zapnout – v aplikaci stistknete tlačítko Office (takové to kulaté vlevo nahoře), nebo Soubor (v nejnovějších Office), a tam „někde“ to bude – např. v anglickém Excel 2007 je to v Excel options (tlačítko dole) a zvolit Show Developer tab in the Ribbon, v českém Excel 2016 je to v Přizpůsobit pás karet a vpravo zaškrtnout Vývojář.

Pokračovat ve čtení „Jak používat (velmi rychlá) VBA makra v MS Office“

Překládejte snadno z/do cizích jazyků v prohlížeči

Jestli podobně jako já píšete či čtete v několika jazycích a občas hledáte správný překlad, tak nejspíš buď používáte nějaké složité a bůhvíco dělající rozšíření do prohlížeče, nebo jako já online Google Translator.

Jenže když těch jazyků používáte více, tak musíte neustále přepínat zdrojový a cílový jazyk, navíc standardně jsou vidět jen 3, takže to jsou další kliknutí – no prostě samé starosti. Přitom existuje snadné řešení – překlad přímo z adresního pole.

Pokračovat ve čtení „Překládejte snadno z/do cizích jazyků v prohlížeči“

Automatické statistiky videí díky Google Sheets, Apps Script a YouTube Data API

Před pár dny jsem tu psal příspěvek o tom, jak si snadno udělat automaticky aktualizovaný přehled (nejen) vašich video kanálů s využitím Google Sheets, Apps Script a YouTube Data API. Mělo to jen jednu chybku – videím chyběly statistiky, tak to dnes napravíme.

Chybějící statistiky si vyžádaly nutnost přepsání celého skriptu, protože API YouTube.PlaylistItems neposkytuje statistická data, bylo potřeba použít další část YouTube Data API a to YouTube.Videos. Zároveň bylo potřeba skript optimalizovat, aby se nedotazoval na statistiky každého videa najednou a rovnou jsem skript také zpřehlednil.

Pokračovat ve čtení „Automatické statistiky videí díky Google Sheets, Apps Script a YouTube Data API“

Mějte přehled ve svých videích díky Google Scripts, Sheets a YouTube Data API

Možná víte, že jsem digital manažer výrobce značek Tefal, Krups, Rowenta pro ČR, SR a Maďarsko. A jedna z milých povinností, kterou mám na starosti, je i správa našich YouTube kanálů, kterých je celkem 5, plus jsou YouTube kanály našich spřátelených beauty blogerek atp.

Než jsem přišel, tak se to dělalo tak, že když někdo přidal YouTube video, tak pak vzal tu URL a napsal to do nějakého Excelu s nějakým názvem. Samozřejmě někdy zapomněl, nebyly tam popisky, náhledy atd.

Nesnáším, když se ztrácí čas prací, kterou lépe zastanou stroje a to je zrovna tento případ. Udělal jsem si proto jednoduchý Google (Sheets) Apps Script, který funguje takto:

  1. Vezme seznam všech listů v Google Tabulce a spustí nad nimi smyčku:
    • vezme název listu
    • zjistí, jestli existuje YouTube kanál, který se jmenuje jako název listu
    • když ano, smaže list a nahraje do něj seznam všech videí v daném YouTube kanálů – URL, URL obrázku, Titulek, Popis, Datum publikování
    • upraví formáty a např. funkcí IMAGE doplní aktuální obrázek videa
  2. A tenhle skript se spouští každou hodinu

Výsledkem tak je stále aktuální seznam všech videí na všech našich (resp. i cizích – libovolných zadaných) YouTube kanálech a když by někdo přidat nový kanál, tak prostě stačí přidat nový list, pojmenuje jej názvem kanálu a do hodiny se stáhne opět kompletní seznam (případně může stisknout tlačítko v menu a načte se hned). Je tam i záložka pro ruční zadávání videí, abychom měli přehled i o takových, která jsou na jiné službě nebo u někoho, u koho nepotřebujeme kompletní přehled.

Takže jak na to?

V první fázi je potřeba funkce, která stáhne seznam videí z YouTube přes standardní YouTube Service, která je součástí App Scriptu a využívá YouTube Data API.

Původně jsem se domníval, že to udělám jako funkci Tabulek, tedy že napíšu =youtube(„nazev-kanalu“) a ono to rovnou vyplní tabulku daty. Jenže jak jsem později zjistil, ve funkcích YouTube Service nefunguje, musel bych to řešit dotazováním na URL z Data API a to mi za to nestálo.

Funkce je to myslím primitivní, snad jedinou komplikací je to, že stahuji videa po 25. a stránkuji, abych se vyhnul problémům u obsáhlých kanálů. Z vrácené hodnoty (viz dokumentace k Playlistitems) vypreparuji kýžené detaily a ty ukládám do pole, které pak vracím jako výsledek funkce:

/**
* Return YouTube videos details for given channel
*
* @param {string} username YouTube channel name (username) - see channel URL
* @return Array representing key params of YouTube videos in given channel
*/
function getVideos(username) {
 var results = YouTube.Channels.list('contentDetails', {forUsername: username});
 var array = [];
 for(var i in results.items) {
 var item = results.items[i];
 // Get the playlist ID, which is nested in contentDetails, as described in the
 // Channel resource: https://developers.google.com/youtube/v3/docs/channels
 var playlistId = item.contentDetails.relatedPlaylists.uploads;
 
 var nextPageToken = '';
 
 // This loop retrieves a set of playlist items and checks the nextPageToken in the
 // response to determine whether the list contains additional items. It repeats that process
 // until it has retrieved all of the items in the list.
 while (nextPageToken != null) {
 var playlistResponse = YouTube.PlaylistItems.list('snippet', {
 playlistId: playlistId,
 maxResults: 25,
 pageToken: nextPageToken
 });
 
 for (var j = 0; j < playlistResponse.items.length; j++) {
 var playlistItem = playlistResponse.items[j];
 array.push([
 playlistItem.snippet.resourceId.videoId,
 playlistItem.snippet.thumbnails['default']['url'],
 playlistItem.snippet.title,
 playlistItem.snippet.description,
 playlistItem.snippet.publishedAt,
 
 ]);
 }
 nextPageToken = playlistResponse.nextPageToken;
 }
 }
 return array;
 }

Druhá funkce řeší to procházení všech listů v aktuální tabulce, zjištění názvů a vyplnění hodnot z YouTube:

function getSheetsVideos () {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets();
  
  for (var n = 0; n < sheets.length ; n++ ) {    
    var sheet = ss.getSheets()[n];
    var sheetName = sheet.getName();
    var videos = (getVideos (sheetName)); 
    if (videos.length == 0) continue;
    sheet.clear();
    sheet.appendRow(['URL','Thumbnail','Title','Description', 'Published at']) ;
    var values = [];
    for (var video in videos) {
      values.push(["https://www.youtube"+".com/watch?v="+videos[video][0],'=image("'+videos[video][1]+'")',videos[video][2],videos[video][3], new Date(videos[video][4])]);
    }
    sheet.getRange(2, 1, videos.length , 5).setValues(values)    
    sheet.getDataRange().setVerticalAlignment("middle");
    sheet.setColumnWidth(1, 320);
    sheet.setColumnWidth(2, 120);
    sheet.setColumnWidth(3, 300);
    sheet.setColumnWidth(4, 400);    
    sheet.setColumnWidth(5, 100); 
    sheet.getRange("C:D").setWrap(true);
    sheet.getRange("1:1").setFontWeight("bold");
    sheet.getRange("C:C").setFontWeight("bold");
    for(var i=2; i<=videos.length+1; i++){
      sheet.setRowHeight(i, 90);
    };
  }
}

No a to je vlastně všechno, ještě jsem přidal funkci, která při otevření sešitu vytvoří položku v menu pro aktualizaci všech videí, kdybych to potřeboval rychleji než do hodiny:

function onOpen() {
 var ui = SpreadsheetApp.getUi();
 // Or DocumentApp or FormApp.
 ui.createMenu('Aktualizace')
 .addItem('Aktualizace všech videí', 'getSheetsVideos')
 .addToUi();
}

No a pak samozřejmě nastavit automatické stahování (Zdroje / Spouštěče aktuálního projektu). Před prvním spuštěním bylo také třeba zapnout podporu YouTube Data API (Zdroje / Pokročilé služby Google) a tuším to chtělo i nějakou autorizaci. Výsledek vidíte na obrázku

Podnět pro vás: co takhle tam přidat statistiky shlédnutí videí? Kdo se do toho vrhnete? Napovím – Google Apps Script YouTube Analytics Service.