/ Gists

Gists

On gists

Dynamic component

Tailwind CSS

index.html #

<!-- 
- https://www.youtube.com/watch?v=sxxUK0l8jKE 
- https://play.tailwindcss.com/4cuLPqCv05
-->

  <div class="p-20 flex justify-center items-center gap-12">
  <img class="avatar-sm" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
  <img class="avatar" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
  <img class="avatar-lg" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
  <img class="avatar-xl" src="https://res.cloudinary.com/thirus/image/upload/v1705061543/images/avatar.png" alt="" />
</div>

On gists

IconList (scan)

Nette

IconListPresenter.php #

class IconListPresenter extends \App\Presenters\BasePresenter
{

	/**
	 * @var Context
	 * @inject
	 */
	public $connection;

	public function actionDefault()
	{

		$icons = scandir(INDEX_DIR . '/../webapp/frontapp/svg');
		$list = [];
		foreach ($icons as $icon) {
			if (!strpos($icon, 'svg')) {
				continue;
			}

			$list[] = $icon;
		}


		$this->template->occurrences = $this->findOccurrences($list);
		$this->template->list = $list;

		
		$scan = array_diff(scandir(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/'), ['.', '..']);
		$urls = [];
		foreach ($scan as $iconName) {
			if (is_file($file = INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/' . $iconName)) {
				$urls[str_replace('.txt', '', $iconName)] = file_get_contents($file);
			}
		}

		$this->template->urls = $urls;
	}

	public function actionUpdateIcons()
	{

		$icons = scandir(INDEX_DIR . '/../webapp/frontapp/svg');
		$list = [];
		foreach ($icons as $icon) {
			if (!strpos($icon, 'svg')) {
				continue;
			}

			$list[] = $icon;
		}
		
		$scan = array_diff(scandir(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/'), ['.', '..']);
		$urls = [];
		foreach ($scan as $iconName) {
			if (is_file($file = INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/' . $iconName)) {
				$urls[str_replace('.txt', '', $iconName)] = file_get_contents($file);
			}
		}

		foreach ($list as $icon) {
			if (isset($urls[$icon])) {
				$url = $urls[$icon];
				$url = str_replace('48px.svg', '20px.svg', $url);

				$fetchIcon = file_get_contents($url);
				$fetchIcon = str_replace('><path', ' viewBox="0 0 20 20"><path fill="currentColor" ', $fetchIcon);
				file_put_contents(INDEX_DIR.'/../webapp/frontapp/svg/' . $icon, $fetchIcon);

				// save what we saved
				//file_put_contents(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/' . $icon . '.txt', $url);
			}
		}

		$this->terminate();
	}


	private function createListFiles()
	{
		$allFiles = [];

		foreach (Finder::findFiles('*.latte')->from(INDEX_DIR . '/../app/BrandCloudModule/') as $key => $splFile) {
			$fileResouce = file_get_contents($key);
			$allFiles[$key] = $fileResouce;
		}

		foreach (Finder::findFiles('*.vue')->from(INDEX_DIR . '/../webapp/frontapp/components/') as $key => $splFile) {
			$fileResouce = file_get_contents($key);
			$allFiles[$key] = $fileResouce;
		}

		return $allFiles;
	}

	private function findOccurrences($icons)
	{
		$allFiles = $this->createListFiles();
		$all = [];

		foreach ($allFiles as $filePath => $fileResource) {
			foreach ($icons as $icon) {
				$icon = str_replace('.svg', '', $icon);
				//$nicePath = explode('..', $filePath)[1];
				$nicePath = $filePath;

				preg_match_all('~<aw-icon.+icon=("|\')' . preg_quote($icon) . '("|\')~', $fileResource, $m1);
				preg_match_all('~("|\')' . preg_quote($icon) . '("|\')~', $fileResource, $m2);

				if (!isset($all[$icon][$nicePath])) {
					$all[$icon][$nicePath] = 0;
				}

				if (count($m1[0])) {
					$all[$icon][$nicePath] += count($m1[0]);
				}

				if (count($m2[0])) {
					$all[$icon][$nicePath] += count($m2[0]);
				}
			}
		}

		return $all;
	}


	public function actionSaveUrlIcon()
	{
		// RAW POST DATA
		$data = json_decode(file_get_contents("php://input"));

		// icon fetch & save
		$url = str_replace('48px.svg', '20px.svg', $data->url);
		$fetchIcon = file_get_contents($url);
		$fetchIcon = str_replace('><path', ' viewBox="0 0 20 20"><path fill="currentColor" ', $fetchIcon);
		file_put_contents(INDEX_DIR.'/../webapp/frontapp/svg/' . $data->icon, $fetchIcon);

		// save what we saved
		file_put_contents(INDEX_DIR.'/../app/ServiceModule/templates/IconList/icons-list/'.$data->icon . '.txt', $data->url);

		// data
		echo json_encode($data);

		$this->terminate();
	}
}

On gists

Google Spread Sheet via Google_Client

PHP Libs PHP

index.php #

<?php
/*

https://www.nidup.io/blog/manipulate-google-sheets-in-php-with-api

*/

require './vendor/autoload.php'; 

// configure the Google Client
$client = new \Google_Client();
$client->setApplicationName('Google Sheets API');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]); 
$client->setAccessType('offline');
// credentials.json is the key file we downloaded while setting up our Google Sheets API
$path = '***'; //google console admin need to generate this file
$client->setAuthConfig($path);

// configure the Sheets Service
$service = new \Google_Service_Sheets($client);
$spreadsheetId = '***'; // get with share with and see to url



// the spreadsheet id can be found in the url https://docs.google.com/spreadsheets/d/143xVs9lPopFSF4eJQWloDYAndMor/edit
$spreadsheet = $service->spreadsheets->get($spreadsheetId);
var_dump($spreadsheet);


// all values
$range = 'List 1'; // here we use the name of the Sheet to get all the rows
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);



// rows by range
$range = 'List 1!A1:F10';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);



// cells of column
$range = 'List1!B1:B21'; // the column containing the movie title
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$values = $response->getValues();
var_dump($values);



// rows into json objects
$range = 'Sheet1';
$response = $service->spreadsheets_values->get($spreadsheetId, $range);
$rows = $response->getValues();
// Remove the first one that contains headers
$headers = array_shift($rows);
// Combine the headers with each following row
$array = [];
foreach ($rows as $row) {
    $array[] = array_combine($headers, $row);
}
var_dump($array);
/*
$jsonString = json_encode($array, JSON_PRETTY_PRINT);
print($jsonString);

*/


// append new row
$newRow = [
    '456740',
    'Hellboy',
    'https://image.tmdb.org/t/p/w500/bk8LyaMqUtaQ9hUShuvFznQYQKR.jpg',
    "Hellboy comes to England, where he must defeat Nimue, Merlin's consort and the Blood Queen. But their battle will bring about the end of the world, a fate he desperately tries to turn away.",
    '1554944400',
    'Fantasy, Action'
];
$rows = [$newRow]; // you can append several rows at once
$valueRange = new \Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$range = 'List 1'; // the service will detect the last row of this sheet
$options = ['valueInputOption' => 'USER_ENTERED'];
$service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $options);



// update existing
$updateRow = [
    '456740',
    'Hellboy Updated Row',
    'https://image.tmdb.org/t/p/w500/bk8LyaMqUtaQ9hUShuvFznQYQKR.jpg',
    "Hellboy comes to England, where he must defeat Nimue, Merlin's consort and the Blood Queen. But their battle will bring about the end of the world, a fate he desperately tries to turn away.",
    '1554944400',
    'Fantasy, Action'
];
$rows = [$updateRow];
$valueRange = new \Google_Service_Sheets_ValueRange();
$valueRange->setValues($rows);
$range = 'Sheet1!A2'; // where the replacement will start, here, first column and second line
$options = ['valueInputOption' => 'USER_ENTERED'];
$service->spreadsheets_values->update($spreadsheetId, $range, $valueRange, $options);



// delete some row
$range = 'Sheet1!A23:F24'; // the range to clear, the 23th and 24th lines
$clear = new \Google_Service_Sheets_ClearValuesRequest();
$service->spreadsheets_values->clear($spreadsheetId, $range, $clear);


/** with text formatting */
$range = 'List 1!B4';
$params = [
    'ranges' => $range,
    'fields' => 'sheets.data.rowData.values',
    'includeGridData' => true,
];

$response = $service->spreadsheets->get($spreadsheetId, $params);
$data = $response->getSheets()[0]['data'][0]['rowData'][0]['values'][0];

$formattedValue = $data['formattedValue'];
$hyperlink = $data['hyperlink'];
$userEnteredFormat = $data['userEnteredFormat'];

var_dump($formattedValue);
var_dump($hyperlink);
var_dump($userEnteredFormat);

On gists

Css grid by KevinPowell sheats

CSS CSS trick

grid.css #

/* Adjustable grid */
.grid {
 --column-count: 3;
 display: grid;
 grid-template-columns: repeat(var(--column-count), 1fr);
}

/* modifiers */
.grid-3 { --column-count: 3; }
.grid-4 { --column-count: 4; }
.grid-5 { --column-count: 5; }

/* custom */
.grid { --column-count: 1; }
@media (min-width: 600px) {
 .grid { --column-count: 3; }
}
@media (min-width: 960px) {
 .grid { --column-count: 4; }
}

/*
-----------------------------------------------------
*/

/* grid auto-columns */
.auto-grid {
 display: grid;
 grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
}

/*
-----------------------------------------------------
*/

/* Pushing the footer down */
.main-layout {
 min-height: 100vh;
 display: grid;
 grid-template-rows: rows 1fr rows;
}


/*
-----------------------------------------------------
*/

/* The stack */
.the-stack {
 display: grid;
 grid-template-areas: "stack";
 place-items: center; 
}
.the-stack > * {
 grid-area: stack;
}

On gists

BroadCastChannel (sync between 2 tabs immediately)

JavaScript

index.html #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <button>CLICK ME</button>

        <script>
            const channel = new BroadcastChannel('myChannel');
            document.getElementsByTagName('button')[0].addEventListener('click', e => {
                channel.postMessage('Hello from Tab 1' + new Date().getSeconds);

                console.log('CHANNEL 1');
            });

            channel.onmessage = event => {
                console.log('Message received in Tab 2:', event.data);

                console.log('CHANNEL 2');
            };
        </script>
    </body>
</html>

On gists

Delete recursively from child to parent

PHP AW

delete-recursively-from-child.ph #

<?php

	private function deleteDuplicateRecursive(Tables\Navigation $duplicateItem)
	{
		/*
		// OLD
		$findDescendants = function(Tables\Navigation $parent, array $stack = [], $level = 1) use (&$findDescendants) {
			$children = $this->navigation->getAdjacencyList($parent->domain_id)->getChildren($parent->id);
			
			foreach ($children as $child) {
				$stack[$level][] = $child;
				$stack = $findDescendants($child, $stack, $level + 1);
			} 
				
			return $stack;
		};

		// mazeme deti odspoda nahoru
		$descendants = $findDescendants($duplicateItem);

		foreach (array_reverse($descendants, true) as $level => $descendantArr) {
			foreach ($descendantArr as $descendant) {
				$this->deleteDuplicate($descendant);
			}
		}
		*/

    // NEW, better, shorter
		$children = $this->navigation->getAdjacencyList($duplicateItem->domain_id)->getChildren($duplicateItem->id);
		foreach ($children as $child) {
			$this->deleteDuplicateRecursive($child);
		}

		// na zaver i roota
		$this->deleteDuplicate($duplicateItem);
	}

On gists

full width in container

CSS CSS trick

index.html #

<!--
https://jsbin.com/heqamezuju/edit?html,css,output
-->

	<grid>
		
		<item class="l">
			
			aaa
			
		</item>
		<item class="r">
			
			bbb
			
		</item>
	</grid>


  <style>
    grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	max-width: 500px;
	outline: 2px solid gray;
	height: 500px;
	margin: auto;
	
}


item {
	padding: 10px;
}

.r, .l {
	position: relative;	
	isolation: isolate;
}

.r:after {
	background: lightgray;
	top: 0;
	bottom: 0;
	left: 0;
	width: 50vw;
	position: absolute;
	content: "";
	z-index: -1;
}


.l:after {
	background: lightpink;
	top: 0;
	bottom: 0;
	right: 0;
	width: 50vw;
	position: absolute;
	content: "";
	z-index: -1;
}


    
  </style>



On gists

Advanced from Tailwind 3

Tailwind CSS

index.html #

<!--
https://lab.rjwebdesign.cz/tailwindcss/advanced/
-->

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link href="./dist/output.css" rel="stylesheet" />
    </head>
    <body class="p-5">
        <h1 class="mb-4 font-bold text-3xl">1) Peer / Group</h1>
        <div class="peer group group/second group/third grid place-items-center bg-slate-600 w-20 h-20 mt-10">
            <div class="bg-black w-5 h-5 group-hover:bg-red-500"></div>
            <div class="bg-black w-5 h-5 group-hover/second:bg-green-500"></div>
            <div class="bg-black w-5 h-5 group-hover/third:bg-orange-500"></div>
        </div>
        <div class="w-20 h-20 bg-orange-400 mt-10 peer-hover:bg-violet-300"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">2) Animation / Transition</h1>
        <div class="w-20 h-20 bg-teal-700 transition-all hover:bg-red-300 delay-300 duration-150"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">3) Responsivenes / BP (ranges)</h1>
        <div class="w-20 h-20 bg-red-500 md:max-lg:bg-green-500"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">4) Dynamic variants / props / values</h1>
        <div class="w-20 h-20 bg-[theme('colors.blue.300')]"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">5) TW extend / config</h1>
        <div class="w-20 h-20 neon-blue"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">6) TW extend -> COLORS</h1>
        <div class="text-primary">Hello how are you?</div>
    </body>
</html>