Programming languages

How to gzip-compress on-the-fly in C++ using boost::iostreams

This minimal example shows you how to write data to a .gz file in C++, compressing the data on-the-fly using boost::iostreams. Using the modern iostreams layer, as opposed to a block-based approach like zlib allows you to use the full power and ease-of-use of std::ostream.

#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
using namespace std;

int main(int argc, char** argv) {
    if(argc < 2) {
        cerr << "Usage: " << argv[0] << " <output .gz file>" << endl;
    }
    //Read filename from the first command line argument
    ofstream file(argv[1], ios_base::out | ios_base::binary);
    boost::iostreams::filtering_streambuf<boost::iostreams::output> outbuf;
    outbuf.push(boost::iostreams::gzip_compressor());
    outbuf.push(file);
    //Convert streambuf to ostream
    ostream out(&outbuf);
    //Write some test data
    out << "This is a test text!\n";
    //Cleanup
    boost::iostreams::close(outbuf); // Don't forget this!
    file.close();
}
cmake_minimum_required(VERSION 3.0)
find_package(Boost 1.36.0 COMPONENTS iostreams)

include_directories(${Boost_INCLUDE_DIRS})
add_executable(iostreams-gz-compress iostreams-gz-compress.cpp)
target_link_libraries(iostreams-gz-compress ${Boost_LIBRARIES})

 

Posted by Uli Köhler in Boost, C/C++

How to decompress GZ files on-the-fly in C++ using boost::iostreams

This minimal example shows you how to open a .gz file in C++, decompress it on-the-fly using boost::iostreams and then copy its contents to stdout:

#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
using namespace std;

int main(int argc, char** argv) {
    if(argc < 2) {
        cerr << "Usage: " << argv[0] << " <gzipped input file>" << endl;
    }
    //Read from the first command line argument, assume it's gzipped
    ifstream file(argv[1], ios_base::in | ios_base::binary);
    boost::iostreams::filtering_streambuf<boost::iostreams::input> inbuf;
    inbuf.push(boost::iostreams::gzip_decompressor());
    inbuf.push(file);
    //Convert streambuf to istream
    istream instream(&inbuf);
    //Copy everything from instream to 
    cout << instream.rdbuf();
    //Cleanup
    file.close();
}
cmake_minimum_required(VERSION 3.0)
find_package(Boost 1.36.0 COMPONENTS iostreams)

include_directories(${Boost_INCLUDE_DIRS})
add_executable(iostreams-gz-decompress iostreams-gz-decompress.cpp)
target_link_libraries(iostreams-gz-decompress ${Boost_LIBRARIES})
Posted by Uli Köhler in Boost, C/C++

How to parse .xml.gz using PugiXML and boost::iostreams

In our previous post Minimal PugiXML file reader example we provided a short example of how to read from an uncompressed XML file using PugiXML. In practice, many large XML files are distributed as .xml.gz package.

Since you can use boost::iostreams to decompress gzipped data on the fly and pipe it directly into PugiXML, you don’t need to store the uncompressed data on your hard drive.

#include <iostream>
#include <fstream>
#include <pugixml.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
using namespace std;
using namespace pugi;

int main() {
    // Open "raw" gzipped data stream
    ifstream file("test.xml.gz", ios_base::in | ios_base::binary);
    // Configure decompressor filter
    boost::iostreams::filtering_streambuf<boost::iostreams::input> inbuf;
    inbuf.push(boost::iostreams::gzip_decompressor());
    inbuf.push(file);
    //Convert streambuf to istream
    istream instream(&inbuf);
    // Parse from stream
    xml_document doc;
    xml_parse_result result = doc.load(instream);
    // Print content of root element
    cout << "Load result: " << result.description() << "\n"
         << doc.child("root-element").child_value() // "Test text"
         << endl;
}
cmake_minimum_required(VERSION 3.0)
find_package(Boost 1.36.0 COMPONENTS iostreams)

include_directories(${Boost_INCLUDE_DIRS})
add_executable(pugixml-example pugixml-example.cpp)
target_link_libraries(pugixml-example pugixml ${Boost_LIBRARIES})
<?xml version="1.0" encoding="UTF-8"?>
<root-element>Test text</root-element>

Download all three files and then run

gzip test.xml
cmake .
make
./pugixml-example

You should see an output like

Load result: No error
Test text

 

Posted by Uli Köhler in Boost, C/C++

How to fix RapidJSON segmentation faults when building nested Documents

Problem:

You want to build a RapidJSON application that builds a JSON from scratch and is using Documents nested inside other documents, but when you try to run it, you see an error message like

zsh: segmentation fault (core dumped)  ./rapidjson-example

Solution:

Segmentation faults (i.e. illegal memory accesses) can have many reasons, but the most common one is that you use local allocators.

In order to fix the issue, use one allocator for your entire application.

MemoryPoolAllocator<> jsonAlloc; // I recommend to declare this statically

// ...
doc.AddMember("text", Value().SetString("Hello JSON!"), jsonAlloc);

Note that MemoryPoolAllocator never releases any memory from its memory pool.

Continue reading →

Posted by Uli Köhler in C/C++

How to fix RapidJSON Assertion `!hasRoot_’ failed.

Problem:

Your program is using RapidJSON but when running it you see an error message like

rapidjson-example: /usr/include/rapidjson/writer.h:452: void rapidjson::Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags>::Prefix(rapidjson::Type) [with OutputStream = rapidjson::BasicOStreamWrapper<std::basic_ostream<char> >; SourceEncoding = rapidjson::UTF8<>; TargetEncoding = rapidjson::UTF8<>; StackAllocator = rapidjson::CrtAllocator; unsigned int writeFlags = 0]: Assertion `!hasRoot_' failed.

Solution:

You are using a Writer for more than one Document. While you can use the Stream backing the Writer for any number of documents, each Writer must only be used once!

To fix the issue, create a Writer instance (on the same output Stream) for each document you intend to write.

Continue reading →

Posted by Uli Köhler in C/C++

How to create and serialize a document in RapidJSON

RapidJSON is a JSON library optimized for speed – hence it lacks some convieniece and lacks easy-to-use documentation on how to create JSON documents from scratch.

Here’s how you can create a Document:

// Generate document: {"text": "Hello JSON!"}
Document doc;
doc.SetObject(); // Make doc an object !
doc.AddMember("text", "Hello JSON!", doc.GetAllocator());

Full example, which prints to cout:

#include <iostream>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/ostreamwrapper.h>
using namespace rapidjson;
using namespace std;

int main() {
    // Generate document: {"text": "Hello JSON!"}
    Document doc;
    doc.SetObject(); // Make doc an object !
    doc.AddMember("text", "Hello JSON!", doc.GetAllocator());
    // Write to stdout
    OStreamWrapper out(cout);
    Writer<OStreamWrapper> writer(out);
    doc.Accept(writer);
}

 

Posted by Uli Köhler in C/C++

How to write JSON to cout in RapidJSON

RapidJSON does not provide a straightforward way of serializing JSON to cout (= stdout), but you can use OStreamWrapper to do that:

#include <rapidjson/writer.h>
#include <rapidjson/ostreamwrapper.h>
// ... 
OStreamWrapper out(cout);
Writer<OStreamWrapper> writer(out);
doc.Accept(writer);

Full example:

#include <iostream>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/ostreamwrapper.h>
using namespace rapidjson;
using namespace std;

int main() {
    // Generate document: {"text": "Hello JSON!"}
    Document doc;
    doc.SetObject(); // Make doc an object !
    doc.AddMember("text", "Hello JSON!", doc.GetAllocator());
    // Write to stdout
    OStreamWrapper out(cout);
    Writer<OStreamWrapper> writer(out);
    doc.Accept(writer);
}

 

Posted by Uli Köhler in C/C++

How to iterate PugiXML children using C++11 foreach-loop

PugiXML allows you to use the C++11 for loop (also known as range-based for loop or foreach loop) to iterate the children of a node easily:

<?xml version="1.0" encoding="UTF-8"?>
<root-element>
    <sub>A</sub>
    <sub>B</sub>
    <sub>C</sub>
</root-element>
#include <iostream>
#include <pugixml.hpp>
using namespace std;
using namespace pugi;

int main() {
    xml_document doc;
    xml_parse_result result = doc.load_file("test.xml");

    for(const auto& child : doc.child("root-element")) {
        cout << child.child_value() << endl;
    }
}
add_executable(pugixml-for pugixml-for.cpp)
target_link_libraries(pugixml-for pugixml)

Running the example will print

A
B
C
Posted by Uli Köhler in C/C++

Minimal PugiXML file reader example

XML:

<?xml version="1.0" encoding="UTF-8"?>
<root-element>Test text</root-element>

C++:

#include <iostream>
#include <pugixml.hpp>
using namespace std;
using namespace pugi;

int main() {
    xml_document doc;
    xml_parse_result result = doc.load_file("test.xml");
    
    cout << "Load result: " << result.description() << "\n"
         << doc.child("root-element").child_value() // "Test text"
         << endl;
}

Build configuration

add_executable(pugixml-example pugixml-example.cpp)
target_link_libraries(pugixml-example pugixml)

Compile using

cmake .
make

 

Posted by Uli Köhler in C/C++

How to parse all PubMed baseline files in parallel using Python

In our previous post How to parse PubMed baseline data using Python we investigate how to use the pubmed_parser library to parse PubMed medline data using Python.

In this follow-up we’ll provide an example of how to use glob to select all PubMed baseline files in a directory and use concurrent.futures with tqdm to provide a convenient yet easy-to-use process parallelism using ProcessPoolExecutor and a progress bar UI for the command line.

First, install the requirements using

pip install git+git://github.com/titipata/pubmed_parser.git six numpy tqdm

Now download this script, ensure some files like pubmed20n0002.xml.gz or pubmed20n0004.xml.gz are in the same directory and run it:

#!/usr/bin/env python3
import pubmed_parser as pp
import glob
import os
from collections import Counter
import concurrent.futures
from tqdm import tqdm

# Source: https://techoverflow.net/2017/05/18/how-to-use-concurrent-futures-map-with-a-tqdm-progress-bar/
def tqdm_parallel_map(executor, fn, *iterables, **kwargs):
    """
    Equivalent to executor.map(fn, *iterables),
    but displays a tqdm-based progress bar.
    
    Does not support timeout or chunksize as executor.submit is used internally
    
    **kwargs is passed to tqdm.
    """
    futures_list = []
    for iterable in iterables:
        futures_list += [executor.submit(fn, i) for i in iterable]
    for f in tqdm(concurrent.futures.as_completed(futures_list), total=len(futures_list), **kwargs):
        yield f.result()

def parse_and_process_file(filename):
    """
    This function contains our parsing code. Usually, you would only modify this function.
    """
    # Don't parse authors and references for this example, since we don't need it
    dat = pp.parse_medline_xml(filename, author_list=False, reference_list=False)

    # For this example, we'll build a set of count of all MeSH IDs in this file
    ctr = Counter()
    for entry in dat:
        terms = [term.partition(":")[0].strip() for term in entry["mesh_terms"].split(";")]
        for term in terms:
            ctr[term] += 1
    return filename, ctr


if __name__ == "__main__":
    # Find all pubmed files in the current directory
    all_filenames = glob.glob("pubmed*.xml.gz")
    # For some workloads you might want to use a ThreadPoolExecutor,
    # but a ProcessPoolExecutor is a good default
    executor = concurrent.futures.ProcessPoolExecutor(os.cpu_count())
    # Iterate results as they come in (the order is not the same as in the input!)
    for filename, ctr in tqdm_parallel_map(executor, parse_and_process_file, all_filenames):
        # NOTE: If you print() here, this might interfere with the progress bar,
        # but we accept that here since it's just an example
        print(filename, ctr)

Now you can start modifying the example, most notably the parse_and_process_file() function to do whatever processing you intend to do.

Posted by Uli Köhler in Bioinformatics, Python

How to parse PubMed baseline data using Python

Want to parse more than one PubMed file? Also see our follow-up at How to parse all PubMed baseline files in parallel using Python

PubMed provides a data dump of metadata from all PubMed articles on the NCBI Servers.

In this example, we’ll parse one of the compressed metadata XML files using the pubmed_parser Python library.

First, download one of the .xml.gz files. For this example, we’ll use pubmed20n0001.xml.gz.

Now we can install the required libraries:

pip install git+git://github.com/titipata/pubmed_parser.git six numpy

Now you can download & run our script. For this example, we will extract a list of MeSH terms for every  and print PubMed ID and a list of MeSH IDs.

#!/usr/bin/env python3
import pubmed_parser as pp

# Don't parse authors and references for this example, since we don't need it
dat = pp.parse_medline_xml("pubmed20n0001.xml.gz", author_list=False, reference_list=False)
# Iterate PubMed entries from that file
for entry in dat:
    # entry["mesh_terms"] is like "D000818:Animal; ..."
    # In this example, we are only interested in the MeSH ID, like D000818.
    # Print the PubMed ID, followed by a list of MeSH terms.
    print(entry["pmid"], [
        term.partition(":")[0].strip() for term in entry["mesh_terms"].split(";")
    ])

Running this script takes 13.3 seconds on my Notebook which is equivalent to about 1.4 MBytes of GZipped input data per second. When running the script, you will see lines like

30957 ['D000319', 'D001794', 'D003864', 'D006801', 'D006973', 'D007676', 'D010869']

which means that the PubMed Article with ID 30957 has the MeSH terms ['D000319', 'D001794', 'D003864', 'D006801', 'D006973', 'D007676', 'D010869'].

See the pubmed_parser documentation, or just try it out interactively for more information on what fields are available in the entries you can iterate.

Posted by Uli Köhler in Bioinformatics, Python

How to install PyPy3 + virtual environment in 30 seconds

TL;DR:

Run this

wget -qO- https://techoverflow.net/scripts/pypy3-installer.sh | bash

then run vpypy every time you want to activate (you might need to restart). The script currently assumes you are running Linux x86_64 and have installed virtualenv (sudo apt install virtualenv or similar if you don’t have it installed)

Full description:

PyPy is an alternate Python implementation that can be used to speed up many workloads. However, installing it is a somewhat cumbersome process, especially if you don’t have too much experience with virtual environments and related concepts.

We provide a script that automatically downloads PyPy3, installs it to ~/.pypy3 and creates a virtual environment in ~/.pypy3-virtualenv. After that, it creates a shell alias vpypy that aliases to source ~/.pypy3-virtualenv/bin/activate and hence provides an easily memoizable way of activating the environment without requiring the user to memoize the directory.

Also, since both pypy3 itself and the virtual environment are  installed in the user’s home directory, running this script does not require admin permissions.

After running the script using

wget -qO- https://techoverflow.net/scripts/pypy3-installer.sh | bash

you can activate the virtual environment using the vpypy alias that is automatically added to ~/.bashrc and ~/.zshrc. Restart your shell for the alias definition to load, then run vpypy:

uli@uli-laptop ~ % vpypy
(.pypy3-virtualenv) uli@uli-laptop ~ % 

You can see that the prompt has changed. Now you can use pip (which will install packages locally to the PyPy3 virtualenv), python (which maps to pypy3) and other related executables. In order to run a script using PyPy, just run python myscript.py

Full source code:

#!/bin/bash
# TechOverflow's 30-second Pypy3 virtual environment generator
# This script is released under CC0 1.0 Universal
DIRECTORY=~/.pypy3
VENV_DIRECTORY=~/.pypy3-virtualenv
VERSION=pypy3.6-v7.3.0-linux64

# Download (or use existing) pypy3
if [ -d "$DIRECTORY" ]; then
    echo "Skipping PyPy download, already exists"
else
    echo "Downloading PyPy to $DIRECTORY"
    # Download & extract to DIRECTORY
    wget https://techoverflow.net/downloads/${VERSION}.tar.bz2 -O /tmp/${VERSION}.tar.bz2
    bash -c "cd /tmp && tar xjvf ${VERSION}.tar.bz2"
    mv /tmp/${VERSION} $DIRECTORY
    rm /tmp/${VERSION}.tar.bz2
fi

# Create virtualenv
if [ -d "$VENV_DIRECTORY" ]; then
    echo "Skipping to create pypy3 virtualenv, already exists"
else
    echo "Creating PyPy virtual environment in $VENV_DIRECTORY"
    virtualenv -p ${DIRECTORY}/bin/pypy3 ${VENV_DIRECTORY}
fi

# Create "vpypy" shortcut
set -x
vpypy
result="$?"
set +x
if [ "$result" -ne 127 ]; then
    echo "Skipping to create vpypy shortcut, already exists in current shell"
else
    echo "Creating bash/zsh shortcut 'vpypy'"
    if [ -f ~/.bashrc ]; then
        echo -e "\n# TechOverflow PyPy installer\nalias vpypy='source ${VENV_DIRECTORY}/bin/activate'\n" >> ~/.bashrc
    fi
    if [ -f ~/.zshrc ]; then
        echo -e "\n# TechOverflow PyPy installer\nalias vpypy='source ${VENV_DIRECTORY}/bin/activate'\n" >> ~/.zshrc
    fi
    # Activate shortcut in current shell (but do not automatically activate virtual environment)
    alias vpypy='source ${VENV_DIRECTORY}/bin/activate'
fi

echo -e "\n\nPyPy installation finished. Restart your shell, then run 'vpypy' to activate the virtual environment"

 

 

Posted by Uli Köhler in Linux, Python

How to decompress gzip files using zlib – a minimal example

zlib is a great library in use by hundreds of thousands of programs (including Python). However, it lacks documentation.

This minimal example shows you how to create a simple zcat-like program that decompresses a gzipped input file and prints its contents to stdout.

/**
 * zzcat.c -- Minimal gzip decompression example using zlib
 * Written by Uli Köhler (techoverflow.net).
   Not copyrighted -- provided to the public domain
 */
#include <stdio.h>
#include <zlib.h>

#define BUFSIZE 16384

/* compress or decompress from fin (command line argument) to stdout */
int main(int argc, char **argv)
{
    if(argc <= 1) { // <= (number of expected CLI arguments)
        fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
        return -1;
    }

    gzFile fin = gzopen(argv[1], "rb");

    char buf[BUFSIZE];
    int n;

    while((n = gzread(fin, buf, BUFSIZE)) > 0) {
        fwrite(buf, 1, n, stdout);
    }

    return 0;
}

Compile using

g++ -o zzcat zzcat.c -lz

Usage example:

# Create test file
echo "foo" | gzip -c > test.txt.gz
# Uncompress using zzcat! 
./zzcat test.txt.gz # This will print "foo"

 

Posted by Uli Köhler in C/C++

C/C++ program template with one CLI argument

This example program provides an example of a CLI executable in C/C++ that uses one command line argument and exits with a usage message if that argument is not present:

#include <stdio.h>

int main(int argc, char **argv)
{
    if(argc <= 1) { // <= (number of expected CLI arguments)
        fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
        return -1;
    }
    
    // TODO Your code goes here!
    printf("Input file: %s\n", argv[1]);
    return 0;
}

Compile with

g++ -o cli-onearg cli-onearg.cpp

Usage example:

$ ./cli-onearg  
Usage: ./cli-onearg <input file>
$ ./cli-onearg my-input-file.txt
Input file: my-input-file.txt

 

Posted by Uli Köhler in C/C++

How to fix /usr/bin/ld: cannot find -lzlib

Problem:

You want to compile a C++ executable that uses zlib, but you see an error message like

/usr/bin/ld: cannot find -lzlib
collect2: error: ld returned 1 exit status

Solution:

Use -lz instead of -lzlib. The zlib library is named libz.so, not libzlib.so!

Example:

g++ -o ztest zpipe.c -lz

 

Posted by Uli Köhler in C/C++

How to fill matrix with NaN in Octave

Also see: How to initialize NaN matrix in octave

If you have a matrix in Octave like

A = zeros(2,4)

you can fill it with NaN using

A(:,:) = NaN

Note that you have to use A(:) = NaN for 1D-matrices. A(:,:) = NaN for 2D matrices, A(:,:,:) = NaN for 3D matrices and so on.

Example:

>> A = zeros(2,4)
A =

   0   0   0   0
   0   0   0   0

>> A(:,:) = NaN
A =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

 

Posted by Uli Köhler in Octave

How to initialize NaN matrix in octave

Also see: How to fill matrix with NaN in Octave

You can use NaN(N,M) as a function to initialize a NxM matrix filled with NaN in octave. For example, to initialize a 2x4x3 matrix, use

A = NaN(2,4,3)

Example:

>> A = NaN(2,4,3)
A =

ans(:,:,1) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

ans(:,:,2) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

ans(:,:,3) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
Posted by Uli Köhler in Octave

How to remove all event listeners from a DOM element in Javascript

You can remove all event listeners from a DOM element in Javascript by replacing the element with a deep clone of itself. elem.cloneNode(...) will not clone the event listeners of the source element.

elem.replaceWith(elem.cloneNode(true));

Full example:

var elem = document.getElementById('mybutton');
elem.replaceWith(elem.cloneNode(true));

Source for the original (partial) suggestion on StackOverflow: @Felix Kling

Posted by Uli Köhler in Javascript

How to remove dashicons CSS from WordPress

WordPress uses dashicons as its primary icon font. However, many themes do not require dashicons on the frontend and hence it’s only used in the admin frontend, i.e. when a user is logged in.

I made a simple plugin to make WordPress load the dashicons CSS only if the user is logged in. For non-logged-in users, the dashicons CSS is removed from the frontend (hence improving the loading speed of your website).

<?php 
/*
Plugin Name: TechOverflow remove dashicons
*/

/**
 * Remove dashicons CSS from the page, only load if user is logged in
 */
function dashicons_admin_only() {
    if(!is_user_logged_in()) {
        global $wp_styles;
        wp_dequeue_style('dashicons');
        // wp_deregister_style('dashicons') causes internal PHP errors in WordPress !
        $wp_styles->registered['dashicons']->src = '';
    }
}
    
add_action( 'wp_print_styles', 'dashicons_admin_only' );

Just create an new folder called techoverflow-no-dashicons inside your wp-content/plugins directory, and save the source code listed above as wp-content/plugins/techoverflow-no-dashicons/functions.php inside. After that, you can modify the code to fit your specific needs.

Note that using this plugin might make your site appear differently if you are logged in. Hence it’s important to check your site when not logged in, e.g. using incognito mode.

Posted by Uli Köhler in PHP, Wordpress

WordPress: How to move script to footer if plugin doesn’t support it

Many WordPress plugins provide you with an option to configure whether scripts are loaded in the header or the footer of the page.

If you want to move a script to the footer for performance reasons, and the plugin doesn’t support it, one option is to just edit the wp_enqueue_script() call in the plugin’s source code and set $in_footer = true.

However, these change won’t survive plugin updates and hence are not recommended for security reasons.

A better option is to write a custom plugin that removes the <script> tag from the head and moves it to the footer. The following file is the functions.php of my custom plugin that moves the <script> tag from the cookie-law-info plugin to the bottom of the page.

<?php 
/*
Plugin Name: TechOverflow Cookie Law to footer
*/

function postpone_script($name) {
    global $wp_scripts;
    // Get attributes from original script
    $thesrc = $wp_scripts->registered[$name]->src;
    $theversion = $wp_scripts->registered[$name]->ver;
    // Remove script from the header
    wp_dequeue_script($name);
    wp_deregister_script($name);
    // Add script to the bottom
    wp_enqueue_script($name, $thesrc, false /* no deps */, $theversion, true /* bottom */);
}

/**
 * Move cookie law javascript to the bottom
 */
function postpone_cookie_law() {
    postpone_script('cookie-law-info');
}
    
add_action( 'wp_print_scripts', 'postpone_cookie_law' );

Just create an new folder called techoverflow-cookie-law-footer inside your wp-content/plugins directory, and save the source code listed above as wp-content/plugins/techoverflow-cookie-law-footer/functions.php inside. After that, you can modify the code to fit your specific needs.

Remember to check your page for issues (javascript errors, delayed rendering of some elements) that appear when you move the javascript to the footer, since some plugins may not be compatible with the script being placed in the footer. Also, you might need to call postpone_script() multiple scripts with different $name argument. Check the original plugin’s wp_enqueue_script() calls for the correct $name (first argument). In case it’s not obvious which wp_enqueue_script() call relates to a specific script, you can also check the version in the src of the original <script> tag (e.g. 1.8.2 in ...?ver=1.8.2 ) and search for that version in the plugin’s folder to find the matching wp_enqueue_script() call.

Posted by Uli Köhler in PHP, Wordpress