• Skip to main content
  • Skip to primary sidebar

Ani's Webdev Blog

A learning diary of website development

Blog

[CSS] Simple parallax [Code + Demo]

This code implements a simple parallax section with only CSS, no Javascript needed. The idea is that an image will be set as the background image of a section with fixed position, so that when people scroll down, the image stays fixed. The section should have a width defined.

There is an overlay layer on the image which we can put a darker color on the image. Text is horizontally and vertically centered, written on top of the overlay layer, so it is visible and not affected by the overlay.

The downside of this, as far as I notice, that the background image does not stay fixed on mobile.

Codewith HTML and CSS:

See result in JSFiddle.

[WordPress] Redirect archive 404 pages to blog post page

If you restructure tags and categories of your WordPress website, for example renaming, removing, or deleting, you would have a lot of broken links made by the change. This post shows you how to make a redirect that all 404 archive pages will be forwarded to the blog post page, or a new page that you define.

Here is the code that you can place into the file functions.php of the theme:

add_action('template_redirect', 'archive_to_blog');
function archive_to_blog () {
    global $wp;
       
    $page_url = $wp->request;
    $first_level_url = explode('/', $page_url);
    // Check and exclude url that does not contain tag or category
    if ( $first_level_url[0] !== 'tag' && $first_level_url[0] !== 'category' ) {
       return;
    }
    if ( is_404() ) {
       // Finally, just 301 redirect them into whatever link you want.
       wp_redirect('/blog/', 301);
       exit;
    }
}

It is quite clear what it will do. First, before WordPress checks which template to load (with template_redirect hook), the function archive_to_blog will request the url from the browser address bar.

If it is an archive page, the expected result would be: tag/tagname or category/categoryname.

Then, we extract the returned url with explode(). After that, we check if the first part of the url is are tag or category. If not, returns at once. If they are, then continue checking are they broken links with WordPress built-in function is_404().

The downside of this solution is that it checks every links return, to find if the page is a 404 tag or category page. It is somehow unnecessary in my opinion.

Code refactoring: When and How

There is a saying, “writing is rewriting”. Each time I look at my code several years earlier, I always feel headache and would like to rewrite them, or improve them with what have been learnt so far, so that they are easier to read, to understand and to update.

In general, code refactoring refers to the process of changing bad codes into cleaner, purposeful, human-readable, reusable code in order to be cost effective, easy to maintain and collaborate, and probably a better performance.

Some signs that the code can be refactored

  • Inline comments: Every time there is an inline comment, that means the code is difficult to understand and therefore there is a need to rewrite it so that it becomes meaningful even without the inline comments.
  • Repeated code: Duplicating codes make it difficult to maintain. If there are changes, you have to go and make changes in all the places.
  • Fat functions: Functions that do too many tasks are difficult to maintain.
  • Big decision trees: if or switch with too many different possible branches or too many tasks inside.

What can be done to improve these situations?

  • Naming conventions: names of the functions, variables, classes, interfaces, and namespaces should explain itself. It should tell us what it does or what it represents. This eliminates the need to use inline comments.
  • Returns early in a function, so that the function does not need to get to the last line to stop. If there is a condition that it can stop earlier, just return.
  • Break up into small functions, with each function to be approx. 15 lines of codes and do only one task.
  • Avoid the use of Globals because they are writable which make the code prone to bugs and may produce unexpected behavior. Instead, write an API to fetch the data.
  • Avoid the use of many level nested conditions. Instead, break them up into small functions and returns early. This will also help you to get rid of repeated code.
  • Avoid unnecessary codes, and make it as fewer lines as possible.
  • Separate the files by their intents. Business logic, HTML view, Javascript or CSS should be in separate places because they do different work.

Above all, we should think about the intent of the code, and try to make it less complexity with fewer lines. Easy for us, easy for people who will be after our work.

That’s what I have learnt today by reading the book on KnowTheCode. Although it sounds so clear, it will for sure require a lot of practices everyday to deeply understand and let it be a good habit. I recommend that you also come to the website and grab yourself one PDF of the book. It is only more than 100 pages but practically provides a lot of code examples.

[Bug + Fix] Upload button behaves as a submit button

Lately, I made a project which includes a form to submit information. In the form, there was one Submit button, and another button was Upload. By “button”, I mean the element with markup <button></button>, not the <a> with a .btn class in Bootstrap.

There came a problem: when pressing button Upload, the form submitted itself. This wrong behavior was because I did not assign the button a type. This is how I wrote it:

<button>
    Upload
<button>

According to W3Schools, there are 3 types of buttons: button, submit, and reset. By specifying them, you tell the browser how the button was supposed to behave.

  • button: without a default behavior
  • submit: to submit a form data via the action url
  • reset: to reset form fields to initial values

Without any type specified, the button will behave as a submit button, and that’s why both buttons in my form submits data when clicked.

To fix, the Upload button should be:

<button type="button">
    Upload
<button>

Bottom line: never make a button without type.

[WordPress][ACF] Dynamically populate a select list with values from repeater text fields

Task description

There are two custom fields made with Advanced Custom Fields Pro plugin: Video Tutorials and Video Tutorial Sections.

  • Video Tutorials: has a repeater field that include Video name (Text), Video URL from Youtube (Text), and Video section (Select). This will display under a page called Video Tutorials.
Setting up the Video Tutorials Custom Fields Group
Setting up the Video Tutorials Custom Fields Group
  • Video Tutorial Sections: a repeater of text fields to list the sections. This is assigned to an Options page. If you don’t use Options page, I guess it is good enough to just create a page and assign the values then.

The idea is to add a selection field to the Video Tutorials, which takes in values from the Video Tutorial Sections.

Setting up the Video Tutorials Section Custom Fields Group
Setting up the Video Tutorials Section Custom Fields Group
Creating sections
Creating sections
This section should take values from the Video Tutorials Section Options page
This section should take values from the Video Tutorials Section Options page

I would like to do it so that: first, the page displays a thumbnail image from the Youtube Video, then when people click, the actual video will load. This will make the page load faster than placing a bunch of videos at once. That is also why we need the Video ID instead of the whole URL.

How to populate video sections values into video tutorials choices

First, the ACF documentation has instructions on this topic already. It is the Example 2 from this link which can be taken and modified a bit in this case. Simply saying, we can hook into the “acf/load_field/name=video_single_section” to add the choices from the Video Tutorials Sections.

/**
 * Populate video sections values into video tutorials choices
 */
add_filter( 'acf/load_field/name=video_single_section', 'acf_load_video_sections_choices' );
function acf_load_video_sections_choices ( $field) {
    $field['choices'] = [];
    if( have_rows('video_tutorials_sections', 'option') ) {
        while( have_rows('video_tutorials_sections', 'option') ) {
            the_row();
            $value = get_sub_field('video_tutorials_section_name');
            $field['choices'][ $value ] = $value;
        }
    }
    return $field;
}

Then, come back to the “Video Tutorials” page and reload. You should now see that the selection has successfully takes values from our options page:

Now you can assign the video to the right category
Now you can assign the video to the right category

Notices:

  • When changing the value of any rows in Video Tutorial Section, you have to assign the select field again to the video.

That’s it, quite simple!

ACF issue: First row duplication in nested loops

Let’s talk a bit about how to display the videos on the front-end in sections. We have data already, now it’s time to show it in our Video Tutorials page.

The first solution I think of is to create two nested while loops:

  • The first loop looks for and display the sections
  • The second loop looks for the value of Video Section in each single video, and if the video’s section name is equal to the name of the section from the first loop, the video will be placed under that section.

But, there comes an issue with this solution: always, the first row is duplicated. And the problem is somewhere from the second loop. I don’t know why, and Googling does not help me much. And I find a workaround solution for this duplicate issue:

First, loop through the Video Tutorials Section, store the unique values into an array. Then, create another array to store the Video Tutorials information.

$sections = [];
if(have_rows('video_tutorials_sections', 'option')) :
  while(have_rows('video_tutorials_sections', 'option')) : 
      the_row(); 
      $sections[] = get_sub_field('video_tutorials_section_name', 'option');
  endwhile;
  $sections = array_unique($sections);
endif;
$videos_quick_links = [];
if(have_rows('video_tutorials')) :
  while(have_rows('video_tutorials') ) : 
    the_row();
    $videos = array(
      'name' => get_sub_field('video_tutorials_name'),
      'section' => get_sub_field('video_single_section'),
      'url' => get_sub_field('video_tutorials_url')
    );
    $videos_quick_links[] = $videos;
  endwhile;
endif;

Then, in the body, display the information with a nested foreach loop.

About the thumbnail image: please read this Stackoverflow post. In summary, the link to retrieve the thumbnail is “https://img.youtube.com/vi/<video-id>/0.jpg”

<?php 
$counter_anchor = 1;
foreach ($sections as $section) :
     $anchor_id = create_section_id($section); ?>
     <div class="col-lg-4 not-v-center">
          <a href="#<?php echo $anchor_id; ?>">
              <li>
                  <p>
                      <?php echo $counter_anchor . ". " . $section; ?>
                  </p>
                  <ul>
                  <?php
                  foreach ($videos_quick_links as $video_q) :
                    if($video_q['section'] === $section) : ?>
                        <li class="text-left">
                            <?php echo $video_q['name']; ?>
                        </li?>
                    <?php endif;
                  endforeach;
                  ?>
                  </ul>
              </li>
          </a>
      </div>
<?php
$counter_anchor++;
endforeach; ?>

Embedding Youtube videos are quite annoying, because at the end of the video, it always suggests videos from the other channel. The “&feature=youtu.be&rel=0” at the end of the video url will make sure that it only suggests videos from my channel.

Lastly, I use lity to display the video within the page. There will be video in a lightbox. Download lity style and script file from the link and then enqueue them with wp_enqueue_style and wp_enqueue_scripts in WordPress:

add_action( 'wp_enqueue_scripts', 'blog_add_styles' );
function blog_add_styles() {
    if (is_page_template('video-tutorials.php')) {
         $stylesheet_uri = get_stylesheet_directory_uri();
         wp_enqueue_style( 'lity-css', $stylesheet_uri . '/css/lity.min.css', array(), '0.1' );
         wp_enqueue_script( 'lity-js', $stylesheet_uri . '/js/lity.min.js', true );
    }    
}

And, of course, you can make some CSS to style up the page that it looks better.

Trello boards: Transfering private boards to another account

Transfering Trello boards to another account had caused me some headache recently.

The main thing was, I would like to move all the private boards from company email account into my personal email account.

I had been searching for a while over the Internet with some phrases like “transfer Trello boards to another account“, or “move Trello boards to another email account“, or even “importing Trello boards from JSON file” (because Trello allows exporting the board into CSV or JSON).

Later, I found out that the solutions I got from other people’s answer did not help quite much.

But then there was a very simple solution coming to mind that helped me move my private boards successfully. You don’t even need third-party applications like Zapier or so. And I would like to share with you now.

So follow these simple steps (images below):

  • Go to the Trello board you want to transfer
  • On top of the board, click “Add members“
  • Enter the email of the account you want to transfer the board to and choose from the drop-down list (you already have the new account, right?)
  • Set permissions to the new account to be “Admin“
  • Go to another account to check if you have access to the board from there.
  • Come back to the first account, click on your avatar in the list of members and choose “Leave board“.

That’s it. Really. It did not even take up to 10 minutes. If you have difficulties performing this, check these images below:

add new member to trello board
Add new members to the board you want to transfer.
trello board member change permission
Change permission to the new member to be Admin.
leave trello board
Leave the board you don’t want to access from.
  • « Go to Previous Page
  • Go to page 1
  • Interim pages omitted …
  • Go to page 3
  • Go to page 4
  • Go to page 5
  • Go to page 6
  • Go to page 7
  • Go to Next Page »

Primary Sidebar

Hi! I am a Vietnamese coder living in Oulu, Finland. Currently I am working with PHP, MySQL, HTML, CSS, and JavaScript. This blog is my learning diary, in which I share knowledge from my own experience or research. Hopefully you can find something useful here and don’t hesitate to open a discussion or leave a feedback!

My Blog

A learning diary
#wordpress #javascript #php #vue #css

Highlights

  • [WordPress] 5 Ways to Migrate Sites
  • [WordPress] Customizing Themes: Basic Principles & Examples
  • reCaptcha v3: How to implement on WordPress custom forms to stop bot signups
  • [WordPress] How to make the functions.php less messy
  • [CSS] Simple parallax [Code + Demo]

Latest

  • WordPress + Gumlet + S3: Resizing images from server side and upload to S3
  • [WordPress] Using Child Themes
  • [WordPress] Using Code Snippets to Modify Themes Without Child Theme
  • [WordPress] Let’s Make Plugin E01: A Simple View Count Plugin
  • [WordPress] Create custom post type programmatically
Anh Karppinen, personal web, version 1.0.0
  • Privacy Policy