Using twix and momentjs in meteor - plugins

I'm trying to put together a small app using meteor, and having a lot of luck. But I can't get the app to use the Twix plugin for momentjs.
Using Meteorite, I added the Momentjs library from Atmosphere, mrt add moment, so no problem there. But there's no twix package in Atmosphere. I used npm to install twix package, but neither meteor no mrt will add twix, responding Package named twix doesn't exist in your meteor installation which I guess makes sense, it being a Nodejs package not a Meteor package. Finally I tried downloading the twix.js file and placing it in different directories, but nothing has worked.
I'm not getting errors with this code:
if (Meteor.isServer) {
Meteor.startup(function () {
var moment = Npm.require('moment');
Npm.require('twix');
});
and I can use the MomentJS library, but not the twix plugin. Writing (within Meteor.isClient)
Template.dayTable.date = function() {
return moment(Session.get('selectedDate')).format("MMM Do YY");
}
works fine, but writing
var t = new moment("1/25/1982 9:30 AM").twix("1/25/1982 1:30 PM");
has the js console tell me Uncaught TypeError: Object [object Object] has no method 'twix'
Is there a secret place I can put the twix.js file for Meteor/MomentJS to use (which seems likely)? Am I not require-ing it correctly? Or what?
Thanks!

Meteor loads javascript in a certain order. See the Meteor docs (search for "load order"). To fix this:
add moment.js to client/lib to ensure it's loaded before twix
add twix.js to the client folder
You can also look into creating a package (which is what Npm.require is intended for) and include that, or rename the files since files are included alphabetically. More info is in the docs.

It's not documented anywhere, but you can also use Twix standalone, like this:
var Twix = Npm.require('twix');
var t = new Twix(firstTime, secondTime);

Related

How to dynamically load a JAR file with Vert.x JavaScript?

Using Vert.x JavaScript (3.8.4), I want to dynamically load a JAR file at runtime. This is necessary because that file might not exist when my Vert.x application gets started. Ideally, I would like to be able to use code like this:
// load custom JAR file
requireJar("path/to/dynamic.jar");
// use class from dynamically loaded package
var instance = new com.mydynamicpackage.MyCustomClass();
How can I achieve this?
You might find this answer to be helpful:
How to access external JAR files from JavaScript using Rhino and Eclipse?
Another approach that is valid would be to provide the jar with other means, i.e. not via a javascript implementation, to check afterwards, if it is available and then deal with the case if it is not.
java.lang.Class.forName( 'com.mydynamicpackage.MyCustomClass' )
This will throw an error, if MyCustomClass does not exist.
Loading jars at runtime might not be a good idea if you cannot determine they are loaded from a not trustworthy source. This is at least true for the java world.
Based on this answer, I have created the following JavaScript function for dynamically loading a class from a JAR file:
var requireJavaClass=(function(){
var method=java.net.URLClassLoader.class.getDeclaredMethod("addURL",java.net.URL.class);
method.setAccessible(true);
var cache={};
var ClassLoader=java.lang.ClassLoader;
var File=java.io.File;
return function(classname,jarpath){
var c=cache[classname];
if (c) return c;
if (jarpath) {
var cl=ClassLoader.getSystemClassLoader();
method.invoke(cl,new File(jarpath).toURI().toURL());
cl.loadClass(classname);
}
return cache[classname]=Java.type(classname);
}
})();
The equivalent to the snippet I posted in the my question would be:
var MyCustomClass=requireJavaClass("com.mydynamicpackage.MyCustomClass","path/to/dynamic.jar");
var instance = new MyCustomClass();
So far, I have only tested this with Vert.x 3.8.5 running in JRE8, i.e. I can't say if this also works in older Vert.x versions or with JRE9+.

trying to access Thunderbird-tabmail does not work

I want to open a new tab with a gloda conversation from inside calendar code.
I receive an error from error console:
window not defined (or document not defined), depending on which of the two I use to Access tabmail:
let tabmail = window.document.getElementById("tabmail");
let tabmail = document.getElementById("tabmail");
The code works fine if the js file is included in an overlay xul-file.
But I want to use it outside of xul in my code.
Somewhere in my calendar code (in my 'addevent'), the same code throws the error.
This code is originally called from a rightclick on an email, but several layers deep into calendar code.
In MDN, I read that window is global? So what do I Need to do to add an tab?
This part works if tabmail is properly referenced:
tabmail.openTab("glodaList", {
collection: queryCollection,
message: aCollection.items[0],
title: tabTitle,
background: false
});
So how do I get a reference for tabmail?
Any help is appreciated.
after trying and looking through code for really some time before posting, it took only ca. 20 minutes to accidentally find the solution after submitting the question..
While browsing mailutils on mxr for something else, I found the solution in some function:
mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
if (mail3PaneWindow) var tabmail = mail3PaneWindow.document.getElementById("tabmail");

Create and modify collections in a package

I'm trying to create a collection within a package (technically within a build plugin):
StaticCollection = new Mongo.Collection(null)
// also the same with Mongo.Collection('static')
StaticCollection.insert({stuff: 'thing'})
But this throws essentially this error:
While loading plugin `compileMarkdownFiles` from package `faichenshing:collection-files`:
packages/compileMarkdownFiles/plugin/compile-md.js:29:1: Mongo is not defined
at Package (packages/compileMarkdownFiles/plugin/compile-md.js:29:1)
at <runJavaScript-268>:121:4
at <runJavaScript-268>:128:3
This didn't work as Meteor.Collection either.
Then I tried to import the mongo collection into my build plugin like this:
Package.registerBuildPlugin({
name: "compileMarkdownFiles",
use: ['spacebars-compiler', 'mongo'],
// etc.
});
as well as in my Package.onUse:
api.use('mongo')
it throws this error:
While loading plugin `compileMarkdownFiles` from package `faichenshing:collection-files`:
packages/ddp/stream_server.js:3:1: __meteor_runtime_config__ is not defined
at self (packages/ddp/stream_server.js:3:1)
at <runJavaScript-83>:694:4
at <runJavaScript-83>:4779:3
No amount of searching for __meteor_runtime_config__ has clarified this problem. It seems completely unrelated.
Questions like this one seem to not run into this problem at all.
The more I think about this the more convinced I am it has something to do with the existence of a build plugin in this code, but the collection definition isn't taking place within registerSourceHandler or anything.

meteor: database is undefined

I'm having some troubles understanding, what i believe is trivial but i can't seem to get my head around it.
I have this publish function in server.js (server only)
Meteor.publish("tikiMainFind", function(){
return tikiDB.find()
})
In app.js (server + client) i'm declaring this mongo collection:
tikiDB = new Mongo.Collection("tiki")
Why is it that this doesn't work in client.js
console.log(tikiDB.find())
//ReferenceError: tikiDB is not defined
Without any idea how you have your app structured, I agree with David Weldon's answer. Check File Load Order to see what order your files are getting loaded.

sails.js setup: How to make a node module available across the sails project (controller / model, etc)?

I just getting started with SailsJS as my first web framework on Node. Let's say I wanna add MomentJS in and use across the app. How to set it up?
you can use the bootstrap.js (in config/)
like:
module.exports.bootstrap = function (cb) {
sails.moment = require('moment');
cb();
};
in all Sails-Files you can use
sails.moment()
now.
If you're trying to include your node_modules into the client side, such as jQuery, AngularJS or one of the various many font libraries, then you can npm install them as normal, but just to be sure in sails you edit your tasks/config/copy.js and add a new block, example:
grunt.config.set('copy', {
dev: {
files: [{
expand:true,
cwd: './node_modules/font-awesome/fonts',
src: ['**/*'],
dest: '.tmp/public/fonts'
}
}
});
LESS can be #imported like normal without being copied around. Other assets will need to be copied as above. If you're using the sails linker then don't forget to add your JS paths to tasks/pipeline.js too (if necessary).
You can read more here:
http://ash.zi.vc/sails/2016/02/02/including-client-side-node-modules-in-my-sails-application/
It's not directly obvious how to sync npm modules to the web accessible directories.
SailsJS is no different to any other NodeJS app. So on top of your (say) Controller.js file, you do
var m = require("moment");
And you're good to go. #mdunisch's method will obviously let you use the moment package throughout your app, without having to do "require" in each file.