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.
// 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>