convert a javascript library to AMD - javascript

I'm trying to use a library -- Google's libphonenumber -- in my require application that is not AMD. What is the best way to consume this? I know I can create a module like this:
define(['module'], function (module) {
// insert and return library code here.
});
But that doesn't seem great. It seems like I would have to refactor some of their code to get that working (e.g., turn it all into an object and return that object). I see a lot of libraries using a different pattern where they use an immediately invoked function that defines the module on the window object and returns it.
(function() {
var phoneformat = {};
window.phoneformat = phoneformat;
if (typeof window.define === "function" && window.define.amd) {
window.define("phoneformat", [], function() {
return window.phoneformat;
});
}
})();
** UPDATE **
Is there any reason not to just do this?
define(['lib/phoneformatter'], function(phoneformatter) {
});
I get access to all of my methods but now it seems they are global because I did not wrap the library in a define...

Use RequireJS's shim. It'll look something like this
requirejs.config({
shim: {
'libphonenumber': {
exports: 'libphonenumber' // Might not apply for this library
}
}
});
This will load libphonenumber and put its variables in the global scope

This ended up working for me:
define(['module'], function (module) {
// insert and return library code here.
});
I am not entirely sure why 'module' was necessary. But it doesn't work without it. Also, I just returned an object and attached functions to it like so:
return {
countryForE164Number: countryForE164Number,
nextFunction: nextFunction,
// more functions as needed.
}
There is not much in the way of documentation for using 'module' but from what I can ascertain: Module is a special dependency that is processed by requireJS core. It gives you information about the module ID and location of the current module. So it is entirely possible that I messed up the paths in config.

Related

The way to use custom method everywhere without requiring the module everywhere

I am using Node.js. I defined a custom method to the String obj like this:
if (!String.prototype.myMethod) {
String.prototype.myMethod= function () {
//do something
return this;
};
}
I found that myMethod maybe used in many different files, so that I have to require the file where this piece of code in. Is there any way that does the many 'requires' ?
Don't do that.
Node is intentionally designed in a module pattern, where each module gets it's own scope to run in and without polluting the global variables. This very intentional and very important.
https://nodejs.org/api/modules.html#modules_the_module_wrapper

load module in requirejs only in browser, not in nodejs

I wrote modules for both browser and nodejs using requirejs.
Everything works fine, but I want to include a module just for the browser, not for node as I don't need it and it would not work in node. (It's just a fancy design library for the browser).
My code looks like this:
define([
'requirement',
'libs/fancy'
], function(Requirement, fancy) {
// do stuff
});
fancy is the lib that I don't want in node. So I could write a workaround like this:
if (typeof window !== 'undefined') { // cheap detection of browser/node
define([
'requirement',
'libs/fancy'
], start);
} else {
define([
'requirement'
], start);
}
function start(Requirement, Fancy) {
// do stuff
}
But obviously this is ugly. Does anyone know a better way to do it?
-- EDIT 1:
var requirements = ['requirement'];
if (typeof window !== 'undefined') {
requirement.push('libs/fancy');
}
define(requirements, function(Requirement, Fancy) {
// do stuff
}
Still not perfect
I've sometimes used the second method you show of creating an array of dependencies on which I push depending on what I need.
There's another method, however, that I've used when I don't want to modify the list of dependencies. Presumably the code inside your module will have to work with an undefined value for Fancy. So you could use something like what follows. The idea is to configure RequireJS to load a module that returns an undefined value when loaded. This way you don't need to modify your dependency list. It just needs to be able to handle a case where Fancy is undefined.
var requirejs = require("requirejs");
// Create a fake module that we name immediately as "undefined".
requirejs.define("undefined", [], function () { return undefined; });
var req = requirejs.config({
map: {
// Make it so that all requests for `foo` load `undefined` instead.
"*": {
foo: "undefined"
}
}
});
req(["foo"], function (foo) {
console.log(foo);
});
The example above maps foo to undefined so when console.log executes, the value on the console is undefined. In your own code you'd map libs/fancy to undefined.
A variation on this method would be to have the undefined module return an object which shows the same interface as the real library but does nothing. This would avoid having to test whether Fancy is defined or not inside your module. I'd call the fake module something else than undefined though. Maybe something like fake-fancy.

How to pass element parameter to require.js define call?

I have a page that is split into "widgets" that are loaded dynamically on the fly - JS with require.js, HTML & CSS with custom JS. This is especially handy because it allows each widget define it's own JS requirements.
For example:
define(['jquery', 'mustache'], function($, Mustache) { ...
However, in order to target the widget JS functionality into correct element, I need to pass the widgets root element to the javascript, that is loaded with require.js, which is something require.js doesn't support... :/
What I currently have is something like this, where the define call returns an function that does the rendering...
// Example.js
define(['jquery'], function($) {
return function($el) {
// Render the widget here to "$el"
$el.html('asdsadads');
}
});
... which is run by the require call...
require(['js/example'], function(render) { render($el); });
... which works ok with simple structures but with more complex widgets, the init function starts to bloat, which makes it less pretty and harder to read (also, more prone to bugs).
The optimal situation would be something like this...
// Example.js
define(['jquery'], function($) {
if() { // Check for route and/or other modifiers (is logged in etc)
$el.html('asdasdasd');
} else {
$el.html('qwerty');
}
});
...where the actual functionality is directly inside the define call. Unfortunately, as far as I understand, there is no way to pass the element with the require call, like so...
define(['jquery'], function($, $el) {
So, what is a man to do? Is there a pattern that I could use to somehow pass the element cleanly to the define call? Or do I have to resort into this ugly callback jungle?
The idea of a define block is to return a class or function that can be used in another part of your code. This encourages and re-usable, DRY, modular style of coding.
It doesn't make sense for the define module to be aware of $el at the point of creation. What does make sense is that you return a class that gets instantiated with the $el. This way your module is reusable and you return the burden of control to your application, and not the module itself.
Simple example of a module and its use:
define(['jquery'], function($) {
var MyClass = function(args){
this.initView(args.$el);
}
MyClass.prototype.initView($el){
//init your view
}
return MyClass;
});
Then when you can use this module like this:
define(['path/to/myClass'], function(MyClass) {
var myView = new MyClass({$el: $('.my-selector')}),
myOtherView = new MyClass({$el: $('.my-other-selector')});
});

Strange behavior with RequireJS using CommonJS sintax

I'm a strange behavior with RequireJS using the CommonJS syntax. I'll try to explain as better as possible the context I'm working on.
I have a JS file, called Controller.js, that registers for input events (a click) and uses a series of if statement to perform the correct action. A typical if statement block can be the following.
if(something) {
// RequireJS syntax here
} else if(other) { // ...
To implement the RequireJS syntax I tried two different patterns. The first one is the following. This is the standard way to load modules.
if(something) {
require(['CompositeView'], function(CompositeView) {
// using CompositeView here...
});
} else if(other) { // ...
The second, instead, uses the CommonJS syntax like
if(something) {
var CompositeView = require('CompositeView');
// using CompositeView here...
} else if(other) { // ...
Both pattern works as expected but I've noticed a strange behavior through Firebug (the same happens with Chrome tool). In particular, using the second one, the CompositeView file is already downloaded even if I haven't follow the branch that manages the specific action in response to something condition. On the contrary, with the first solution the file is downloaded when requested.
Am I missing something? Is it due to variable hoisting?
This is a limitation of the support for CommonJS-style require. The documentation explains that something like this:
define(function (require) {
var dependency1 = require('dependency1'),
dependency2 = require('dependency2');
return function () {};
});
is translated by RequireJS to:
define(['require', 'dependency1', 'dependency2'], function (require) {
var dependency1 = require('dependency1'),
dependency2 = require('dependency2');
return function () {};
});
Note how the arguments to the 2 require calls become part of the array passed to define.
What you say you observed is consistent with RequireJS reaching inside the if and pulling the required module up to the define so that it is always loaded even if the branch is not taken. The only way to prevents RequireJS from always loading your module is what you've already discovered: you have to use require with a callback.

Javascript - accessing namespace in different files

I can do this in node.js
var module = require('../path/module')
module.functionname()
So I thought I'd like to do that in client side Javascript to organize things slightly.
So each of my files now has a namespace. So say login.js has a namespace login.
My question is, what's the best way in ECMAScript 5 to implement something alongs these lines?
What you are trying to achieve can be done with AMDs (asynchronous module definitions). Check out RequireJS for that: http://requirejs.org/
With Require.js you can basically define a set of dependencies, let them get loaded asynchronously and execute code once all stuff was loaded nicely:
require(['dependency1.js', 'dependency2.js'], function(dep1, dep2) {
console.log(dep1.functionname())
})
The dependency will then declare it's functionalities with require's define method:
define(['a/possible/dependency.js'], function() {
return {
functionname: function() { return 1 }
}
})

Categories

Resources