Jump to content

Boost

Members
  • Posts

    127
  • Joined

  • Last visited

Posts posted by Boost

  1. Hey,

    I have a single-page template featuring a straightforward HTML form with a select element, as shown below:

    <form id="case-study_cat" action="/case-studies/" method="POST">
    	<div class="uk-margin-bottom">
        	<select id="selected" class="uk-select" aria-label="Select" name="selected">
        		<option value="all" selected="">All</option>
              	<option value="financial-services">Financial Services</option>
            	<option value="insurance">Insurance</option>
              	<option value="telecom">Telecom</option>
              	<option value="e-commerce">E-commerce</option>
              	<option value="partner">Partner</option>
              	<option value="security">Security</option>
              	<option value="public-sector">Public Sector</option>
              	<option value="energy">Energy</option>
              	<option value="aviation">Aviation</option>
              	<option value="events">Events</option>
          	</select>
        </div>
    </form>

    Upon selecting an option, the template dynamically generates a list of posts based on the chosen category.

    Now, on another page—let's say the homepage—I'd like to include a button that links directly to a category from that select form. This way, when users land on that page, they immediately see the list of posts within the chosen category. Does this plan make sense? Is there a method to accomplish this?

    Cheers!

     

  2. Hei @ngrmm. I have a blog index page like below. As you see, I have each post tagged with a category. However, my posts URL do not contain the category, so they are like https//acme.com//blog/what-is-conversational-ai/. I want to have a simple select dropdown with my categories: All, Technology, Insights, Customer Experience..etc. So, when you select, for example "Insights", only posts from that category would appear. 

    2024-02-19_12-45.thumb.png.306dfa1903e67b1b96cc566002868ede.png

  3. Hei,

    I'm trying to create a simple filter for my blog posts, but have not had luck yet. The posts use a page reference field value as their category. However, different from the examples I found in the forum and below, I don't have the categories as part of my URL, and because of that, I can't use the url segments. On the front end, I also have pagination, which makes things a bit more complex for me.

    Here is my setup: I have two templates. One is blog-index.php and blog.php.


    2024-02-19_10-16.thumb.png.8ae4be0b44267801b6eced512a96c9ac.png

    And inside the blog post:

    2024-02-19_10-16_1.png.3fb666b3ba21bacaeb84cf26a44cfedd.png

  4. Hey,

    Since you all are much smarter than me, I'd really appreciate your input on this task.

    So, here's the deal: I've got a layout with two columns, a sidebar, and the main section. What I want to do is take the H2 headings from my blog post and turn them into a table of contents. That way, I can have a section on my sidebar that acts like a TOC. Sure, I could manually add those entries to the TOC field, but do you happen to know of a more automatic way to do it?

    Cheers

  5. Hey,

    Thanks for the updates!

    Nice website, @ryan. Just out of curiosity, why am I seeing this?

    <link rel="stylesheet" href="/wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/css/uikit.min.css">
    <script src="/wire/modules/Jquery/JqueryCore/JqueryCore.js"></script>
    <script src="/wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/js/uikit.min.js"></script>

    Any specific reason for doing this instead of:

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.18.0/dist/css/uikit.min.css" />

    Cheers

  6. And here is the same thing, but for JS files. The implementation is straightforward; you only need to add one PHP file to your server and make a few tweaks. The main difference is that this script does not minify the files. During my tests, minifying the JS files didn't work well for me.

    My setup:
    -site/
      -templates/
        - inc/
        - scripts/
        

    _init.php
    Include the CombinedJS.php file at the top of my _init.php:

    include_once('./inc/CombinedJS.php');

    _main.php
    Add the following to the <head> section:

    <?php 
    	$jsFiles = [
    	   	paths()->templates . 'scripts/uikit.min.js',
    	   	paths()->templates . 'scripts/uikit-icons.min.js',
    	];
    		
    	echo CombinedJS::JS($jsFiles);
    ?>

    CombinedJS.php

    <?php namespace ProcessWire;
    
    use RuntimeException;
    
    /**
     * Class CombinedJS
     *
     * A class for combining JavaScript files and generating a script tag for the combined JavaScript.
     */
    class CombinedJS {
    
        /**
         * @var string|null The output directory for saving the combined JavaScript file.
         */
        private static $outputDirectory;
    
        /**
         * @var string|null Hash of the concatenated content of JavaScript files.
         */
        private static $filesHash;
    
        /**
         * Initializes the output directory if it is not already set.
         */
        private static function initOutputDirectory() {
            if (!isset(self::$outputDirectory)) {
                self::$outputDirectory = paths()->templates . 'scripts/';
            }
        }
    
        /**
         * Checks if a directory is writable.
         *
         * @param string $directory The directory path to check.
         *
         * @return bool True if the directory is writable, false otherwise.
         */
        private static function isWritableDirectory($directory) {
            // Check if the directory exists
            if (!is_dir($directory)) {
                return false;
            }
    
            // Check if the directory is writable
            if (!is_writable($directory)) {
                return false;
            }
    
            return true;
        }
    
        /**
         * Combines JavaScript files without minifying them.
         *
         * @param array $files An array of JavaScript file paths.
         *
         * @return string The combined JavaScript content.
         */
        private static function combineJS(array $files): string {
            $combinedJS = '';
    
            foreach ($files as $file) {
                // Read the content of each JavaScript file
                $jsContent = file_get_contents($file);
    
                // Append the JavaScript content to the combined JavaScript content
                $combinedJS .= $jsContent;
            }
    
            return $combinedJS;
        }
    
        /**
         * Generates a unique filename for the combined JavaScript file based on the provided file paths.
         *
         * @param array $files An array of JavaScript file paths.
         *
         * @return string The generated combined JavaScript filename.
         */
        private static function generateCombinedFilename(array $files): string {
            return md5(implode('', $files)) . '.js';
        }
    
        /**
         * Saves the combined JavaScript content to a file.
         *
         * @param string $filename The filename for the combined JavaScript file.
         * @param string $content The combined JavaScript content to be saved.
         *
         * @throws RuntimeException If there is an error writing the file to disk.
         */
        private static function saveToFile(string $filename, string $content): void {
            // Save the combined JavaScript content to the specified file
            $filePath = self::$outputDirectory . DIRECTORY_SEPARATOR . $filename;
    
            if (file_put_contents($filePath, $content) === false) {
                $error = error_get_last();
                $errorMessage = isset($error['message']) ? $error['message'] : 'Unknown error';
                throw new RuntimeException('Failed to write the combined JavaScript file to disk. Error: ' . $errorMessage);
            }
        }
    
        /**
         * Generates a script tag for the combined JavaScript file based on the provided file paths.
         *
         * @param array $files An array of JavaScript file paths.
         *
         * @return string The script tag for the combined JavaScript file.
         *
         * @throws RuntimeException If the output directory is not writable.
         */
        public static function JS(array $files): string {
            // Initialize the output directory
            self::initOutputDirectory();
    
            // Ensure the output directory is writable
            if (!self::isWritableDirectory(self::$outputDirectory)) {
                throw new RuntimeException('The output directory is not writable.');
            }
    
            // Combine JavaScript files without minifying
            $combinedJS = self::combineJS($files);
    
            // Generate a unique filename for the combined JavaScript file
            $combinedFilename = self::generateCombinedFilename($files);
    
            // Save the combined JavaScript content to a file
            self::saveToFile($combinedFilename, $combinedJS);
    
            // Return the script tag
            return '<script src="' . urls()->templates . 'scripts/' . $combinedFilename . '"></script>';
        }
    
    }

    Notes:

    • Ensure that you have writing permissions for the $outputDirectory location.
    • The combined JS file will be generated and saved only if the files have changed or if the file doesn't exist on disk.
    • The order of the combined file will adhere to the sequence specified in the array.
    • Modify the hardcoded paths based on your requirements.

    Any suggestions for improvements are welcome!

    Cheers!

  7. 1 hour ago, bernhard said:

    I don't think that this is true any more with HTTP2 because browsers can download multiple files at once. That's why I didn't implement something like this in RockFrontend. But I'm not sure 🙂 

    Me neither 🙂

    I had to write the script because https://pagespeed.web.dev/ complained about my multiple files.

    • Sad 1
  8. This is my approach to combining CSS files for improved page speed. The implementation is straightforward; you only need to add one PHP file to your server and make a few tweaks.

    My setup:
    -site/
      -templates/
        - inc/
        - styles/
        

    _init.php
    Include the CombinedCSS.php file at the top of my _init.php:

    include_once('./inc/CombinedCSS.php');

    _main.php
    Add the following to the <head> section:

    <?php 
    	$cssFiles = [
        	paths()->templates . 'styles/uikit.min.css',
        	paths()->templates . 'styles/uikit.ext.css',
        	paths()->templates . 'styles/main.css'
    	];
    		
    	echo CombinedCSS::CSS($cssFiles);
    ?>

    CombinedCSS.php

    <?php namespace ProcessWire;
    
    /**
     * Import the RuntimeException class for throwing runtime exceptions.
     */
    use RuntimeException;
    
    /**
     * Class CombinedCSS
     * 
     * A class for combining and minifying CSS files and generating a link tag for the combined CSS.
     */
    class CombinedCSS {
        
        /**
         * @var string|null The output directory for saving the combined CSS file.
         */
        private static $outputDirectory;
    
        /**
         * @var string|null Hash of the concatenated content of CSS files.
         */
        private static $filesHash;
    
        /**
         * Initializes the output directory if it is not already set.
         */
        private static function initOutputDirectory() {
            if (!isset(self::$outputDirectory)) {
                self::$outputDirectory = paths()->templates . 'styles/';
            }
        }
    
        /**
         * Checks if a directory is writable.
         * 
         * @param string $directory The directory path to check.
         * @return bool True if the directory is writable, false otherwise.
         */
        private static function isWritableDirectory($directory) {
            // Check if the directory exists
            if (!is_dir($directory)) {
                return false;
            }
    
            // Check if the directory is writable
            if (!is_writable($directory)) {
                return false;
            }
    
            return true;
        }
    
        /**
         * Combines and minifies an array of CSS files.
         * 
         * @param array $files An array of CSS file paths.
         * @return string The combined and minified CSS content.
         */
        private static function combineAndMinifyCSS(array $files): string {
            $combinedCss = '';
    
            foreach ($files as $file) {
                // Read the content of each CSS file
                $cssContent = file_get_contents($file);
    
                // Minify the CSS content (you can replace this with your preferred minification logic)
                $minifiedCss = self::minifyCSS($cssContent);
    
                // Append the minified CSS to the combined CSS content
                $combinedCss .= $minifiedCss;
            }
    
            return $combinedCss;
        }
    
        /**
         * Minifies CSS content.
         * 
         * @param string $css The CSS content to be minified.
         * @return string The minified CSS content.
         */
        private static function minifyCSS(string $css): string {
            // Replace this with your preferred CSS minification logic
            // Example: removing comments, extra whitespaces, etc.
            $minifiedCss = preg_replace('/\/\*.*?\*\//s', '', $css);
            $minifiedCss = preg_replace('/\s+/', ' ', $minifiedCss);
    
            return $minifiedCss;
        }
    
        /**
         * Generates a unique filename for the combined CSS file based on the provided file paths.
         * 
         * @param array $files An array of CSS file paths.
         * @return string The generated combined CSS filename.
         */
        private static function generateCombinedFilename(array $files): string {
            return md5(implode('', $files)) . '.css';
        }
    
        /**
         * Saves the combined CSS content to a file.
         * 
         * @param string $filename The filename for the combined CSS file.
         * @param string $content The combined CSS content to be saved.
         * 
         * @throws RuntimeException If there is an error writing the file to disk.
         */
        private static function saveToFile(string $filename, string $content): void {
            // Save the combined CSS content to the specified file
            $filePath = self::$outputDirectory . DIRECTORY_SEPARATOR . $filename;
    
            if (file_put_contents($filePath, $content) === false) {
                $error = error_get_last();
                $errorMessage = isset($error['message']) ? $error['message'] : 'Unknown error';
                throw new RuntimeException('Failed to write the combined CSS file to disk. Error: ' . $errorMessage);
            }
        }
    
        /**
         * Generates a link tag for the combined CSS file based on the provided file paths.
         * 
         * @param array $files An array of CSS file paths.
         * @return string The link tag for the combined CSS file.
         * @throws RuntimeException If the output directory is not writable.
         */
        public static function CSS(array $files): string {
            // Initialize the output directory
            self::initOutputDirectory();
    
            // Ensure the output directory is writable
            if (!self::isWritableDirectory(self::$outputDirectory)) {
                throw new RuntimeException('The output directory is not writable.');
            }
    
            // Combine and minify CSS files
            $combinedCss = self::combineAndMinifyCSS($files);
    
            // Check if the files have changed by comparing their hash
            $currentFilesHash = md5($combinedCss);
            $combinedFilename = '';
    
            if ($currentFilesHash !== self::$filesHash) {
                // If the files have changed, generate a unique filename for the combined CSS file
                $combinedFilename = self::generateCombinedFilename($files);
    
                // Save the combined CSS content to a file
                self::saveToFile($combinedFilename, $combinedCss);
    
                // Update the files hash
                self::$filesHash = $currentFilesHash;
            } else {
                // If the files have not changed, check if the file exists on disk
                $combinedFilename = self::generateCombinedFilename($files);
                $filePath = self::$outputDirectory . DIRECTORY_SEPARATOR . $combinedFilename;
    
                if (!file_exists($filePath)) {
                    // If the file doesn't exist, save the combined CSS content to a file
                    self::saveToFile($combinedFilename, $combinedCss);
                }
            }
    
            // Return the link tag
            return '<link rel="stylesheet" href="' . urls()->templates . 'styles/' . $combinedFilename . '">';
        }
    }

    Notes:

    • Ensure that you have writing permissions for the $outputDirectory location.
    • The combined CSS file will be generated and saved only if the files have changed or if the file doesn't exist on disk.
    • The order of the combined file will adhere to the sequence specified in the array.
    • Modify the hardcoded paths based on your requirements.

    Any suggestions for improvements are welcome!

    Cheers!

    • Like 1
  9. On 6/23/2016 at 3:11 PM, EyeDentify said:

    Hello There PW fans and users.

    I Thought i share something that i came up with a while ago when i decided to adopt the teachings in this guide:
    MaintainableCSS

    This guide has made my development much easier cause i allways was stressed about having all code in one giant file and jumping around trying to keep everything organized and clear.

    So i decided to go with modules, as i call them, having all the CSS belonging to a specific module in one file, and also the responsive media querys that belongs to the module in the same file. Now... so far so good. Turns out that there is a 31 file limit in browsers to how many files you can load with css.

    And also i wanted to make less HTTP requests, so i started thinking, and came up with a simple PHP script that i run on my PW site in a hidden template and when that PHP script runs, it combines/compiles or merges the CSS module files together to one giant file that i link to in my website header.

    This way, there is one HTTP request for all the CSS that runs the site, minus some third party stuff.

    Lets look at the PHP script

    <?PHP             
    /* 
        EyeDentifys CSS File combiner. v1.0
        
        Array of essential files - update as needed.
        We do this to ensure the order of how the files are combined.
        You can have as many CSS module files here as you want.
        
        Remember that the combined file is compiled in the order they
        are placed in the array.
        
        Remember to check all the paths so they reflect your setup before use.
        And also, the combined file is overwritten without notice when you re-combine.
    */
    $cssModules[] = 'module_global.css';
    $cssModules[] = 'module_table.css';
    $cssModules[] = 'module_forms.css';
    $cssModules[] = 'module_layout.css';
    
    
    /* init vars */
    $str = '';
    $moduleCount = 0;
    $errorCount = 0;
    $listFiles = '';
    
    /* add a string with the latest update time and date to the top of the combined file */
    $dateStr = date('Y-m-d H:i:s');
    $str .= '/* Combined file last updated at ' . $dateStr . ' */' . PHP_EOL;
    
    /* go through modules and concatenate them in a string var */
    foreach($cssModules AS $key => $module){
    
        /* check if the file exist */
        if(file_exists('css/modules/' . $module)){
    
            /* read file data */
            $str .= file_get_contents('css/modules/' . $module);
    
            /* add module count - used for output in template */
            $moduleCount++;
    
            /* add the file to list */
            $listFiles[] = '[' . $module . ']';
    
        } else {
    
            /* if the file do not exist add it to the "do not exist" list */
            $listFiles[] = 'Error - file [' . $module . '] do not exist!';
            
            /* increment error count */
            $errorCount++;
        }
    }
    
    /* render the combined css */
    echo('<h2>Combined CSS</h2><pre class="code-view-pre">' . $str . '</pre>');
    
    /* list combined files */
    echo('<h2>Combined files</h2>');
    echo('<ul class="unstyled-list">');
        foreach($listFiles AS $key => $file) {
            echo('<li>' . $file . '</li>');
        }
    echo('</ul>');
    echo('<p>Number of file errors <strong>' . $errorCount . '</strong> st.</p>');
    
    /* the file name defaults */
    $combinedFileName = 'css/combined_styles.css';
    $backupFileName = 'css/backups/backup_styles_' . date("Y-m-d_H-i-s") . '.css';
    
    /* backup the old combined file before updating it */
    copy($combinedFileName, $backupFileName);
    echo('<p>Backup created to file: <strong>' . $backupFileName . '</strong></p>');
    
    /* create update the combined css file */
    file_put_contents($combinedFileName, $str);
    echo('<p>Combined css file: <strong>' . $combinedFileName . '</strong> updated!</p>');
    
    echo('<p><strong>' . $moduleCount . '</strong> files combined.</p>');
    ?>


    Like i said above, i have this in a hidden Template file that i run when logged in as ADMIN. 
    I just refresh the page everytime i made a change and uploaded to the server so the new changes is combined into the big file and can be seen on the website.

    My script assumes the following directory structure:

    1. This is where the script looks for the module files:
    templates -> css -> modules

    2. This is where the script saves the combined big CSS file:
    templates -> css

    3. This is where the script saves a backup of the current big CSS file before creating and writing over the new big file:
    templates -> css -> backups


    You need to go through the script and change the hardcoded paths to suit your needs before use.
    Also please try this out at some test site first so you get the hang of it. Be safe.

    This way of dealing with alot of CSS code has realy made my life much easier.
    Cause if i want to change some modules CSS i just open that file, make the changes, upload the module, and run the script and its compiled in with the other CSS in the big file.

    I am sure you creative fellows on the forums can make refinements to this code, but it has served me well.

    Hope it helps someone.
     

    Hei @EyeDentifythat's cool. It's exactly what I'm looking for. But, I cannot get it working. I didn't understand the admin template part. Could you provide the steps for it? 

×
×
  • Create New...