B

2021

WordPress Development

Website Refresh | WordPress Development
Client: Farsiight
URL: farsiight.com

Designs: Farsiight
Web Development: Bartosz

This website combines Gutenberg blocks with custom PHP/JS to deliver a balance of fast loading with ease of content editing.

Farsiight
Desktop view for Farsiight
Farsiight
Mobile view of Farsiight
Farsiight
Custom Mobile Menu for Farsiight
Farsiight
Desktop View of Farsiight Landing Pages – Modified for a standalone experience used in SEM campaigns
// Excerpt from Farsiight plugin 

// Add Arrow Icons to Mobile Menu
function menu_arrow($item_output, $item, $depth, $args) {

 	if('5' == $args->menu) {
		if (in_array('menu-item-has-children', $item->classes)) {
        $arrow = '<button title="View More" class="arrow"><img loading="lazy" width="8" height="16" src="https://farsiight.com/wp-content/uploads/2020/11/arrow.svg" alt="Toggle Arrow" title="Toggle More"></button>'; // Change the class to your font icon
        $item_output = str_replace('</a>', '</a>'. $arrow .'', $item_output);
    	}
	}
	if('3' == $args->menu) {
		if (in_array('menu-item-has-children', $item->classes)) {
        $arrow = '<button title="View More" class="arrow"><img loading="lazy" width="8" height="16" src="https://farsiight.com/wp-content/uploads/2021/01/arr.svg" alt="Toggle Arrow" title="Toggle More"></button>'; // Change the class to your font icon
        $item_output = str_replace('</a>', '</a>'. $arrow .'', $item_output);
    	}
	}
    return $item_output;
}
add_filter('walker_nav_menu_start_el', 'menu_arrow', 10, 4);


// WP Walker to add classes specific to menu list properties - main vs sub-item

class CSS_Menu_Maker_Walker extends Walker {

  var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );

  function start_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n$indent<ul>\n";
  }

  function end_lvl( &$output, $depth = 0, $args = array() ) {
    $indent = str_repeat("\t", $depth);
    $output .= "$indent</ul>\n";
  }

  function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

    global $wp_query;
    $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
    $class_names = $value = '';        
    $classes = empty( $item->classes ) ? array() : (array) $item->classes;

    // Add active class
    if(in_array('current-menu-item', $classes)) {
      $classes[] = 'active';
      unset($classes['current-menu-item']);
    }

    // Check for children
    $children = get_posts(array('post_type' => 'nav_menu_item', 'nopaging' => true, 'numberposts' => 1, 'meta_key' => '_menu_item_menu_item_parent', 'meta_value' => $item->ID));
    if (!empty($children)) {
      $classes[] = 'has-sub';
    }

    $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
    $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

    $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
    $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

    $output .= $indent . '<li' . $id . $value . $class_names .'>';

    $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
    $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
    $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
    $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

    $item_output = $args->before;
    $item_output .= '<a'. $attributes .'><span>';
    $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
    $item_output .= '</span></a>';
    $item_output .= $args->after;

    $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
  }

  function end_el( &$output, $item, $depth = 0, $args = array() ) {
    $output .= "</li>\n";
  }
}

// Navigation Menu Widget
add_shortcode('footerwidget_menu','footerwidget_menu');
function footerwidget_menu($atts,$content){
 
    $atts = shortcode_atts( array(
        'menu_class' => 'menu',
        'menu' => '',
        'container' => 'div',
        'container_class' => '',
        'echo' => false
    ), $atts );
	
	$content = wp_nav_menu(
			array(                
				'menu' => sanitize_text_field($atts['menu']),
				'menu_class' => sanitize_text_field($atts['menu_class']),
				'container'  => sanitize_text_field($atts['container']),
				'container_class' => sanitize_text_field($atts['container_class']),
				'echo' => false,
				'walker' => new CSS_Menu_Maker_Walker()
			)
		);

	return $content;
	
}

// Descriptions added to Mobile Menu 

add_filter( 'walker_nav_menu_start_el', 'tu_menu_item_description', 10, 4 );
function tu_menu_item_description( $item_output, $item, $depth, $args ) 
{
	
	if ( '3' == $args->menu ) {
	// if ( 'slideout' == $args->theme_location ) {
		$item_output = str_replace( $args->link_after . '</a>', $args->link_after . '</span><span class="description">' . $item->description . '</span></a>', $item_output );
	}
	
	// Return the output
	return $item_output;
}

Highlights

Performance was a key factor for this WordPress development. GeneratePress Premium provides a lightweight minimalist theme allowing for custom development and extending WP and Gutenberg. This complete development included extensive CSS for high quality responsive design, optimisation of hosting and WordPress elements for Page Speed and ongoing development for standalone landing pages.

Custom PHP, JS, CSS Theme Development

Dynamic WP menus with WP Walker Class for custom displays

‘App style’ mobile menus

Video Popups for YouTube (with no titles, meta-info)

Landing Pages with different headers / footer

Custom forms (multi-step CF7 forms, Slack API integration)

// PHP Hook for Video Popups + YouTube embed (no title, labels or controls).

//  JQuery iframe wrapper for video
<script type="text/javascript">
jQuery('#play-video').on('click', function(e){
  e.preventDefault();
  jQuery('#video-overlay').addClass('open');
  jQuery("#video-overlay").append('<div class="iframewrapper"><div class="iframe-icontainer"><iframe src="https://www.youtube.com/embed/MEguZuHWnws?rel=0&autoplay=1&autohide=1&showinfo=0&controls=0" width="853" height="505" frameborder="0" allow="accelerometer; autoplay;" allowfullscreen></iframe></div></div>');
});
jQuery('.video-overlay, .video-overlay-close').on('click', function(e){
  e.preventDefault();
  close_video();
});

jQuery(document).keyup(function(e){
  if(e.keyCode === 27) { close_video(); }
});

function close_video() {
  jQuery('.video-overlay.open').removeClass('open').find('.iframewrapper').remove().find('iframe').remove();
};
</script>

// HTML for Video Container
<div id="video-overlay" class="video-overlay">
  <a class="video-overlay-close">×</a>
</div>


// CSS for Play button
<style>
.video-play-button {
  position: absolute;
  z-index: 10;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
  -webkit-transform: translateX(-50%) translateY(-50%);
  box-sizing: content-box;
  display: block;
  width: 52px;
  height: 72px;
  border-radius: 50%;
  padding: 18px 20px 18px 28px;
}

.video-play-button:before {
  content: "";
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
  -webkit-transform: translateX(-50%) translateY(-50%);
  display: block;
  background: #0CB4CE;
  border-radius: 50%;
  animation: pulse-border 1500ms ease-out infinite;
}

.video-play-button:after {
  content: "";
  position: absolute;
  z-index: 1;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%);
  -webkit-transform: translateX(-50%) translateY(-50%);
  display: block;
  background: #0CB4CECC;
  border-radius: 50%;
  transition: all 200ms;
}

.video-play-button:hover:after {
  background-color: darken(#0CB4CE, 10%);
}

.video-play-button img {
  position: relative;
  z-index: 3;
  max-width: 100%;
  width: auto;
  height: auto;
}

.video-play-button span {
  display: block;
  position: relative;
  z-index: 99;
  width: 0;
  height: 0;
}

@keyframes pulse-border {
  0% {
    transform: translateX(-50%) translateY(-50%) translateZ(0) scale(1);
    opacity: 1;
  }
  100% {
    transform: translateX(-50%) translateY(-50%) translateZ(0) scale(1.5);
    opacity: 0;
  }
}

.video-overlay {
  position: fixed;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0,0,0,0.5);
  opacity: 0;
  transition: all ease 500ms;
}

.video-overlay.open {
  position: fixed;
  z-index: 1050;
  opacity: 1;
}

.video-overlay-close {
    position: absolute;
    z-index: 1051;
    top: 8px;
    line-height: 1;
    font-weight: 400;
    color: #fff;
    text-decoration: none;
    cursor: pointer;
    transition: all 200ms;
    font-size: 65px;
    margin-top: 0px;
    right: 15px;
    filter: drop-shadow(3px 3px 30px rgb(0, 11, 27));
}

.video-overlay-close:hover {
  color: #0CB4CE;
}
    
// CSS Responsive Adjustments

.cs-indv-c {
    position: absolute;
}
@media (max-width:425px) {
    .cs-indv-c {
        top: 100px;
        right: 50%;
    }
}
@media (min-width:426px) and (max-width:599px) {
    .cs-indv-c {
        top: 140px;
        right: 50%;
    }
}
@media (max-width:599px) {
    .video-play-button span {
        border-left: 29px solid #fff;
        border-top: 17px solid transparent;
        border-bottom: 17px solid transparent;
        margin-left: 12px;
        margin-top: 18px;
    }
    .video-play-button:before, .video-play-button:after {
        width: 67px;
        height: 67px;
    }
    .video-overlay iframe {  
        /*position: absolute;
        top: 50%;
        left: 50%;
        transform: translateX(-50%) translateY(-50%);*/
        /* width: 90%; */
        /* height: auto; */
        /* box-shadow: 0 0 15px rgba(0,0,0,0.75); */
        position: absolute; 
        top: 0; 
        left: 0; 
        width: 100%; 
        height: 100%;
    }
     .iframewrapper {
        overflow: hidden;
        max-width: 95%;
        margin-left: 2.5%;        
        margin-top: 15vh;
    }
    .iframe-icontainer {
            position: relative;
            padding-bottom: 56.25%; /* 16:9 */  
            padding-top: 0px;
            width: 300%; /* enlarge beyond browser width */
            left: -100%; /* center */
    }

}       
@media (min-width:600px) and (max-width:1024px) {
    .cs-indv-c {
        top: 190px;
        right: 50%;
    }
    .video-play-button span {
        border-left: 61px solid #fff;
        border-top: 36px solid transparent;
        border-bottom: 36px solid transparent;
    }
    .video-play-button:before, .video-play-button:after {
        width: 144px;
        height: 144px;
    }   
    .video-overlay iframe {  
         position: absolute; 
        top: 0; 
        left: 0; 
        width: 100%; 
        height: 100%;
    }
    .iframewrapper {
         overflow: hidden;
        max-width: 75%;
        margin-left: auto;
        margin-right: auto;        
        margin-top: 15vh;
    }
    // CSS Trick to hide YouTube title and info
    .iframe-icontainer {
            position: relative;
            padding-bottom: 56.25%; /* 16:9 */  
            padding-top: 0px;
            width: 300%; /* enlarge beyond browser width */
            left: -100%; /* center */
    }
}   
@media (min-width:1025px) {
    .cs-indv-c {
        top: 170px;
        right: 23%;
    }
    .video-play-button span {
        border-left: 61px solid #fff;
        border-top: 36px solid transparent;
        border-bottom: 36px solid transparent;
    }
    .video-play-button:before, .video-play-button:after {
        width: 144px;
        height: 144px;
    }
    
    .video-overlay iframe {  
         position: absolute; 
        top: 0; 
        left: 0; 
        width: 100%; 
        height: 100%;
    }
    .iframewrapper {
         overflow: hidden;
        max-width: 75%;
        margin-left: auto;
        margin-right: auto;
        margin-top: 15vh;
    }
    .iframe-icontainer {
            position: relative;
            padding-bottom: 56.25%; /* 16:9 */  
            padding-top: 0px;
            width: 300%; /* enlarge beyond browser width */
            left: -100%; /* center */
    }  
}   
#content .pointy a, #content .pointy { cursor: pointer !important; }
</style>