Requirejs add arguments to the script element - requirejs

is it possible to add arguments to the sctipt element
e.g.
<script
...
src="XX.js"
></script>
i want to add the argument hello="world" so this is added to the page:
<script
...
src="XX.js"
hallo="welt"
></script>
Reason: I have a js library (aloha-editor) which depends on a parameter for loading it's plugins (and the main functionallity is actuall in a plugin). However I only want to load the plugin when the user want's to edit and requirejs is the best choice since it is used at other parts in the application.

If you are wrapping the aloha script in a define function you could pass arguments like this (link):
//in main appfile
require.config({
'config': {
'aloha': {
src: "XX.js",
hallo: "welt"
}
}
});
//and in the aloha file
define(['module'], function (module) {
var src = module.config().src,
hallo = module.config().hallo;
... // the aloha code
});
There was also an alternative "simplified" syntax in the docs.
Edit: Maybe I misunderstood the question, if you where asking if it's possible to add html attributes to a script tag already on the page: <script src='' data-src='xx.js' data-hallo='welt'></script> is the new html5 syntax for adding custom attributes to tags, everything preceded by data- is correct syntax.

Related

not able to load jquery via require [duplicate]

I'm getting this error when I browse my webapp for the first time (usually in a browser with disabled cache).
Error: Mismatched anonymous define() module: function (require) {
HTML:
<html>
.
.
.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script> var require = { urlArgs: "v=0.4.1.32" }; </script>
<script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
<script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
</body>
</html>
JS:
$(function () {
define(function (require) {
// do something
});
});
Anyone know exactly what this error means and why its happening?
source file, a short discussion about it in the github issues page
Like AlienWebguy said, per the docs, require.js can blow up if
You have an anonymous define ("modules that call define() with no string ID") in its own script tag (I assume actually they mean anywhere in global scope)
You have modules that have conflicting names
You use loader plugins or anonymous modules but don't use require.js's optimizer to bundle them
I had this problem while including bundles built with browserify alongside require.js modules. The solution was to either:
A. load the non-require.js standalone bundles in script tags before require.js is loaded, or
B. load them using require.js (instead of a script tag)
In getting started with require.js I ran into the issue and as a beginner the docs may as well been written in greek.
The issue I ran into was that most of the beginner examples use "anonymous defines" when you should be using a "string id".
anonymous defines
define(function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define(function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
define with string id
define('moduleOne',function() {
return { helloWorld: function() { console.log('hello world!') } };
})
define('moduleTwo', function() {
return { helloWorld2: function() { console.log('hello world again!') } };
})
When you use define with a string id then you will avoid this error when you try to use the modules like so:
require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
moduleOne.helloWorld();
moduleTwo.helloWorld2();
});
I had this error because I included the requirejs file along with other librairies included directly in a script tag. Those librairies (like lodash) used a define function that was conflicting with require's define. The requirejs file was loading asynchronously so I suspect that the require's define was defined after the other libraries define, hence the conflict.
To get rid of the error, include all your other js files by using requirejs.
Per the docs:
If you manually code a script tag in HTML to load a script with an
anonymous define() call, this error can occur.
Also seen if you
manually code a script tag in HTML to load a script that has a few
named modules, but then try to load an anonymous module that ends up
having the same name as one of the named modules in the script loaded
by the manually coded script tag.
Finally, if you use the loader
plugins or anonymous modules (modules that call define() with no
string ID) but do not use the RequireJS optimizer to combine files
together, this error can occur. The optimizer knows how to name
anonymous modules correctly so that they can be combined with other
modules in an optimized file.
To avoid the error:
Be sure to load all scripts that call define() via the RequireJS API.
Do not manually code script tags in HTML to load scripts that have
define() calls in them.
If you manually code an HTML script tag, be
sure it only includes named modules, and that an anonymous module that
will have the same name as one of the modules in that file is not
loaded.
If the problem is the use of loader plugins or anonymous
modules but the RequireJS optimizer is not used for file bundling, use
the RequireJS optimizer.
The existing answers explain the problem well but if including your script files using or before requireJS is not an easy option due to legacy code a slightly hacky workaround is to remove require from the window scope before your script tag and then reinstate it afterwords. In our project this is wrapped behind a server-side function call but effectively the browser sees the following:
<script>
window.__define = window.define;
window.__require = window.require;
window.define = undefined;
window.require = undefined;
</script>
<script src="your-script-file.js"></script>
<script>
window.define = window.__define;
window.require = window.__require;
window.__define = undefined;
window.__require = undefined;
</script>
Not the neatest but seems to work and has saved a lot of refractoring.
Be aware that some browser extensions can add code to the pages.
In my case I had an "Emmet in all textareas" plugin that messed up with my requireJs.
Make sure that no extra code is beign added to your document by inspecting it in the browser.
Or you can use this approach.
Add require.js in your code base
then load your script through that code
<script data-main="js/app.js" src="js/require.js"></script>
What it will do it will load your script after loading require.js.
I was also seeing the same error on browser console for a project based out of require.js. As stated under MISMATCHED ANONYMOUS DEFINE() MODULES at https://requirejs.org/docs/errors.html, this error has multiple causes, the interesting one in my case being: If the problem is the use of loader plugins or anonymous modules but the RequireJS optimizer is not used for file bundling, use the RequireJS optimizer. As it turns out, Google Closure compiler was getting used to merge/minify the Javascript code during build. Solution was to remove the Google closure compiler, and instead use require.js's optimizer (r.js) to merge the js files.

Can system.js replace require.js

I'm using requirejs in a large project. This project will soon be upgraded to angular2.
Angular2 uses system.js, so I'm thinking of switching to system.js too. Should I be able to remove the reference to the requirejs library and include system.js instead and expect it to work, or is there something I don't understand here?
I tried by just removing the require.js file and adding the system.js file instead, but I get error messages saying define is not defined.
Can you help? Will I need require.js in addition to system.js?
I just switched to system.js too. You need to replace your require.js with system.js and add simple script tag. So it should look like this:
<script src="~/lib/system.js/dist/system.js" type="text/javascript"></script>
<script>
// set our baseURL reference path
System.config({
baseURL: '/app'
});
System.import('startup.js');
</script>
in addition to above steps set
System.defaultJSExtensions = true;
by default systemjs is not adding extension .js

How use an external non-typescript library from typescript without .d.ts?

I have defined these in my .html file:
<script type="text/javascript" src="bower_components/tree.js/tree.min.js"></script>
<script type="text/javascript" src="bower_components/q/q.js"></script>
<script type="text/javascript" src="test.js"></script>
Then in test.js:
var myTree = Tree.tree({})
But Typescript errors out saying: "Cannot find name 'Tree'"
I also tried compiling with --module amd and placing import Tree = require("model/tree"); at the top of the test.js file, but it errors out again: Cannot find external module 'model/tree'. however clearly it should be a valid import, see here where it was defined: https://github.com/marmelab/tree.js/blob/master/src/main.js
I do not want to write .d.ts files for every single external javascript file I want to use, is that seriously what Typescript wants me to do?
I do not want to write .d.ts files for every single external javascript file I want to use, is that seriously what Typescript wants me to do?
No. The simplest / quickest solution is simply to tell it that there is some variable Tree out there. This is as simple as:
declare var Tree:any; // Magic
var myTree = Tree.tree({})
TypeSafety is a sliding scale in TypeScript. In this case you are only telling the compiler that there is something called Tree that you will manage and don't care for much typesafety beyond the fact that it is there.
More
IMHO: The line declare var Tree:any; is much simpler syntax than other JS veficiation tools would have you write to declare your usage of variables that are not present in your code.
Update
interface ITree {
.. further methods and properties...
}
interface ITreeFactory {
tree(input: { [key: string]: any }): Itree
};
declare var Tree: ITreeFactory; // magic...
You may define 'require' yourself and use undocumented amd-dependency feature of TypeScript:
/// <amd-dependency path="model/tree" />
declare var require:(moduleId:string) => any;
var Tree = require("model/tree");
'amd-dependency' directive will tell the compiler to include your module to "define" arguments in generated code:
see a sample here.
You may also check a very good article which explains how to use TypeScript with RequireJS.
But note that without writing proper TypeScript definitions for your existing code you won't be provided with any type information, and so you won't get type safety checks, advanced code completion in tools and so on. So, your 'Tree' will actually be of type 'any', and actually will be a dynamic JS piece inside other TS code.

Require module after optimized app.js

I'm using require.js and optimize it with the node module r.js.
It works but I have one problem when trying to require a module after I've included require.js.
That's what I need:
<script data-main="/js/app-built" src="/js/vendor/require.min.js"></script>
<script type="text/javascript">
require(['Functions'], function(Functions){
console.log(Functions);
});
</script>
This doesn't work, as it doesn't find the Functions module.
But this works:
<script data-main="/js/app-built" src="/js/vendor/require.min.js"></script>
<script type="text/javascript">
require(['app-built'], function(){
require(['Functions'], function(Functions){
console.log(Functions);
});
});
</script>
Is there a way to achieve the first approach?
In your first snippet the problem is that by the time the first require call executes, it is quite possible (quite likely in fact) that RequireJS has not yet loaded your application. The data-main attribute initiates right away the loading of your main module but it only initiates it right away. The loading is still asynchronous. And the reason it works in your second snippet is that the outer require forces the inner require to execute after your main module is loaded.
So for your require call to be successful, RequireJS must have enough information to load it. So it must already have a configuration that will allow it to find your module. This either adding some configuration before you load RequireJS. You can set require to a configuration object which will be picked up by RequireJS when it is loaded:
<script type="text/javascript">
require = {
// Enough config to find the main module.
baseUrl: ...,
paths: ...,
bundles: {
// List here every module you want to load individually.
"app-built": ["Functions"]
}
};
</script>
<script src="/js/vendor/require.min.js"></script>
<script type="text/javascript">
require(['app-built']);
require(['Functions'], function(Functions){
console.log(Functions);
});
</script>
You don't have to pull the whole config out of your main module because RequireJS can combine configs, but there need to be enough there to allow RequireJS to start loading things. The app-built module could contain additional configuration that is not needed for the initial steps. In the code above I've dropped data-main and used require(['app-built']) instead because I'm not sure whether it is possible to still use data-main even when using the bundles parameter. (I'm concerned it might confuse RequireJS.) Using bundles will allow RequireJS to know that when you require Functions, it must find it in app-built.
Apart from perhaps still being able to use data-main instead of the initial require call (which I'm not sure you can do), I do not think it is possible to simplify this further.

How to namespace modules in the browser but not in node

I have seen many examples of the self-invoking pattern that detects the global object (module.export / window) -- but I am not sure how to do namespacing with this pattern and still have it work in node the same way.
(function(exports) {
'use strict';
// how do i do something like this and have it work in node as well
// exports Namespace.Models.HelloWorld = function () {}
exports.say = function() {
return 'hello world';
};
}(typeof exports === 'undefined' ? this.helloworld = {} : exports));
After looking at the code some more I think you're code should work fine. What you want is to namespace all your code so that it doesn't pollute the global namespace right? So what you need is a single object in the global namespace that you then put all your code under.
Note: The global namespace in the browser is window in case you didn't know.
For example, JQuery creates only two global objects: jQuery and $. Everything you do with JQuery involves only those two global objects. JQuery even has a compatibility mode that disables the dollar sign so then you only have the jQuery object. The pattern people use to get the dollar sign back even when it's been disabled is to do this:
(function ($) {
// Do stuff with $
})(jQuery);
It's a self-invoking function that passes the jQuery object into itself which then becomes the $ argument. That way you can still have the convenience of the dollar sign without clogging up the global window object with yet another property. In your code (this.helloWorld) the this keyword refers to the global namespace (unless your code is wrapped inside another function or something and you didn't post it). What you've done is create a property on the window object (global namespace) called helloWorld, you set it to an empty object, and you pass it in. But you only do this if exports is undefined. That's the part that identifies if you're in node or not. exports will only be undefined if you're in the browser because exports is only available in node modules (just don't add an exports property to the global namespace in the browser, lol).
Note: Node has no application-wide "global" namespace that things get put into by default. Everything in node is scoped to the module level. So even if you define a variable on the first line of your module you can still define the exact same variable on the first line of another module and they won't conflict with each other. There is however, a global object in node that truly is global and you can access its properties from any module. I do not encourage you to use the global object, like, ever. If you need to use that object then you should probably reconsider your application structure.
Whatever you attach to exports in node becomes available to any other module that requires it.
// helloWorld.js
exports.message = "Hello, world!";
and then...
// main.js
var helloWorld = require('./helloWorld.js');
// Now all the properties are available on the variable `helloWorld`.
console.log(helloWorld.message);
// Prints "Hello, world!" to the console.
In the browser you want to do something similar by attaching a single uniquely named object to window and then whomever uses your script should access all your functions through that "namespace". So finally we have this:
// helloWorld.js
(function (myNamespace) {
myNamespace.message = "Hello, world!";
})(typeof exports === 'undefined' ? this.helloWorld = {} : exports)
If exports does not exist then add helloWorld to this (which refers to window when in the global scope like it is in this example) and pass that in. If exports does exist then pass it in instead. Now inside the function we can attach properties and methods to myNamespace and they'll either be attached to window.helloWorld or exports depending on the environment.
I could add the above helloWorld.js file to my node application and use it like this:
// nodeScript.js
var helloWorld = require('./helloWorld.js');
console.log(helloWorld.message);
Or I could add the above helloWorld.js file to my web app. Your page might look like this:
// index.html
<html>
<head>
<title>My Site</title>
<script src="helloWorld.js" />
<script src="clientScript.js" />
</head>
<body>
<div id="messageBox"></div>
</body>
</html>
And your script might look like this:
// clientScript.js
document.getElementById('messageBox').innerHTML = helloWorld.message;
The above page would end up with "Hello, world!" inside the div because it read the message from our module's exposed properties :)
Hopefully that clears things up. Sorry for jumping in with browserify at first instead of directly answering your original question. I do highly recommend browserify though :)
You need browserify. Write your modules in the node-style and then let browserify turn them into proper client-side scripts :)
From browserify home page:
Write your browser code with node.js-style requires:
// main.js
var foo = require('./foo');
var gamma = require('gamma');
var n = gamma(foo(5) * 3);
var txt = document.createTextNode(n);
document.body.appendChild(txt);
Export functionality by assigning onto module.exports or exports:
// foo.js
module.exports = function (n) { return n * 11 }
Install modules with npm:
npm install gamma
Now recursively bundle up all the required modules starting at main.js into a single file with the browserify command:
browserify main.js -o bundle.js
Browserify parses the AST for require() calls to traverse the entire dependency graph of your project.
Drop a single <script> tag into your html and you're done!
<script src="bundle.js"></script>
Not only is it fun to write client-side scripts like this but browserify will bundle it all together into a nice and tidy minified single script file :D

Resources