YouTube No-Cookie URL
https://www.youtube-nocookie.com/embed/aqz-KE-bpKQ
Custom Domain for WordPress Pages
If you want to use a domain for a WordPress page, add the following snippet to your .htaccess
before the WordPress section.
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} domain\.com$ [NC]
RewriteRule ^(.*)$ index.php?page_id=1879 [NC,QSA,L]
# BEGIN WordPress
...
Change Field Name in Advanced Custom Fields
You have created a field in Advanced Custom Fields Plugin and have already saved data in it. You want to rename the field and your data is no longer visible in the backend? No problem. Log into PHPMyAdmin and run the following commands.
UPDATE wp_termmeta SET meta_key = 'new_key' WHERE meta_key = 'old_key'
Detect a WordPress Development Environment
if ('Development/Name' === $_SERVER['WP_CONTEXT']) {
// Development
} else {
// Production
}
To set the environment variable add this to your .htaccess
file
Options Indexes FollowSymLinks
SetEnv WP_CONTEXT Development/Name
No Post in Elementor Posts Widget
Add this snippet to your functions.php
to show a message if no posts found in Elementor Posts Widget.
add_action('elementor/query/query_results', function ($query) {
if (0 === $query->found_posts) {
_e('No posts found.', 'domain');
}
});
Delete Media Files from WordPress Database
DELETE FROM wp_posts WHERE post_type = 'attachment';
DELETE FROM wp_postmeta WHERE meta_key = '_wp_attached_file';
DELETE FROM wp_postmeta WHERE meta_key = '_wp_attachment_metadata';
Defer Loading Background Images
Add this to your <head> section...
<style id="defer-style">
.selector {
background-image: none !important;
}
</style>
...and this before </body> tag...
<script>
document.addEventListener('DOMContentLoaded', function () {
var deferStyle = document.getElementById('defer-style');
if (null !== deferStyle) {
deferStyle.parentElement.removeChild(deferStyle);
}
});
</script>
Preload Fonts for Google PageSpeed Insights
<link rel="preload" href="/path/font.woff2" as="font" type="font/woff2" crossorigin>
Javascript Browser Check
Google Chrome
window.navigator.userAgent.indexOf('Chrome') > -1
Microsoft Internet Explorer
window.navigator.userAgent.indexOf('MSIE') > -1 || !!navigator.userAgent.match(/Trident.*rv\:11\./)
Microsoft Edge
window.navigator.userAgent.indexOf('Edge') > -1
Safari
window.navigator.userAgent.indexOf('Safari') > -1 && window.navigator.userAgent.indexOf('Chrome') == -1
Mozilla Firefox
window.navigator.userAgent.indexOf('Firefox') > -1
Chromium Edge
window.navigator.userAgent.indexOf('Edg/') > -1
Redirect all URLs to another Domain
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ https://www.domain.com/$1 [R=302,L]
</IfModule>
Show Future Posts in Frontend
add_action('pre_get_posts', function ($query) {
if (false === is_user_logged_in() && $query->is_main_query() && $query->is_single()) {
$query->set('post_status', [
'publish',
'future'
]);
}
});
Disable WordPress Updates
Add this to your wp-config.php
define('WP_AUTO_UPDATE_CORE', false);
Remove Google Fonts from Elementor completely
add_action('wp_print_styles', function () {
wp_dequeue_style('google-fonts-1');
});
Fix Autoscroll on Elementor
If you use a sticky header with anchor links, there is one problem since Elementor 3.0 was released. Everything is fine, if you have a single one page layout. But when you have subpages and use your anchor links also in the main navigation, then you will have some trouble.
You're on a subpage and want to jump to an anchor link on another page. You scroll automatically to the anchor, but now the sticky header is placed over it.
Copy and paste the following snippet and the problem will solved.
add_action('wp_footer', function () {
?>
<script>
var hash = window.location.hash.replace('#', '');
var scrollToElement = document.getElementById(hash);
var header = document.querySelector('[data-elementor-type="header"]');
var headerHeight = header.offsetHeight;
if (null !== scrollToElement) {
var style = document.createElement('style');
style.innerText = '#' + hash + ':before { content: ""; display:block; height: ' + headerHeight + 'px; margin: ' + (-1 * headerHeight) + 'px 0 0; visibility: hidden; pointer-events: none; }';
document.head.appendChild(style);
document.addEventListener('DOMContentLoaded', function() {
setTimeout(function () {
document.head.removeChild(style);
}, 1000);
});
}
</script>
<?php
}, 1);
Overwrite Stylesheets in WordPress
Use these methods to overwrite existing stylesheets and you no longer have to use !important for your sections.
Header Scripts
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style('new', 'css/new.css', ['old'], false);
}, 99);
Footer Scripts
add_action('get_footer', function () {
wp_enqueue_style('new', 'css/new.css', ['old'], false);
}, 99);
Ultimate WordPress .htaccess File
The ultimate .htaccess of WordPress looks like this one.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
# BEGIN SSL Forwarding
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
# END SSL Forwarding
# BEGIN CORS Security
<IfModule mod_headers.c>
<FilesMatch "\.(ttf|ttc|otf|eot|woff|woff2|font.css|css|js|gif|png|jpe?g|svg|svgz|ico|webp)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
</IfModule>
# END CORS Security
# BEGIN Browser Caching
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
# CSS
ExpiresByType text/css "access plus 1 year"
# Data
ExpiresByType application/atom+xml "access plus 1 hour"
ExpiresByType application/rdf+xml "access plus 1 hour"
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/ld+json "access plus 0 seconds"
ExpiresByType application/schema+json "access plus 0 seconds"
ExpiresByType application/vnd.geo+json "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
# Favicon (cannot be renamed!) and cursor images
ExpiresByType image/vnd.microsoft.icon "access plus 1 week"
ExpiresByType image/x-icon "access plus 1 week"
# HTML
ExpiresByType text/html "access plus 0 seconds"
# JavaScript
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
# Manifest files
ExpiresByType application/manifest+json "access plus 1 week"
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Media files
ExpiresByType audio/ogg "access plus 1 year"
ExpiresByType image/bmp "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/ogg "access plus 1 year"
ExpiresByType video/webm "access plus 1 year"
# Web Fonts
# Embedded OpenType (EOT)
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType font/eot "access plus 1 year"
# OpenType
ExpiresByType font/opentype "access plus 1 year"
# TrueType
ExpiresByType application/x-font-ttf "access plus 1 year"
# Web Open Font Format (WOFF) 1.0
ExpiresByType application/font-woff "access plus 1 year"
ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
# Web Open Font Format (WOFF) 2.0
ExpiresByType application/font-woff2 "access plus 1 year"
# Other
ExpiresByType text/x-cross-domain-policy "access plus 1 week"
</IfModule>
# END Browser Caching
# BEGIN Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/vtt
AddOutputFilterByType DEFLATE text/x-component
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/js
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/atom+xml
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/ld+json
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/font-woff2
AddOutputFilterByType DEFLATE application/x-font-woff
AddOutputFilterByType DEFLATE application/x-web-app-manifest+json font/woff
AddOutputFilterByType DEFLATE font/woff
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
# Exception: Images
SetEnvIfNoCase REQUEST_URI \.(?:gif|jpg|jpeg|png|svg)$ no-gzip dont-vary
# Drop problematic browsers
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary
</IfModule>
# END Compression
# BEGIN Caching on Apache
<IfModule mod_headers.c>
<FilesMatch "\.(ico|pdf|flv|swf|js|css|gif|png|jpg|jpeg|txt|woff2|woff)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(js|css|xml|gz)$">
Header append Vary Accept-Encoding
</FilesMatch>
</IfModule>
# END Caching on Apache
# BEGIN Keep-Alive Header
<IfModule mod_headers.c>
Header set Connection keep-alive
</IfModule>
# END Keep-Alive Header
# BEGIN Disable ETags
<IfModule mod_expires.c>
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
</IfModule>
<IfModule mod_headers.c>
<FilesMatch ".(js|css|xml|gz|html|woff|woff2|ttf)$">
Header append Vary: Accept-Encoding
</FilesMatch>
</IfModule>
# END Disable ETags
# BEIGN Protection
<Files install.php>
Order allow,deny
Deny from all
</Files>
<Files wp-config.php>
Order allow,deny
Deny from all
</Files>
<Files readme.html>
Order allow,deny
Deny from all
Satisfy all
</Files>
<Files liesmich.html>
Order allow,deny
Deny from all
Satisfy all
</Files>
<Files error_log>
Order allow,deny
Deny from all
</Files>
<FilesMatch "(\.htaccess|\.htpasswd)">
Order deny,allow
Deny from all
</FilesMatch>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>
<Files xmlrpc.php>
Order deny,allow
Deny from all
</Files>
# END Protection
Optional Snippets
# BEGIN No-Referrer Header
<IfModule mod_headers.c>
Header set Referrer-Policy "no-referrer"
</IfModule>
# END No-Referrer Header
# BEGIN X-Frame-Options Header
<IfModule mod_headers.c>
Header set X-Frame-Options "sameorigin"
</IfModule>
# END X-Frame-Options Header
# BEGIN X-XSS-Protection Header
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
</IfModule>
# END X-XSS-Protection Header
# BEGIN X-Content-Type-Options Header
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
</IfModule>
# END X-Content-Type-Options Header
# BEGIN Strict-Transport-Security Header
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule>
# END Strict-Transport-Security Header
Zoom-In Animation… One by One
Ok, put that Javascript snippet on your site.
$(window).on('scroll', function () {
var scrollPosition = $(window).scrollTop() + $(window).height();
var timeout = 100;
$('.ws-post').each(function () {
var element = $(this);
var elementPosition = element.offset().top;
if (false === element.hasClass('ws-post--ready') && scrollPosition >= elementPosition) {
setTimeout(function () {
element.addClass('ws-post--ready');
}, timeout += 100);
}
});
});
The code above will add a class on your elements, if the user scroll down on your site and the element is in the viewport.
Don't forget to style the elements, to make the effect more fancy.
.ws-post {
transform: scale(0);
-webkit-transform: scale(0);
visibility: hidden;
opacity: 0;
transition: transform 100ms cubic-bezier(0, 0, 1, 1), visibility 0ms linear, opacity 100ms cubic-bezier(0, 0, 1, 1);
-webkit-transition: transform 100ms cubic-bezier(0, 0, 1, 1), visibility 0ms linear, opacity 100ms cubic-bezier(0, 0, 1, 1);
}
.ws-post.ws-post--ready {
transform: scale(1);
-webkit-transform: scale(1);
visibility: visible;
opacity: 1;
}
Human Readability Time Function
You need a function to publish your date like "1 hour ago", "3 days ago" or something like that? No problem. Here is my way to do that.
function ws_format_time($datetime, $full = false)
{
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$diff = (array) $diff;
$string = [
'y' => 'year',
'm' => 'month',
'w' => 'week',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
foreach ($string as $key => $value) {
if ($diff[$key]) {
$prefix = 's';
$string[$key] = $diff[$key] . ' ' . $value . ($diff[$key] > 1 ? $prefix : '');
} else {
unset($string[$key]);
}
}
if (!$full) {
$string = array_slice($string, 0, 1);
}
return $string ? implode(', ', $string) . ' ago' : 'just now';
}
Elementor Font Awesome 5 Pro Support (Self-Hosted)
Actually, this variant is already obsolete, if not already deprecated. However, I use this method in some projects. If e.g. Font Awesome 5 Pro has already been purchased and there is no access to the CDN. With the integration of the u.g. Code snippets in the functions.php
, there is still the possibility to use the premium icons in Elementor.
In Elementor, the Font Awesome 5 CDN can only be used with the license key.
function enqueue_icon_font() {
wp_enqueue_style('font-awesome-5', 'https://use.fontawesome.com/releases/v5.1.0/css/all.css');
}
add_action('wp_enqueue_scripts', 'enqueue_icon_font', 1);
add_action('elementor/editor/before_enqueue_styles', 'enqueue_icon_font', 1);
add_action('elementor/controls/controls_registered', function ($controls_registry) {
$icons = $controls_registry->get_control('icon')->get_settings('options');
$new_icons = array_merge(
array(
'fab fa-elementor' => 'elementor',
),
$icons
);
$controls_registry->get_control('icon')->set_settings('options', $new_icons);
}, 10, 1);
CSS Flip Animation
Here is a little flip animation that I like to use in dropdowns at my navigations.
selector {
animation: ws-flip-rotation 500ms ease-in-out forwards;
-webkit-animation: ws-flip-rotation 500ms ease-in-out forwards;
}
@keyframes ws-flip-rotation {
0% {
opacity: 0;
transform: translateY(45px) rotate3d(1, 1, 0, 45deg);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@-webkit-keyframes ws-flip-rotation {
0% {
opacity: 0;
-webkit-transform: translateY(45px) rotate3d(1, 1, 0, 45deg);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
}
}
CSS Hamburger Menu
A really nice Hamburg menu button. Simple and yet so brilliant.
First the basic framework with HTML:
<button class="ws-navigation__button">
<span class="ws-navigation__hamburger">
<span class="ws-navigation__button-line"></span>
<span class="ws-navigation__button-line"></span>
<span class="ws-navigation__button-line"></span>
</span>
<span class="ws-navigation__cross">
<span class="ws-navigation__button-line"></span>
<span class="ws-navigation__button-line"></span>
</span>
</button>
… and then a little bit of CSS:
<style>
selector {
z-index: 99;
}
.ws-navigation__button {
display: block;
width: 40px;
height: 40px;
position: relative;
border: none;
padding: 0;
background: none;
cursor: pointer;
}
.ws-navigation__hamburger,
.ws-navigation__cross {
display: block;
width: 60%;
height: 60%;
position: absolute;
top: 20%;
left: 20%;
}
.ws-navigation__button-line {
display: block;
width: 100%;
height: 2px;
position: absolute;
background-color: #000;
}
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(2) {
width: 75%;
}
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(1),
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(2),
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(3) {
right: 0;
transform: translateY(-50%);
-webkit-transform: translateY(-50%);
transition: width 0.15s ease-in-out;
-webkit-transition: width 0.15s ease-in-out;
}
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(1) {
top: calc(50% - 4px);
transition-delay: 0.4s;
-webkit-transition-delay: 0.4s;
}
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(2) {
top: 50%;
transition-delay: 0.5s;
-webkit-transition-delay: 0.5s;
}
.ws-navigation__hamburger .ws-navigation__button-line:nth-child(3) {
top: calc(50% + 4px);
transition-delay: 0.6s;
-webkit-transition-delay: 0.6s;
}
.ws-navigation__button--clicked .ws-navigation__hamburger .ws-navigation__button-line {
width: 0;
}
.ws-navigation__button--clicked .ws-navigation__hamburger .ws-navigation__button-line:nth-child(1) {
transition-delay: 0.1s;
-webkit-transition-delay: 0.1s;
}
.ws-navigation__button--clicked .ws-navigation__hamburger .ws-navigation__button-line:nth-child(2) {
transition-delay: 0.2s;
-webkit-transition-delay: 0.2s;
}
.ws-navigation__button--clicked .ws-navigation__hamburger .ws-navigation__button-line:nth-child(3) {
transition-delay: 0.3s;
-webkit-transition-delay: 0.3s;
}
.ws-navigation__cross {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
.ws-navigation__cross .ws-navigation__button-line:nth-child(1) {
width: 0;
top: 50%;
left: 0;
transform: translateY(-50%);
-webkit-transform: translateY(-50%);
transition: width 0.15s ease-in-out;
-webkit-transition: width 0.15s ease-in-out;
transition-delay: 0.1s;
-webkit-transition-delay: 0.1s;
}
.ws-navigation__cross .ws-navigation__button-line:nth-child(2) {
width: 2px;
height: 0;
top: 0;
left: 50%;
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
transition: height 0.15s ease-in-out;
-webkit-transition: height 0.15s ease-in-out;
transition-delay: 0.2s;
-webkit-transition-delay: 0.2s;
}
.ws-navigation__button--clicked .ws-navigation__cross .ws-navigation__button-line:nth-child(1) {
width: 100%;
transition-delay: 0.5s;
-webkit-transition-delay: 0.5s;
}
.ws-navigation__button--clicked .ws-navigation__cross .ws-navigation__button-line:nth-child(2) {
height: 100%;
transition-delay: 0.6s;
-webkit-transition-delay: 0.6s;
}
</style>
Now we can simply swap classes with the OnClick event via jQuery and marvel at the magic. Mmh, yummi. 🙂
WordPress Rest API
First we need to add the following code to our functions.php
.
add_action('rest_api_init', function () {
register_rest_route('namespace', '/path', [
'methods' => 'GET',
'callback' => function () {
return $_GET;
}
]);
});
Then we can create a simple form and process the request via Javascript.
$('form').on('submit', function (e) {
e.preventDefault();
$.ajax({
type: 'GET',
url: '/wp-json/namespace/path',
data: $('form').serialize()
}).done(function (response) {
console.log(response);
});
});
Alternatively, you can also call the following URL directly in the browser:
https://www.domain.com/wp-json/namespace/path?parameter=value
Custom Cursor with CSS
Sometimes a simple mouse pointer (cursor) is not enough. Then something of your own has to be found. Replacing the cursors with another graphic is in many cases insufficient or leads to compatibility problems in other browsers. We need something better!
First of all we need some HTML code:
<div class="cursor">
<div class="cursor-pointer"></div>
<div class="cursor-effect"></div>
</div>
Then we give the elements their essential attributes and design them according to our ideas:
.cursor--ready,
.cursor--ready *,
.cursor--ready *:hover {
cursor: none;
}
.cursor {
display: block;
box-sizing: border-box;
-webkit-box-sizing: border-box;
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 99999;
pointer-events: none;
}
.cursor-pointer {
position: absolute;
top: -100%;
left: -100%;
}
.cursor-pointer:before {
content: '';
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
width: 4px;
height: 4px;
border-radius: 100%;
background-color: #a3ff12;
opacity: 1;
transition: all 256ms ease;
-webkit-transition: all 265ms ease;
}
.cursor--active .cursor-pointer:before {
width: 16px;
height: 16px;
box-shadow: 0 0 16px #a3ff12;
opacity: 0.64;
}
.cursor-effect {
position: absolute;
top: -100%;
left: -100%;
transition: top 100ms ease, left 100ms ease;
-webkit-transition: top 100ms ease, left 100ms ease;
}
.cursor-effect:before {
content: '';
display: block;
width: 24px;
height: 24px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
border: 1px solid rgba(163, 255, 18, 0.48);
border-radius: 100%;
opacity: 1;
transition: all 256ms ease;
-webkit-transition: all 256ms ease;
}
.cursor--active .cursor-effect:before {
width: 0;
height: 0;
opacity: 0;
}
@media (max-width: 768px) {
.cursor {
display: none;
}
}
So that everything works properly, a little bit of Javascript is missing at the end:
(function($) {
var cursorPointer = $('.cursor-pointer');
var cursorEffect = $('.cursor-effect');
var cursorEffectOffsetTop = (cursorEffect.height() / 2) - (cursorPointer.height() / 2);
var cursorEffectOffsetLeft = (cursorEffect.width() / 2) - (cursorPointer.width() / 2);
$('body').addClass('cursor--ready');
$(document).on('mousemove', function (e) {
cursorPointer.css({
'top': e.pageY + 'px',
'left': e.pageX + 'px'
});
cursorEffect.css({
'top': (e.pageY - cursorEffectOffsetTop) + 'px',
'left': (e.pageX - cursorEffectOffsetLeft) + 'px'
});
});
$(document).on('mouseenter', 'a, label, input, button', function () {
$('.cursor').addClass('cursor--active');
});
$(document).on('mouseleave', 'a, label, input, button', function () {
$('.cursor').removeClass('cursor--active');
});
})(jQuery);
Force WWW Redirect with SSL
If the domain is called without SSL (i.e. "https: //") or no "www." before that, the forwarding takes place to an SSL domain with WWW.
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(.*)$ [NC]
RewriteRule (.*) https://www.%1/$1 [R=302,L]
Popup with Cookie Timeout
We need a popup. After it has been closed, it should no longer be displayed for the next hour. So the problem could be solved relatively easily.
$(function () {
var now = new Date();
var myCookies = {};
var browserCookies = document.cookie.split('; ');
for (var i = 0; i < browserCookies.length; i++) {
var cookieChunks = browserCookies[i].split('=');
myCookies[cookieChunks[0]] = cookieChunks[1];
}
var cookieTimeout = (now.getHours() + 1) + '' + now.getMinutes();
if ('undefined' !== myCookies['WS_POPUP_CLOSED'] && cookieTimeout >= myCookies['WS_POPUP_CLOSED']) {
return;
}
setTimeout(function () {
$('.ws-popup').addClass('ws-popup--visible');
}, 1000);
$('.ws-popup__button-close').on('click', function () {
document.cookie = 'WS_POPUP_CLOSED=' + now.getHours() + '' + now.getMinutes() + ';';
$('.ws-popup').removeClass('ws-popup--visible');
});
});
Export Construct 2 Project as Android APK
In order to export a project from Construct 2 as an APK under Windows, the following steps are necessary.
- First we have to (if not already available) Android Studio, NodeJS and the Java SE Runtime Environment to install.
- After the installation we open the command line CMD, change to our hard drive "C: \" and execute the following command:
npm install -g cordova
- Then we create a new project with the following command:
cordova create demo com.wossi.demo demo
The word demo is of course my project name here. - Now we switch to our new directory with
cd demo
and execute the following command:cordova platform add android
- Then we open Android Studio and select the menu item "Import Project (Gradle, Eclipse, ADT, etc.)"
- Then we choose the point
android
in our project directoryC:/demo/platforms/android
and confirm our selection with OK. The following message is also simply confirmed with OK. - In the emulator we can now check whether Cordova is running.
- We are now switching to the Construct 2 application and exporting our project with Cordova. In the exported project folder, we now copy the entire content of the
www
folder and paste it into Android Studio underapp/assets/www
.
We overwrite all existing files! - Now we can test our app again using the emulator, change the app icon under
app/res/mipmap/ic_launcher/ic_launcher.png
or make further settings inapp/manifests/AndroidManifest.xml
. If necessary, we can also activate the full-screen mode inapp/res/xml/config.xml
- Finally, we export the APK to Android Studio at
Build > Build Bundle(s) / APK(s) > Build APK(s)
. The unsigned APK can then be found atC:/demo/platforms/android/app/build/outputs/apk/debug/app-debug.apk
Cordova Fullscreen App in Android Studio
I have just generated my first APK for Android and now I want to use my app in full screen mode. However, I have the problem that I cannot hide the navigation bar of the device.
The solution is relatively simple. A small adjustment in app/res/xml/config.xml
should solve the problem. Just add the following code.
<preference name="Fullscreen" value="true" />
In addition, I use the following line in my app/manifests/AndroidManifest.xml
:
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
Allow WordPress Editors to edit Menus
It often happens that customers want to do their own thing in the dashboard (or backend) of WordPress. In the course of this, it may be necessary to enable the editor to edit menus. All you have to do is add the following lines to your functions.php
.
$role_object = get_role('editor');
$role_object->add_cap('edit_theme_options');
Get WordPress Menu Items as Array
That is my solution! 😉
function getNavigationItemsArray(array $menuItems)
{
$navigationItems = [];
$parentPackages = [];
foreach ($menuItems as $menuItem) {
if ($menuItem->menu_item_parent == 0) {
continue;
}
if (!isset($parentPackages[$menuItem->menu_item_parent])) {
$parentPackages[$menuItem->menu_item_parent] = [$menuItem];
} else {
$parentPackages[$menuItem->menu_item_parent][] = $menuItem;
}
}
foreach ($menuItems as $menuItem) {
if (isset($parentPackages[$menuItem->ID])) {
$menuItem->children = $parentPackages[$menuItem->ID];
} else {
$menuItem->children = [];
}
if ($menuItem->menu_item_parent == 0) {
$navigationItems[] = $menuItem;
}
}
return $navigationItems;
}
Rename WordPress Database after Domain Transfer
It happens that you have to transfer a WordPress project into the live environment after development. After the move you are faced with the problem that the old URL is still in the database. The project is therefore not accessible via the new domain. However, it is relatively easy to replace the old domain with the new domain. To do this, you have to execute the following SQL commands in PHPMyAdmin.
UPDATE wp_options SET option_value = replace(option_value, 'http://www.old.com', 'http://www.new.com') WHERE option_name = 'home' OR option_name = 'siteurl';
UPDATE wp_posts SET guid = replace(guid, 'http://www.old.com', 'http://www.new.com');
UPDATE wp_posts SET post_content = replace(post_content, 'http://www.old.com', 'http://www.new.com');
UPDATE wp_postmeta SET meta_value = replace(meta_value, 'http://www.old.com', 'http://www.new.com');
The names of the tables should of course be adjusted accordingly.
Use ACF fields in Yoast SEO as template variable
If you want to use the content of a user-defined field of the ACF plugin (Advanced Custom Fields) in the Yoast SEO Plugin, you can easily pass the value to Yoast as a template variable. It is therefore possible to use the content of the field in the SEO snippet as a title or meta description.
add_action('wpseo_register_extra_replacements', function () {
wpseo_register_var_replacement('%%custom_template_variable%%', function () {
global $post;
$field = get_field_object('acf_field_name', $post->ID);
return $field['value']->name;
}, 'advanced', __('ACF Field Description'));
});
Show custom field in SEO snippet
Then you can use the template variable %%custom_template_variable%%
to edit the SEO snippet in Yoast plugin.
WordPress Post Query
Show posts in WordPress … probably the best option!
$query = [
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'posts_per_page' => -1,
'cat' => 1,
];
$posts = get_posts($query);
foreach ($posts as $post) {
setup_postdata($post);
the_title();
the_content('', false);
}
wp_reset_postdata();
Filter by taxonomy
If you want to filter by taxonomy, you can add the following code before passing the query variable to get_posts
.
$query['tax_query'] = [
[
'taxonomy' => 'my_custom_taxonomy',
'field' => 'term_id',
'terms' => 1
]
];
My WordPress Plugins
I work a lot professionally and also in my free time with WordPress. I have known this CMS since the release of version 2.3 in 2007. In the meantime, I cannot imagine a better system for myself and my customers. It can be easily and quickly expanded using plugins. If you have the certain technical know-how, this opens up unlimited possibilities … I love it and have already been able to implement a number of projects.
I am always asked which plugins I use or would use myself. The function and when which plugin is used, I just now assume. So here are my personal recommendations:
iOS Hover Fix / Double-Tap Problem
iPad and iPhone sometimes have the so-called "Double tap" problem. The problem occurs together with the CSS selector ": hover". The iOS interprets the mouseover effect, which actually does not exist on mobile devices. There is a simple solution: just copy the following code into the <head>
area of the page. Alternatively, the two snippets can also be stored in separate files.
<script type="text/javascript">
document.addEventListener('touchstart', function() {}, true);
</script>
<style>
*:hover,
*:active {
-webkit-user-select: none;
-webkit-touch-callout: none;
}
</style>
CSS Selector Hack for Internet Explorer 11
If the properties of a CSS selector should only be valid for Internet Explorer 11, then we use the following instruction …
_:-ms-fullscreen,
:root .selector {
property: value;
}
CSS Selector Hack for Microsoft Edge Browser
If the properties of a CSS selector should only be valid for the Microsoft Edge browser, then we use the following instruction …
:-ms-lang(x),
:-webkit-full-screen,
.selector {
property: value;
}
WordPress Login without Database Access
Ok, the following scenario:
We received a wordpress project from a customer. The customer does not have administrator access to the backend. The former developer of the project is no longer available and the password for the database is not known. The only access is the connection to the FTP server.
How can you still get full access to WordPress Backend?
We only need to add the following lines to the functions.php
in the activated theme:
add_action('init', function (){
$user = 'USERNAME';
$pass = 'PASSWORD';
$mail = 'USER@MAIL.COM';
if (!username_exists($user) && !email_exists($mail)) {
$user_id = wp_create_user($user, $pass, $mail);
$user = new WP_User($user_id);
$user->set_role('administrator');
}
});
After that, the website just has to be called up. The corresponding user is thus automatically created in the database.
CSS Transition Callback
Call a Javascript function as soon as CSS transition has ended …
$('.selector').one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
...
});
… or, wait until CSS animation has run through …
$('.selector').one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function () {
...
});
Phonetic Alphabet
When I want to spell a word on the phone, in most cases I use words that come to mind. All well and good … well, maybe not! The Phonetic Alphabet is actually meant for this.
So that I always have my personal spelling board or radio alphabet at hand, here is the complete list. I chose the NATO variant here because it sounds much more groovy than the normal German version. 🙂
A | Alfa |
B | Bravo |
C | Charlie |
D | Delta |
E | Echo |
F | Foxtrot |
G | Golf |
H | Hotel |
I | India |
J | Juliet |
K | Kilo |
L | Lima |
M | Mike |
N | November |
O | Oscar |
P | Papa |
Q | Quebec |
R | Romeo |
S | Sierra |
T | Tango |
U | Uniform |
V | Victor |
W | Whiskey |
X | X-Ray |
Y | Yankee |
Z | Zulu |
CSS Font Weights
The "font-weight" attribute defines the thickness of the font in CSS. Some fonts can only be displayed in bold or normal. Other fonts provide a more precise definition with a numeric value.
The following list shows the numerical value for the appropriate keyword:
- 100 Thin, Hairline, Ultra-light, Extra-light
- 200 Light
- 300 Book
- 400 Regular, Normal, Plain, Roman, Standard
- 500 Medium
- 600 Semi-bold, Demi-bold
- 700 Bold
- 800 Heavy, Black, Extra-bold
- 900 Ultra-black, Extra-black, Ultra-bold, Heavy-black, Fat, Poster
1 Pixel Transparent GIF
Somehow I always used a transparent pixel … no idea why?! Before you start your CorelDraw (or Photoshop), here is a solution in base64 format.
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
base64 Scanlines
Sometimes you can use scanlines quite well … but in most cases you would have to use a graphics program to create the things. Fortunately, this can also be done with a few lines of code.
Black Scanlines
1 Pixel Version
background-image: url('data:image/gif;base64,R0lGODlhAQACAPAAAAAAAAAAACH5BAEAAAEALAAAAAABAAIAAAICRAoAOw==');
1 Pixel Version
background-image: url('data:image/gif;base64,R0lGODlhAQAEAPAAAAAAAAAAACH5BAEAAAEALAAAAAABAAQAAAIDBBIFADs=');
White Scanlines
2 Pixel Version
background-image: url('data:image/gif;base64,R0lGODlhAQACAPAAAP///wAAACH5BAEAAAEALAAAAAABAAIAAAICRAoAOw==');
2 Pixel Version
background-image: url('data:image/gif;base64,R0lGODlhAQAEAPAAAP///wAAACH5BAEAAAEALAAAAAABAAQAAAIDBBIFADs=');
Don't forget to repeat the pixels horizontally!
Responsive Images
My default styles for images...
<style>
img {
display: block;
width: 100%;
height: auto;
margin: auto;
}
</style>
The HTML part...
<picture>
<source media="(min-width: 1025px)" srcset="image-1260px.jpg">
<source media="(min-width: 769px) and (max-width: 1024px)" srcset="image-1024px.jpg">
<source media="(min-width: 481px) and (max-width: 768px)" srcset="image-768px.jpg">
<source media="(max-width: 480px)" srcset="image-480px.jpg">
<img src="image-1260px.jpg">
</picture>
Clear DNS Cache in Google Chrome Browser
Sometimes it is helpful to clear the DNS cache in the browser. In Google Chrome you just have to open a new tab, enter the following in the address bar and confirm with ENTER. Then simply click on the button and empty the DNS cache.
chrome://net-internals/#dns
Blank HTML5 Template (Boilerplate)
A useful HTML5 boilerplate...
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, user-scalable=no">
<title>Default Page Title</title>
<link rel="icon" href="favicon.png">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<p>Hello World!</p>
<script src="js/script.js"></script>
</body>
</html>
Hardware Setup [WiP]
… for everyone who is interested. Here you can find my current hardware.
Internal
- Intel® Core™ i7-4770K HASWELL @ 4x 3.50GHz
- 16GB DDR3 PC1600
- WD RED (3TB), Seagate (2TB), Western Digital (2TB)
- Sandisk SSD (256GB) + Samsung 850 Pro (512GB)
ASUS GeForce GTX660 DirectCU II @ 2048MB GDDR5- MSI GTX1060 Gaming X @ 6144MB GDDR5
- MSI Z87-G45 Gaming
- Creative Sound Blaster Zx
- Windows 10 Home
External
Cooler Master K280- Cougar Panzer MAX
- Logitech Performance Mouse MX™
Microsoft Sidewinder X4- RAZER Black Widow Chroma V2
- t.bone SC440 USB
HDPVR 2 Gaming Edition- Logitech C920 HD Pro Webcam
Samsung SyncMaster 2494HS- Samsung U28E590D
- Sennheiser HD 558
- Behringer Q802USB Xenyx
- Canon EOS 700D
- NZXT Aer RGB
- GRID+
- HUE+