Složitější vytváření maker
- Oli
- Člen | 1215
Ahoj,
hledal jsem, ale nikde jsem nenašel žádný článek, který by makra rozebral
dopodrobna. Např. jaký proměnný jsou dostupný v šabloně (_control,
_presenter, …), jak si vybrat konkrétní atribut a pracovat s ním (viz
divoký parsování atributů níže) atd…
Chtěl bych za použití nette-webimages vytvořit makro, který by udělalo hezčí syntax pro picturefill a zároveň by pak (třeba jednou) jen zahodilo picturefill a používalo nativní podporu srcset. To makro se mě nějak povedlo splácnout, ale přijde mě to takový dost divoký.
Oproti defaultnímu
použití webimages tam přidávám nepovinné atributy path
a
type
. Mělo by to fungovat tak, že se uvede nejmenší fotka jako
první atribut (src). Srcset potom obsahuje jen ty části cesty, které se
liší od obrázku ze src
.
Šlo by to nějak učesat nebo to je uplně blbě (kde, proč, jak to udělat správně)? Je to můj první pokus o trochu komplexnější makro, tak prosím o shovívavost :-). (vím že to nepokrývá všechny stavy a není to blbuvzodrný, ale je to jen první nástřel/funkční prototyp)
Díky za připomínky/názory.
{picture src => "P1030303.jpg, 160, 120, path => test, type => photos",
srcset => "(width => 380, height => 240) 600w, (width => 1600, height => 1200) 1600w"}
$me->addMacro('picture', 'echo %modify(My\Macro::prepareArguments([%node.args], $_presenter))');
// ...
public static function prepareArguments(array $arguments, Presenter $presenter)
{
$string = '<span data-picture>';
$src = NULL;
$image = NULL;
foreach ($arguments as $key => $value) {
if ($key === 'src' || (!array_key_exists('src', $arguments) && $key === 0))
{
$value = self::clearData($value);
foreach ($value as $valueKey => $item)
{
if (Strings::contains($item, '=>'))
{
$splited = explode('=>', $item);
$splited[1] = str_replace('"', '', $splited[1]);
$splited[1] = str_replace('\'', '', $splited[1]);
$value[$splited[0]] = $splited[1];
unset($value[$valueKey]);
}
}
$src = \DotBlue\WebImages\Macros::prepareArguments($value);
$link = $presenter->link("//:Nette:Micro:", $src);
$string .= "<span data-src=\"" . $link . "\"></span>";
$image = $link;
} elseif ($key === 'srcset')
{
foreach (Strings::matchAll($value, '~\((.*?)\) [0-9]+w~') as $item)
{
$args = NULL;
$width = explode(') ', $item[0]);
$viewport = (int) substr($width[1], 0, -1);
foreach (self::clearData($item[1]) as $key => $photoArgs)
{
$photo = explode('=>', $photoArgs);
$args[$photo[0]] = $photo[1];
}
$args = $args + $src;
$link = $presenter->link("//:Nette:Micro:", $args);
$string .= "<span data-src=\"" . $link . "\" data-media=\"(min-width: " . $viewport . "px)\"></span>";
}
}
}
if (!is_null($image))
{
$string .= '<noscript><img src="' . $image . '"></noscript>';
}
$string .= '</span>';
return $string;
}
private static function clearData($data)
{
$data = str_replace([', ', ' => '], [',', '=>'], $data);
$data = explode(',', $data);
return $data;
}
Výstup to vygeneruje
<span data-picture>
<span data-src="http://localhost/projekt/photos/test/160x120/P1030303.jpg"></span>
<span data-src="http://localhost/projekt/photos/test/380x240/P1030303.jpg" data-media="(min-width: 600px)"></span>
<span data-src="http://localhost/projekt/photos/test/1600x1200/P1030303.jpg" data-media="(min-width: 1600px)"></span>
<noscript>
<img src="http://localhost/projekt/photos/test/160x120/P1030303.jpg">
</noscript>
</span>