Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

WordPress

Ryan Smee
Ryan Smee
3,392 Points

Additional jQuery to Wordpress Bootstrap Theme

I have recently been working on a responsive theme in Wordpress local using Bootstrap. I want to add some extra functionality to the site with jQuery. Understanding that Bootstrap already calls jQuery I have just added a '.js' file and started writing jQuery to manipulate the dom.

When i write in jQuery i get errors but when i write in vanilla Javascript I don't. Its like the '.js' file is being loaded in before the jQuery call but bootstrap is loaded in first..

Can anyone let me know when I am going wrong? I'm pretty new to Wordpress so i'm sure it's just something silly i'm missing.

Cheers

3 Answers

Andrew Shook
Andrew Shook
31,709 Points

Ok, the problem is in your scripts.js, and the problem is JavaScript engine in the browser doesn't natively know that the "$" is shorthand for jQuery. Try wrapping your jQuery in this:

(function($){

      $('#testDiv').hide();

})(jQuery);

or like this:

function testFunction( $ ){
    $('#testDiv').hide();
}

//function call
testFunction( jQuery);
Ryan Smee
Ryan Smee
3,392 Points

Brilliant, that has worked!

can I declare '$' as 'jQuery', so that I don't have to pass it into every function?

Andrew Shook
Andrew Shook
31,709 Points

you could do something like this:

var $ = jQuery();

but that could run you into some problems in the future.

Ryan Smee
Ryan Smee
3,392 Points

Yeah that was me being dim. After thinking about it for a second I added:

var $ = jQuery

How comes it may give me an issue?

Ryan Smee
Ryan Smee
3,392 Points

Ah, that makes a lot of sense. Thankyou for your help mate. I really appreciate it!

Andrew Shook
Andrew Shook
31,709 Points

If you use another library that has $ as an alias, it will cause an error.

Andrew Shook
Andrew Shook
31,709 Points

Ryan, WordPress doesn't call jQuery on the front end theme. WP comes with jQuery, and uses it for the admin theme. If you would like to include jQuery in you custom theme then you need to add this line of code to your theme's functions.php.

wp_enqueue_script('jquery');  // Enqueue jQuery that's already built into WordPress

If you already have a function in you functions.php which adds js or css files using the 'wp_enqueue_scripts' hook, then add that code there. If not then add this whole code block to your functions.php:

function add_custom_scripst() {
    wp_enqueue_script('jquery');  // Enqueue jQuery that's already built into WordPress
    wp_enqueue_style( 'miami_ymca-style', get_stylesheet_uri() ); //Enqueue style.css
}
add_action( 'wp_enqueue_scripts', 'add_custom_scripts' ); 
Ryan Smee
Ryan Smee
3,392 Points

Hi Andrew,

This is very interesting. I already have already added in bootstrap though and I thought this would call jQuery? Or do I have to do JQuery separately?

    function themeJS() {

        global $wp_scripts;

        wp_register_script( 'html5Shiv', 'https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js', '', '', false );
        wp_register_script( 'respondJS', 'https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js', '', '', false );
        //load
        $wp_scripts->add_data( 'html5Shiv', 'conditional', 'lt IE 9' );
        $wp_scripts->add_data( 'respondJS', 'conditional', 'lt IE 9' );
        //add
        wp_enqueue_script( 'bootstrap_js', get_template_directory_uri() . '/js/bootstrap.min.js', array('jquery'), '', true );
        wp_enqueue_script( 'script_js', get_template_directory_uri() . '/js/script-min.js', array('jquery', 'bootstrap_js'), '', true );
    }
    add_action( 'wp_enqueue_scripts', 'themeJS' );
Andrew Shook
Andrew Shook
31,709 Points

No you have to call jQuery yourself if the theme you are using doesn't do it. Try this:

   function themeJS() {

        global $wp_scripts;

        wp_register_script( 'html5Shiv', 'https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js', '', '', false );
        wp_register_script( 'respondJS', 'https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js', '', '', false );
        //load
        $wp_scripts->add_data( 'html5Shiv', 'conditional', 'lt IE 9' );
        $wp_scripts->add_data( 'respondJS', 'conditional', 'lt IE 9' );
        //add

        // add this line to your function
        wp_enqueue_script('jquery');  // Enqueue jQuery that's already built into WordPress


        wp_enqueue_script( 'bootstrap_js', get_template_directory_uri() . '/js/bootstrap.min.js', array('jquery'), '', true );
        wp_enqueue_script( 'script_js', get_template_directory_uri() . '/js/script-min.js', array('jquery', 'bootstrap_js'), '', true );
    }
    add_action( 'wp_enqueue_scripts', 'themeJS' );
Ryan Smee
Ryan Smee
3,392 Points

Hmmm I just tried it and it didn't seem to work. I am still getting the:

'Uncaught TypeError: undefined is not a function'

Thank you for all your help so far.

Andrew Shook
Andrew Shook
31,709 Points

Do you have a URL I could go to, or are you building the site locally?

Also, which file is throwing the error? Bootstrap.js or your Scripts.js?

Ryan Smee
Ryan Smee
3,392 Points

No it's a local build atm.

Yeah it's the 'script.js'. As I say, it's allowing me to write in vanilla JS just not in JQuery. The pain is that I am doing this as a first project for a new job and i have boasted my JQuery skills and now can't show them off.

Andrew Shook
Andrew Shook
31,709 Points

By local file do you mean your scripts.js? If so please post that code. I believe I know what the problem is, but I'll have to see the code to be sure.

Ryan Smee
Ryan Smee
3,392 Points

sorry i've added my reply as a new answer and the formatting's gone a bit wrong.

Andrew Shook
Andrew Shook
31,709 Points

Not 100% sure but I believe that WordPress forces jQuery to be run in "no conflict" mode. Since other JS libraries also use the "$" as an alias, WP makes sure no one can use it so that things don't get all messed up.

Ryan Smee
Ryan Smee
3,392 Points

The function PHP is as follows:

//setting style sheet locations
    function themeStyles() {

        wp_enqueue_style( 'bootstrap_css', get_template_directory_uri() . '/css/bootstrap.min.css' );
        wp_enqueue_style( 'main_css', get_template_directory_uri() . '/style.css' );
    }
    add_action( 'wp_enqueue_scripts', 'themeStyles' );

//fallback for < ie9 
    function themeJS() {

        global $wp_scripts;

        wp_register_script( 'html5Shiv', 'https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js', '', '', false );
        wp_register_script( 'respondJS', 'https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js', '', '', false );
        //load
        $wp_scripts->add_data( 'html5Shiv', 'conditional', 'lt IE 9' );
        $wp_scripts->add_data( 'respondJS', 'conditional', 'lt IE 9' );
        //add
        wp_enqueue_script('jquery');  // Enqueue jQuery that's already built into WordPress

        wp_enqueue_script( 'bootstrap_js', get_template_directory_uri() . '/js/bootstrap.min.js', array('jquery'), '', true );
        wp_enqueue_script( 'script_js', get_template_directory_uri() . '/js/script-min.js', array('jquery', 'bootstrap_js'), '', true );
    }
    add_action( 'wp_enqueue_scripts', 'themeJS' );

//Customise menu 
    add_theme_support( 'menus' );

    function registerMenus() {
        register_nav_menus(
            array(
                'header-menu' => __( 'Header Menu' )
            )
        );
    }
    add_action( 'init', 'registerMenus');

//setting style sheet locations
    function create_widget( $name, $id, $description ) {
        register_sidebar(array(
            'name' => __( $name ),   
            'id' => $id, 
            'description' => __( $description ),
            'before_widget' => '<div class="widget">',
            'after_widget' => '</div>',
            'before_title' => '<h2>',
            'after_title' => '</h2>'
        ));
    }

    create_widget( 'Row 1 Left Box', 'row1left', 'Row 1 - This is the left section' );
    create_widget( 'Row 1 Left Box2', 'row1left2', 'Row 1 - This is hidden until button 2 is pressed' );
    create_widget( 'Row 1 Left Button', 'leftbutton', 'Row 1 - Left button' );
    create_widget( 'Row 1 Right Button', 'rightbutton', 'Row 1 - Right button' );
    create_widget( 'Row 1 Right Box', 'row1right', 'Row 1 - This is the Right section' );

    create_widget( 'Row 2 Left Box', 'row2left', 'Row 2 - This is the left section' );
    create_widget( 'Row 2 center Box', 'row2center', 'Row 2 - This in the middle section' );
    create_widget( 'Row 2 Right Box', 'row2right', 'Row 2 - This is the right section' );   

As for my JS file it doesn't have a lot in it, other than a bit of Van DOM Manipulation:

//Call to action pannel expand
function ctaExpand() {
    document.getElementById('js-expandCTA').style.display = "none";
    document.getElementById('js-minCTA').style.display = "block";
    document.getElementById('js-CTAbar').style.transition = "all 2s ease-in-out";
    document.getElementById('js-textCTA').style.display = "block";
}

function ctaMin() {
    document.getElementById('js-minCTA').style.display = "none";
    document.getElementById('js-expandCTA').style.display = "block";
    document.getElementById('js-CTAbar').style.height = "auto";
    document.getElementById('js-textCTA').style.display = "none";
}

//iPhone 6 button
function but1() {
    document.getElementById('js-pan2').style.display = "none";
    document.getElementById('js-pan1').style.display = "block";
}

//iPhone 6 Plus button
function but2() {
    document.getElementById('js-pan1').style.display = "none";
    document.getElementById('js-pan2').style.display = "block";
}

The test I was trying to do was a simple:

function testFunction {
        $('#testDiv').hide();
}

I also wrapped it in a document load but no luck.