Search code examples
javascriptjqueryhtmlmeteormeteor-blaze

How to include raw JavaScript code in a Meteor app


I have a javascript that creates an animation on an html page. Outside the Meteor project the animation works perfect as it is just a .js file included in an html file. How can I make it work on Meteor though? The javascript file appears to not run at all (it's not doing anything). Can Meteor include raw javscript files? And if so how? The file is pure JavaScript, no helpers or anything that defines the Meteor structure.

missionPage.js

var TxtRotate = function(el, toRotate, period) {
    this.toRotate = toRotate;
    this.el = el;
    this.loopNum = 0;
    this.period = parseInt(period, 10) || 2000;
    this.txt = '';
    this.tick();
    this.isDeleting = false;
 };

 TxtRotate.prototype.tick = function() {
    var i = this.loopNum % this.toRotate.length;
    var fullTxt = this.toRotate[i];
    if (this.isDeleting) {
      this.txt = fullTxt.substring(0, this.txt.length - 1);
    } else {
      this.txt = fullTxt.substring(0, this.txt.length + 1);
    }
    this.el.innerHTML = '<span class="wrap">'+this.txt+'</span>';
    var that = this;
    var delta = 300 - Math.random() * 100;
    if (this.isDeleting) { delta /= 2; }
    if (!this.isDeleting && this.txt === fullTxt) {
      delta = this.period;
      this.isDeleting = true;
    } else if (this.isDeleting && this.txt === '') {
      this.isDeleting = false;
      this.loopNum++;
      delta = 500;
    }

  setTimeout(function() {
  that.tick();
  }, delta);
  };

  window.onload= function() {
  console.log('I m here');
  var elements = document.getElementsByClassName('txt-rotate');
  console.log(elements);
      for (var i=0; i<elements.length; i++) {
      var toRotate = elements[i].getAttribute('data-rotate');
      var period = elements[i].getAttribute('data-period');
      if (toRotate) {
      new TxtRotate(elements[i], JSON.parse(toRotate), period);
    }
    }
// INJECT CSS
    var css = document.createElement("style");
    css.type = "text/css";
    css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 
  }";
    document.body.appendChild(css);
  };

missionPage.html

<template name="missionPage">
  <div class="ui center aligned container">
    <h3>Our story</h3>
    <h1>This website is
      <span
     class="txt-rotate"
     data-period="2000"
     data-rotate='[ "not just the website", "simple.", "pure JS.", 
 "pretty.", "fun!" ]'></span>
    </h1>
  </div>
</template>

Solution

  • Have you been reading the Guide to Meteor, specifically the section on app structure? If not, I would start there.

    To answer your questions:

    Can Meteor include raw JavaScript files?

    Yes.

    And if so how?

    Any number of ways. You can directly import it:

    import './txtRotate.js';
    

    Or you can put it in the client/compatibility directory and it will be loaded and executed before other JS files.

    In the end, your missionPage.js file should only have MissionPage Template related code in it, not the TxtRotate code. Move TxtRotate to it's own file (excluding the window.onload part), import it inside missionPage.js, and initialize it when the Template is rendered:

    import { Template } from 'meteor/templating';
    import './txtRotate.js';
    
    Template.missionPage.onRendered(function() {
      this.$('.txt-rotate').each(function(i, element) {
        var toRotate = $(element).data('rotate');
        var period = $(element).data('period');
    
        if (toRotate) {
          new TxtRotate(this.get(0), JSON.parse(toRotate), period);
        }
      });
    });
    

    Another option you have is changing your TxtRotate function to be a reusable Blaze Component instead of a standalone function. Something like:

    <template name="missionPage">
      <div class="ui center aligned container">
        <h3>Our story</h3>
        <h1>This website is {{> TxtRotate period="2000" rotate=words}}</h1>
      </div>
    </template>
    

    Where words would be defined in a template helper.