How to include JavaScript from a CDN in meteor? - meteor

I'd like to include JS from a CDN in Meteor before including my own client scripts so that the client scripts can depend on it.
...
<script type="text/javascript" src="https://ajax.googleapis.com/..."></script>
...
<script type="text/javascript" src="/client/..."></script>
...
I tried including the script via *.html file and between <head> tags. But it seems that header content from *.html files will always be appended to the end of the HTML header, no matter where I place it in the file hierarchy (e.g. placing the file in a lib folder or sorting it alphabetically before client JS files won't help).
Any ideas how I could include JS from a CDN before client scripts without having to build a smart package?

Assuming you don't need to load these files before the Meteor packages, create a JS file which is loaded before any of the others. Meteor loads files in alphabetical order so it must be the first file loaded. To that end, naming it aaLoadCDN.js should suffice. Dynamically load the CDN scripts by adding a script src element to the document head:
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript'); // optional
script.setAttribute('src', 'url/to/the/cdn/script.js');
document.getElementsByTagName('head')[0].appendChild(script);
Here are some real-world Meteor packages loading scripts from CDNs:
snapsvg
Font-Awesome (CSS).

You can append the script after the template is rendered. So your script will load only after every other line has been loaded. For example if you directly add a jquery plugin to your template html file, you'll get "jquery not found" error. But this approach prevents that:
Template.Main.onRendered(function () {
$('head').append('<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-formhelpers/2.3.0/js/bootstrap-formhelpers.js"></script>');
});

There's also an abandoned package called meteor-external-fileloader that gives an example using Stripe.js. It hasn't been maintained since September 2013, so be careful.

Related

Why html file must go before js file when addFiles in Meteor

I'm creating a meteor package, very simple one like this
api.addFiles(['errors.js', 'errors_list.html', 'errors_list.js'], 'client');
I noticed that if I change above code to
api.addFiles(['errors.js', 'errors_list.js', 'errors_list.html'], 'client');
Meteor says: Template is not defined.
It is very hard to find out what caused this error. And why js file cannot go before html file in addFiles?
When you use Spacebars (the default templating engine), templates are defined in HTML files :
<template name="fooTemplate">
...
</template>
You can then access this template from everywhere else, be it HTML or JS:
<!-- HTML file -->
{{> fooTemplate}}
//JS file
Template.fooTemplate
If you try to do such an access before the template has been created, it will fail.
Meteor packages load files sequentially. This is how you control the load order.
If you try to use a template before it has been defined, it's undefined and will throw an exception when you try to access it (something along the lines of fooTemplate is undefined).
Thus, as in everything in programming, always initialize first and use later.
Put your HTML files before the JS, and you're good to go.

How to handle CSS with meteor?

I am building a test app to learn how to organize multiple files with METEOR.
I have a head.html and inside I have the following link to my custom CSS:
<!-- Custom CSS -->
<link type="text/css" rel="stylesheet" href="/stylesheets/globals/style.css"/>
Very normal, Yet I have trouble to make that working.
Here is my app directory:
-app folder
---client
-----head.html
-----index.html
-----stylesheets
-------globals
---------style.css
I know it seems to be a very basic question but I can not figure it out.
Basically you have 2 ways of inserting CSS in a Meteor project :
Using the Meteor build tool to automatically concatenate and minify all your CSS files living in the client/ directory : in this case you don't need to import your stylesheets using a link tag in the head. This is perfect for vital CSS files that your app should load when started.
Example : put your CSS file under client/stylesheets/globals/style.css and that's it, no need to import it, it's automatically injected in your project by Meteor.
Using the classic way of importing stylesheets in a web application : you can put your CSS files inside the public/ directory and they will be served by your app server. In this case the Meteor build process will be skipped so files won't be concatenated together nor minified. Use this method when you want to lazy load big CSS files only needed in a subpart of your app (for example admin section styling).
Example : put your minified CSS file under public/stylesheets/admin/style.css, and use something like iron:router to load the CSS file when hitting the admin route.
Router.route("/admin", {
// onRun hooks executed only once
onRun: function(){
// create a link taf holding a reference to our publicly served CSS file
var link=$("<link>",{
rel: "stylesheet",
href: "/stylesheets/admin/style.css"
});
// append to the head tag
$("head").append(link);
}
});

Meteor : Load javascript file but don't execute. Execute on demand

I want to load a javascript file but do not want a "<script type="text/javascript" src="..."></script>" tag created for it.
I am using iron-router. So, I want this js file to execute in 'onAfterAction' hook, i.e. after the template is loaded.
I am thinking of following ways to do this:
One way is place this file in "public" directory and use '$.getScript' function to load and execute this on demand. But, these files won't get minified and compacted to one file. Also, this will need another fetch on the n/w.
The other way is to create a package and include this file in the package. But, then I will have to enclose the whole file in a function and 'export' this function in package. And execute this function on demand.
The third way is to put these files in 'client' directory and call "$.getScript('/client/js/...". But, the js file would get executed twice as a "<script type="text/javascript" src="..."></script>" tag will be created for it..
Is there a better way of doing this so that the file is locally available and can be executed on demand?
From what I understand about Meteor. All JavaScript executes without having to load a <script></script> tags. Depending on how you seem okay with it being a public script, I'd put it in the client folder and utilize the Template.[your-template-name].rendered in some way where you can load that particular script after the template is rendered.
http://docs.meteor.com/#/basic/Template-onRendered

Meteor not server .JS for <script> in <template>

In app.html:
<body>
{{> index}}
</body>
<template name="index">
...
<script src="https://www.gstatic.com/swiffy/v5.2/runtime.js" type="text/javascript" />
<script src="animation.js" type="text/javascript" />
...
</template>
animation.js is inside /public along with all the html and jpeg's etc for a static site.
When I navigate to the app root, it all works right except that the Swiffy animation just doesn't show up. Perhaps something to do with Meteor not just serving JS from the /public directory? How can I fix this?
When I navigate to the very same code stored as /public/index.html, the animation shows up.
Note: Swiffy is just a way to automatically convert Flash animations into .JS that is run by the Swiffy runtime.
Client JS libraries should be placed in the client directory. This will make it available to meteor for inclusion into the minified app.
For more information see http://docs.meteor.com/#structuringyourapp
You can put your library to /client/compatibility directory. But you put there, all pages include your library. If you want some pages include your javascript you must use ext package. For example https://atmosphere.meteor.com/package/external-file-loader

Integrate CKEditor in Meteor

I'm trying to use CKEditor in a meteor application:
My attemps:
Put CKEditor folder with all the files (js, css, lang, plugins and skins) in the public folder, include the reference to the javascript file (ckeditor.js) in the header and use the appropiate class in textarea elements. Failed because the editor only works if the textarea is in the body (in any template the textarea control remains unmodified).
Put the javascript files (ckeditor.js, config.js, styles.js) in client/lib/compatibility folder and the remaining files in the public folder. This time the application cant locate the files (skins, plugins, ...) because is looking for localhost:3000/client/lib/compatibility/ckeditor/ ...
Has anybody make this integration works before?
I got this working and wanted to post a solution for future visitors. First, you need to put everything from the CKEDITOR build download in the public folder. CKEDITOR comes with all sorts of stuff and references everything based on relative directories.
Your public folder should have a directory named ckeditor it should contain contain the following files and folders:
adapters
lang
plugins
skins
ckeditor.js
config.js
contents.css
styles.js
In your primary layout file reference CKEDITOR like so:
<head>
<script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/ckeditor/adapters/jquery.js"></script>
</head>
In your template:
<template name="yourTemplate">
<textarea id="content" name="content"></textarea>
</template>
Finally, in the rendered function of your template:
Template.yourTemplate.rendered = function() {
$('#content').ckeditor();
};
Normally, you would say this.$('#content').ckeditor() but that doesn't work because CKEDITOR is in your public folder. As a result, you need to the global reference to the #content element.
Put only the CKEditor files that you would've included in <head> inside a folder in client/lib, i.e. client/lib/ckeditor. That's all you need to do to get them served to the client: there's no need to reference anything in any <head> or anything like that. All .js and .css files that Meteor finds inside client are automatically concatenated and served to the client. This applies to any client-side library, not just CKEditor.
The next thing you need to do is cause CKEditor to be initialized on the pages that use it. Say you have a template called edit with a textarea with an ID of editor. And say you're also loading the CKEditor jQuery Adapter. Inside a JavaScript file within client, put:
Template.edit.rendered = function() {
$('#editor').ckeditor();
}
The key here is that the initialization happens after the textarea editor exists and is ready, because this code is executed after the edit template is fully rendered. It will be reexecuted anytime edit is rerendered. Any other client-side library is included and initialized similarly.
EDIT Image files referenced via .css are a pain in Meteor. The "proper" way to deal with them is to put them all under the folder public, in this case for example public/ckeditor. Then edit the CKEditor .css files so that all references to image URLs point to your new folder at the root, i.e. /ckeditor/image1.png etc. (leave out "public").

Resources