Node.js / Express - How to access 'req' in JavaScript

So I have a page which is loaded called tournament/:key, which is passing to it a Tournament object. As you can see from below the Jade template is accessing each variable from the Tournament by using, for example, #{tournemantData.name} which would print the Tournament's name to the page. The set of matches is actually stored as an array within Tournament, and I would like to access these through a JavaScript file in order to work with them on this page, as eventually I would like a set of graphical brackets to be produced.

How would I access this tournamentData inside a JavaScript file?

  app.get('/tournament/:key', function(req, res) {
    util.log('Serving request for url [GET] ' + req.route.path);
    Tournament.findByKey(req.params.key, function(err, tournamentData){
      if(!err && tournamentData){
        tournamentData = tournamentData;
        //util.log(tournamentData.teams[0]);
        res.render('tournamentDetails', { 'tournamentData' : tournamentData, seedsSerialized : JSON.stringify(tournamentData.teams) } );
      } else {
        util.log('Error in fetching Tournament by key : ' + req.params.key);
        res.json({
          'retStatus' : 'failure',
          'msg' : 'Error in fetching Tournament by key ' + req.params.key
        });
      }
    });
  });

Jade:

        p Name: #{tournamentData.name}
        p ID: #{tournamentData._id}
        p Key: #{tournamentData.key}
        p Teams: #{tournamentData.teams}
        p Matches: #{tournamentData.matches}
        p Brackets:
        div.bracket
            #tournamentBrackets
            script(type='text/javascript')
                var seeds = var rankArray = !{seedsSerialized};

brackets.js

numRounds = Math.log(seeds.length) / Math.log(2);

/**
 * Randomize array element order in-place.
 * Using Fisher-Yates shuffle algorithm.
 */
function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
};

shuffleArray(seeds);

var bracketData = {
    teams : [              // Matchups
        [ seeds[0].name,  seeds[1].name ],
    [ seeds[2].name,  seeds[3].name ]
  ],
  results : [[
      [ [1, 0], [1, 0] ],
      [ [1, 0], [1, 0] ]
    ]]
}

$(function() {
    $('#tournamentBrackets').bracket({
        init: bracketData
    });
});

EDIT: I have added the JavaScript file, what this is doing is using jQuery.bracket (a jQuery project I am using for generating nice looking brackets), at the moment you can see that I have manually put in the names of the teams.

The array of brackets inside brackets.js is the same format as in tournamentData.matches, but the basic idea is that I want to access this information from within this JavaScript file so that I can print the brackets with these teams.

Edit:

$(document).ready(function() {
  // tournament  is now the same as tournmentData in your express route
  var tournamentText = $(#tournamentData).text();
  var tournament = JSON.parse(tournamentText);
  console.log(tournament, tournament);

  $(function() {
    $('#tournamentBrackets').bracket({
      init: bracketData
    });
  });
}

You can already access the variable in your Jade template meaning that you can access it in that page through Javascript.

Basically you already have the access to tournamentData object.

What you can do is get that tournamentData object and make it global JS variable or keep it in page scope.

Something like this in your template

- var matches = tournamentData.matches ;  //Specific scope

Or

- window.matches = tournamentData.matches; //Binded to window object global

You could publish your data on your Express server via a route like you've already shown with /tournament/:key.

Something like :

 app.get('/tournament-seeds/:key', function(req, res) {
    Tournament.findByKey(req.params.key, function(err, tournamentData){
      res.json({ tournamentData: tournamentData });
    });
  });

Then ...

In your brackets.js file you want to make a call to fetch your seeds (?) data:

So changing your last function in brackets.js in your existing code to something like this (cut for brevity) should do what you want:

$(function() {   $.get('/tournament-seeds/somerandomkey', function(tournamentData){
   seeds = tournamentData.seeds;

    $('#tournamentBrackets').bracket({
        init: bracketData
    });   
  }); 
});

Disclaimer: I'm not suggesting this is the best way to do it, it's the quickest I can think of at the moment!

Alternatively you could blat the json into a variable directly in your template. See: Passing an array to a JSON object for Jade rendering

  • EDIT * like :

On your route:

app.get('/tournament/:key', function(req, res) {
    util.log('Serving request for url [GET] ' + req.route.path);
    Tournament.findByKey(req.params.key, function(err, tournamentData){
      tournamentData = tournamentData;
      util.log(tournamentData.teams[0]);
      res.render('tournamentDetails', { 'tournamentData' : tournamentData, seedsSerialized : JSON.stringify(tournamentData.seeds) } );
    });
  });

In your jade template:

script(type='text/javascript')
 var seeds = !{JSON.stringify(tournamentData.teams)};

In your brakets.js REMOVE your var seeds line.

Not tested but it should get you going.

When you say "JavaScript file" I am assuming you mean a client-side javascript file and not a server-side file in Express.

  1. The first way is to construct the client-side javascript file dynamically on each request and add in the tournament data directly into the script.
  2. The second option is to include to the tournament _id on the page and then have your client-side javascript perform an ajax request to the server to get the rest of the tournament data as json
  3. The third is to embed all the data about your tournament directly into the html and then extract it in your client side script

Embedding your tournament data as a JSON string in the templtae

Jade template

div(style="visibility: hidden")#tournamentData
  !{JSON.stringify(tournamentData)}

Client Side Javascript

Now in your in your client-side javascript you can access the text inside the #tournamentData div

$(document).ready(function() {
   // tournament  is now the same as tournmentData in your express route
   var tournamentText = $(#tournamentData).text()
   var tournament = JSON.parse(tournamentText)
   console.log(tournament, tournament)
   $('#tournamentBrackets').bracket({
     init: bracketData
   })
})