4
votes

I'm working on a simple web app and I receive the above error. Would you guys please lend me a hand?

app.js:

var movieApp = movieApp || {};

(function () {
movieApp.controller = {
    init:function() {
        movieApp.router.init();
        movieApp.section.init();
    }
};

movieApp.router = {
    init:function() {
        routie({
            '/about': function() {
                movieApp.section.toggle('section[data-route="about"]');
            },              
            '/movies': function() {
                movieApp.section.toggle('section[data-route="movies"]');
            },
            ' ': function() {
                movieApp.section.toggle('section[data-route="about"]');
            },  
        });
    }
};

movieApp.content = {
    about: {
        title: "About this app",
        description: "...",
    },

    movies: [
        {
            title: "Shawshank Redemption",
            releaseDate: "14 October 1994",
            description: "Two imprisoned men bond over a number of years, finding solace and eventual redemption through acts of common decency.",
            cover: "../WebApp/static/images/shawshank-redemption.jpg"
        },
        {
            title: "The Godfather",
            releaseDate:"24 March 1972",
            description:"The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.",
            cover: "../WebApp/static/images/the-godfather.jpg"
        },
        {
            title: "Pulp Fiction",
            releaseDate: "14 October 1994",
            description: "The lives of two mob hit men, a boxer, a gangster's wife, and a pair of diner bandits intertwine in four tales of violence and redemption.",
            cover: "../WebApp/static/images/pulp-fiction.jpg"
        },
        {
            title: "The Dark Knight",
            releaseDate: "18 July 2008",
            description: "When Batman, Gordon and Harvey Dent launch an assault on the mob, they let the clown out of the box, the Joker, bent on turning Gotham on itself and bringing any heroes down to his level.",
            cover: "../WebApp/static/images/the-dark-knight.jpg"
        }
    ]
};

movieApp.section = {
    init:function() {
        this.about();
        this.movies();
    },

    about:function() {
        var aboutSection = {
            'title': movieApp.content.about.title,
            'description': movieApp.content.about.description
        };

        Transparency.render(document.querySelector('section[data-route="about"]'),aboutSection);
    },

    movies:function() {
        var moviesSection = {
            'header': "Favorite Movies",
            'movies': movieApp.content.movies
        }

        // dit zorgt ervoor dat de src van img tag veranderd naar wat er staat in this.cover
        var directives = {
            movies: {
                cover: {
                    src: function(params){
                        return this.cover
                    }
                }
            }
        }

        Transparency.render(document.querySelector('section[data-route="movies"]'),moviesSection, directives);
    },

    toggle:function(section) {
        section = typeof section !== 'undefined' ? section : 'section[data-route="about"]';
        document.querySelector(section).classList.toggle('active');
    }
};

movieApp.controller.init();

})();

The html file looks like this:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Movies Web App</title>
    <link rel="stylesheet" href="static/stylesheets/main.css">
</head>
<body>
    <header>
        <nav>
            <ul>
                <li><a href="#/about">About</a></li>
                <li><a href="#/movies">Movies</a></li>
            </ul>
        </nav>
    </header>

    <main id="content">

        <section data-route="about">
            <header>
                <h1 data-bind="title"></h1>
                <p data-bind="description"></p>
            </header>
        </section>

        <section data-route="movies">
            <h1 data-bind="header"></h1>    
            <div data-bind="movies">
                <article data-bind="movie">
                    <header>
                        <h1 data-bind="title"></h1>
                        <em><time data-bind="releaseDate"></time></em>
                    </header>
                    <figure>
                        <img data-bind="cover" src="" alt="">
                    </figure>
                    <p data-bind="description"></p>
                </article>
            </div>
        </section>
    </main>

    <script src="static/js/lib/routie.js"></script>
    <script src="static/js/lib/transparency.js"></script>
    <script src="static/js/app.js"></script>
</body>
</html>

When I run the index page, I get the following error: Uncaught TypeError: Cannot read property 'classList' of null.

Thanks for the help.

1
So obviously document.querySelector(section) is null - Check the value of section - techfoobar
I did console.log(this.section) and I get undefined. How can I solve this? - Matt
Your toggle is designed to take an argument section. If you call toggle somewhere without argument, document.querySelector(section) == null. - Martin Ernst
But don't I pass the argument above @: 'about': function() { movieApp.section.toggle('section[data-route="about"]'); }, - Matt
@Matt - section is an argument, not a property of the calling context. Try console.log(section); immediately before your document.querySelector(...) line. - techfoobar

1 Answers

1
votes

In this section this is equivalent to movieApp.section.

movieApp.section = {
    init:function() {
        this.about();
        this.movies();
        this.toggle();
    },
};

So this.toggle() is calling movieApp.section.toggle() and is then not passing a parameter to that function.

If you wanted to set a default active class on the 'about' section you would need to do this to your function:

toggle:function(section) {
    section = typeof section !== 'undefined' ? section : 'section[data-route="about"]';
    document.querySelector(section).classList.toggle('active');
}

UPDATE

As per the comments you can just remove the toggle line from here:

movieApp.section = {
    init:function() {
        this.about();
        this.movies();
    },
};