Why can't I access JS functions made in separate JS files in my html when using Meteor - meteor

Meteor says when you write some javascript in a JS file, every file automatically has access to it everywhere in the app, but when I write a function in a a separate file like that, I just get a console error saying that function could not be found when I call it in html. The only way I can get it to work is by writing the JS in the html file but I want to keep the languages separate. Any idea on what the problem is?
code:
html in one file:
<button onclick="dylan()"></button>
js in another file:
function dylan(){
console.log("hello");
}
the problem is, when I click the button, it says dylan is not a function.

Meteor docs do not spell this out but every individual javascript file is wrapped into a closure:
(function() { //the file content // })()
so all functions in a given file have their own scope.
Functions defined in a js file in Meteor normally only have file scope - that is, any object in that file can refer to them.
If you want to define a global function, create a global variable:
dylan = function(){
...
}
Note the absence of let or var which would restrict the function to file scope.
Now you can use this global in your onclick handler.
Note however, that normally in Meteor, you would define an event handler at the template level, ex:
Template.myTemplate.events({
'click button'(){
...your code here
}
});
As opposed to referring to event handlers in your html directly.

The purpose of using Meteor is not met if you do not harness the wonderfull features such as
Template.X.events({});,
Template.X.helpers({}); and also
Template.registerHelpers({});
You can write your desired code in below way:
Template.template_name.events({
'click .button_class' : function() {
console.log("Hello");
}
});
//HTML
<button class="button_class"></button>
If that click event has to be used in more than 1 HTML then you can use registerHelper methods than template click events.
Template.registerHelpers('dylan' : function() {
console.log("Hello");
});
//html
<button onclick="dylan"></button>

To access dylan(), you must first load the script file that contains that function into the html document.
You can do this by adding <script src="myfile.js"></script> anywhere before the button. (replace myfile with the name of your script)
Once loaded, <button onClick="dylan()"></button> will work!

Related

Reinitialize library when new data is available

I'm currently developing a Meteor application where I use the video.js-Library.
I have the following template:
template(name='foo')
.video.embed-responsive.embed-responsive-16by9
with richMediaContent
video#video.video-js.vjs-default-skin.vjs-big-play-centered(controls='' preload='auto')
source(src='{{video.videoUrl}}' type='video/mp4')
p.vjs-no-js {{i18n 'videoTagNotSupported'}}
Initializing the video.js-Library after the template is rendered works fine.
Template.foo.onRendered ->
videojs document.getElementsByClassName('video-js')[0], {}
But the videojs-Library is not reinitialized if the same template is rendered with a different video (with a different richMediaContent).
I've already tried to move the video-Part in an own template and included it in the foo-Template so that the onRendered-Call should get called every time a new video is loaded. But this doesn't seem to work.
Do you have any idea how I can reinitialize the library if the video changes?
Thanks in advance!
New answer
Indeed, when your route changes but uses the same template, the said template does not get rendered again, therefore your js plugin call will not trigger a second time. What you can do instead is call your js plugin in an onAfterAction call, within your route definition:
Router.route('/video/:_id', {
name: 'video_page',
template: 'foo',
// ...
onAfterAction: function () {
videojs document.getElementsByClassName('video-js')[0], {}
}
});
Previous answer
I think you are looking for the almighty this.autorun. At the end of your onRendered function, it should look like this (I type it in pure javascript)
this.autorun(function () {
var video = Session.get("video"); // reactive data
videojs document.getElementsByClassName('video-js')[0], {}
});
The idea is that the first line must include, within the autorun function, a way to get your reactive data. In that case, I use the Session which is reactive. Collections are also reactive, so another way would be something like Videos.findOne();. This will depend on how you get that video element.
What this does is that any time the reactive data changes, the callback for this.autorun will run again, and your video plugin will be reset.

Meteor how to create global event?

How can I create a event which will run on any page?
When creating a helper on the main layout template it doesn't work.
Template.layout.events
'click': ->
console.log "you clicked on the site"
You can use Template.body.events instead of Template.layout.events to create events for any template that will apply on anything in <body>
Docs: http://docs.meteor.com/#/full/template_body
you need a special package to create a global event.
install
meteor add gwendall:body-events
and you can use the events from Template.body.events in every template
example
Template.body.events({
'click .myClass':function(){
alert("BODY EVENT");
}
});
or if you like the new syntax
Template.body.events({
'click .myClass'(){
alert("BODY EVENT");
}
});
Neither answer currently is 'wrong' per se, they just work in different situations:
Event maps, Template.body.events({}), on Template.body do not get applied to elements added to the body via Blaze.render, Iron-Router, Flow-Router jQuery, or the DOM API, or to the body element itself. If you are using the above you will need to add the package body-events to be able to utilise the event map on body using the command below:
meteor add gwendall:body-events
If you are not using any of the template rendering packages above then you can directly add to the body event map using the code below:
Template.body.events({
'click': function () {
alert("clicked on the page. oh yeah!");
}
});
nb. it seems the latest version of Blaze allows directly adding event maps to body

Meteor: Proper way to add 'confirm delete' modal

I want to create a confirm delete popup with Bootstrap 3. Is there any good comprehensive examples how to build one. I am very new to Meteor.
Use whatever example from Codrops, etc, just remember put the JSCode inside a
Template.nameTemplate.rendered = function() {}
So thats telling meteor to load that jscode, when the template has beed rendered and it can load any modal, etc...
So just follow whatever example you want, and just put whatever jQuery plugin etc, inside Rendered function
Also in some case the rendered its not enough, you need to use too,you can see timer docs here, anyways if you are having bad time, feel free to upload, some meteorPad, free nitrous box o repo on github and i can help you (i have a bad time with those modals on meteor to, they are a little trickys =p)
update answer
try to add meteor add iron:router, and on the client /app.js
Router.route('/', function () {
this.render('leaderboard');
});
And keep the same rendered like this.
Template.deleteBtn.rendered = function(){
$('.open-modal').on('click', function(e){
$('#confirm').modal()
.on('click', '#delete', function (e) {
// Remove selected player
Players.remove(Session.get("selectedPlayer"));
});
});
}
UPDATE
So using the peppelg:bootstrap-3-modalPackage, you can easy do the follow
First Create a template with the modal content
<template name="modal">
<!-- Modal Stuff -->
</template>
and easy call it on a Event handler.
Template.example.events({
'click #exampleButton':function(){
Modal.show('modal')
}
})
Now back to this example check this meteorpad from line 1-23 on app.'s and 41-62 on main.html

Template.myTemplate.rendered in Meteor?

What is the use of Template.myTemplate.rendered in Meteor?. I had studied the document but i didn't understand the exact functionality.The document says Provide a callback when an instance of a template is rendered. What is the meaning of instance of a template is rendered.Can you please suggest me with an example?
When the callback is fired, an instance of the template has been rendered (added to the document). It can be useful if you for example want to manipulate the elements in the template through the use of a JavaScript library, for example CodeMirror, as I used in one of my projects. For example:
<template name="test">
<textarea></textarea>
</template>
Template.test.rendered = function(){
// Make the textarea highlight the code (kind of).
var myCodeMirror = CodeMirror.fromTextArea(this.find('textarea'))
}

Is it mandatory to write ready function every time while doing jquery?

Is it mandatory to write $(document).ready(function () {... }) every time ?
Can't we do it without this line?
The reason for placing your code inside this function is that it will get called once the DOM has loaded - meaning that all the elements are accessible. Calling jQuery selectors without this function means that the elements have not necessarily been loaded into the DOM and might not be accessible (and you'll see weird results or nothing at all from your code).
So in essense, yes, it is necessary.
$(document).ready makes sure your code runs when the document is ready (i.e. fully loaded). If you don't need to interact with the document, you don't need this. If you put your Javascript at the end of the document, you probably don't need it either. You should put your code into a function () { } though to namespace it either way.
$(document).ready means the code inside this box will be executed once the all document is ready (loaded). It is considered as safe programming but not mandatory.
For example you call a function in script tag do_something(); and this function is in a js file which is not loaded yet then you will get javascript error.
If you put function like this
$(document).ready(function () {
do_something();
});
you are making sure that when function get called all js files will be there to server.
If you don't use that line, and just include the javascript in your body, it will execute as soon as it's loaded. If it's trying to act on DOM elements that have not yet loaded, unpredictable results will occur.... better to be safe than sorry.
jQuery's ready() function is run after the page's content is loaded. This is relatively equivalent to using <body onload="function1();function2();">
If you want to call multiple functions when the page is done loading, you can do the following:
$(document).ready(function() {
function1();
function2();
});
In order to use javascript, you must call it somewhere. This can be in body "onload", jQuery's ready() function, or an event, like a mouse click event.
No you don't always have to do this. You only use it if you want to make sure whatever is inside the ready function loads before the page is displayed in the browser. If you do not care to load the script before page load, then you can just put the script at the end of the page before the closing body tag.
Also As a shortcut to $(document).ready(function () you can do $(function()

Resources