Search code examples
javascriptmeteoriron-router

I am trying to build a map selection that only lets you enter a url when a choice is made


I am using Meteor and Iron Router, most things are working, I have successfully got the page to redirect back to home when visiting /spirit, however I want the redirect to stop working when a selection on the map is made.

I may not be approaching this correctly. You will see below in the BC1 click function what I want to happen.

Here is my MAP.js code below

function map(){
  Template.map.rendered = function(){
    var s = Snap("#map");

  //  var snap = Snap(912,912);






    Snap.load("/map.svg", function (f) {

      var el = f.select("path#Fill-65");//Alberta

      var BC = f.selectAll("path#Fill-112 , path#Fill-94");// All BC

      var BC1 = f.select("path#Fill-112");// BC 1

      var BC2 = f.select("path#Fill-94");//BC 2

      var SK = f.select("path#Fill-114");//Saskatchewan

      var MB = f.select("path#Fill-117");//MANITOBA

      var QB = f.select("path#Fill-116");//QUEBEC

      var ON = f.select("path#Fill-120");//ONTARIO

      var T1 = f.select("path#Fill-115");//T1








      var filterMap = s.paper.filter(Snap.filter.shadow(-2, 0, 3, '#000', '0.5'));

      var filterMapNone = s.paper.filter(Snap.filter.shadow(0, 0, 0));

      BC1.hover(function(){
        allBcOn();
      }, function() {
        allBcOff();
      });


      BC1 .click(function(){
        alert("Enter You West Coaster");
        enter = "false";
        /////SEND TO NEXT PAGE//////
      });


      function allBcOn(){
        BC.forEach( function(elem,i) {
           elem.animate({fill: "#fff"},500);
           elem.attr({filter: filterMap });
        });
      }

      function allBcOff(){
        BC.forEach( function(elem,i) {
           elem.animate({fill: "#C2C2C2"},500);
           elem.attr({filter: undefined });
        });
      }




      el.hover(function(){
        //el.attr({fill: "#000"});
        el.animate({fill: "#fff"},500);
        el.attr({filter: filterMap });
      }, function() {
         el.attr({filter: undefined });
         el.animate({fill: "#C2C2C2"},500);

      });

      SK.hover(function(){
        //el.attr({fill: "#000"});
        SK.animate({fill: "#fff"},500);
        SK.attr({filter: filterMap });
      }, function() {
         SK.attr({filter: undefined });
         SK.animate({fill: "#C2C2C2"},500);

      });

      MB.hover(function(){
        //el.attr({fill: "#000"});
        MB.animate({fill: "#fff"},500);
        MB.attr({filter: filterMap });
      }, function() {
         MB.attr({filter: undefined });
         MB.animate({fill: "#C2C2C2"},500);

      });

      QB.hover(function(){
        //el.attr({fill: "#000"});
        QB.animate({fill: "#fff"},500);
        QB.attr({filter: filterMap });
      }, function() {
         QB.attr({filter: undefined });
         QB.animate({fill: "#C2C2C2"},500);

      });

      ON.hover(function(){
        //el.attr({fill: "#000"});
        ON.animate({fill: "#fff"},500);
        ON.attr({filter: filterMap });
      }, function() {
         ON.attr({filter: undefined });
         ON.animate({fill: "#C2C2C2"},500);

      });

      T1.hover(function(){
        //el.attr({fill: "#000"});
        T1.animate({fill: "#fff"},500);
        T1.attr({filter: filterMap });
      }, function() {
         T1.attr({filter: undefined });
         T1.animate({fill: "#C2C2C2"},500);

      });

      g = f.select("g");

      s.append(g);


    });
  }

**

UPDATE

**

This is my new code. For Iron Router. I dont know where to put the map.js click function for it to work, and when I visit /spirit I get the error below the new code. The /sprit page should send you back to the home page unless you have made a click action on the bcClick.

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',

  waitOn: function() { return Meteor.subscribe('posts'); }
});

Router.map(function() {
  this.route('home', {path: '/'});
  this.route('postsList', {path: '/spirit'});
  this.route('postPage', {
    path: '/spirit/:_id',
    data: function() { return Posts.findOne(this.params._id); }
  });
  this.route('login', {path: '/login'});
});


Router.onBeforeAction('loading');
Router.onBeforeAction('dataNotFound', {only: 'postPage'}); //Show all data when post ID is oncorrect in URL
Router.onBeforeAction(function() {
    if (Session.get("enter") === true) {
        this.render('home');
    } else {
        this.next();
    }
}, { only: ['postsList'] });

Error

Exception from Tracker recompute function: undefined is not a function
TypeError: undefined is not a function
    at Router.onBeforeAction.only (http://localhost:3000/lib/router.js?4e5fa4c0e6dac39de81308142d50f13543d19152:26:14)
    at RouteController.runHooks (http://localhost:3000/packages/iron_router.js?da7f2ac81c3fd9daebf49ce9a6980a54caa1dc17:843:16)
    at http://localhost:3000/packages/iron_router.js?da7f2ac81c3fd9daebf49ce9a6980a54caa1dc17:2302:14
    at Tracker.Computation._compute (http://localhost:3000/packages/tracker.js?192a05cc46b867dadbe8bf90dd961f6f8fd1574f:288:36)
    at Tracker.Computation._recompute (http://localhost:3000/packages/tracker.js?192a05cc46b867dadbe8bf90dd961f6f8fd1574f:302:14)
    at Tracker.flush (http://localhost:3000/packages/tracker.js?192a05cc46b867dadbe8bf90dd961f6f8fd1574f:430:14) 

UPDATE NUMERO TWO

I have a semi working example and router code the way I was expecting. My only issue is when visiting/spirit a refresh redirects you, I want the browser session to remember when the user has clicked the link and allow after the first click to view the page antytime.

You can visit the site here to see what I mean.

Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',

  waitOn: function() { return Meteor.subscribe('posts'); }
});

Router.map(function() {
  this.route('homePage', {path: '/'});
  this.route('postsList', {path: '/spirit'});
  this.route('postPage', {
    path: '/spirit/:_id',
    data: function() { return Posts.findOne(this.params._id); }
  });
  this.route('login', {path: '/login'});
  this.route('landing', {path: '/landing'});
});

Router.onBeforeAction('loading');
Router.onBeforeAction('dataNotFound', {only: 'postPage'}); //Show all data when post ID is oncorrect in URL
Router.onBeforeAction(function(){


  var enter = Session.get("enter");
  if (typeof enter != "undefined" && enter === true) {
    alert("welcome");
    this.render('postsList')
  } else {
    this.redirect('homePage');

  }


}, {only: 'postsList'}); //Show all data when post ID is oncorrect in URL

if (Meteor.isClient) {
  // counter starts at 0
  //Session.setDefault("counter", 0);

  Template.homePage.events({
    'click a': function () {
      // increment the counter when button is clicked
      Session.set("enter", true);
    }
  });
}

Solution

  • Yes, you should rewrite that code to make full use of Iron Router onBeforeAction.

    Here's some example code that you might want to use as a reference. I haven't tested it though. Here's the relevant part of the router:

    Router.route('/', function() {
        this.render('home');
    });
    
    Router.route('/spirit', function() {
        this.render('postsList');
    });
    
    Router.onBeforeAction(function() {
        if (Session.get("enter") === true) {
            this.render('home');
        } else {
            this.next();
        }
    }, { only: ['postsList'] });
    

    And in your BC event you should do something like:

    BC1 .click(function(){
        alert("Enter You West Coaster");
        Session.set('enter', false);
        /////SEND TO NEXT PAGE//////
    });
    

    This should give you a pointer at how you should structure the routing.

    UPDATE

    I've reduced your problem to an example. Try this out:

    meteor-test-map.html

    <head>
      <title>meteor-test-map</title>
    </head>
    
    <body>
    </body>
    
    <template name="layout">
    Main layout
      {{> yield}}
    </template>
    
    <template name="postsList">
    Posts list
    <button>Click Me</button>
    </template>
    
    <template name="spirit">
    Spirit
    </template>
    
    <template name="home">
    Home
    </template>
    
    <template name="loading">
    Loading
    </template>
    

    meteor-test-map.js

    Router.configure({
      layoutTemplate: 'layout',
      loadingTemplate: 'loading',
      notFoundTemplate: 'notFound',
    
      waitOn: function() { return Meteor.subscribe('posts'); }
    });
    
    Router.map(function() {
      this.route('home', {path: '/'});
      this.route('postsList', {path: '/spirit'});
      this.route('postPage', {
        path: '/spirit/:_id',
        data: function() { return Posts.findOne(this.params._id); }
      });
      this.route('login', {path: '/login'});
    });
    
    Router.onBeforeAction('loading');
    Router.onBeforeAction('dataNotFound', {only: 'postPage'}); //Show all data when post ID is oncorrect in URL
    
    Router.onBeforeAction(function() {
        var enter = Session.get("enter");
        if (typeof enter != "undefined" && enter === true) {
            this.render('home');
        } else {
            this.next();
        }
    }, { only: ['postsList'] });
    
    
    Posts = new Meteor.Collection("posts");
    
    if (Meteor.isClient) {
      // counter starts at 0
      Session.setDefault("counter", 0);
    
      Template.postsList.events({
        'click button': function () {
          // increment the counter when button is clicked
          Session.set("enter", true);
        }
      });
    }
    
    if (Meteor.isServer) {
      Meteor.startup(function () {
        // code to run on server at startup
      });
    
      Meteor.publish("posts", function() {
        return Posts.find();
      });
    }