Global variables in jsx file are not loaded - reactjs

In html file, the order of script files are included as jsx files and then js files as,
<script src="global.jsx" type="text/jsx"></script>
<script src="app.js" type="text/javascript"></script>
In global.jsx, the code is,
var abc = {ab: 1, ba: 2}
console.log("from jsx file " + abc)
In app.js, the code is,
console.log("from js file " + abc)
In browser app.js prints error, then global.jsx prints the variable value as:::
app.js -----> ReferenceError: abc is not defined
global.jsx -----> from jsx file [Object object]
How does the browser run the code in reverse, even though in html file, jsx is loaded first and then js is loaded?
And how can one declare browser globals inside jsx file and make it available for other js/jsx files?

You should precompile your file, global.jsx into a JavaScript file rather than relying on the transpiler feature if you want to be assured of a particular script loading behavior.
As your global.jsx file isn't compiled until a later step (when the JSX transpiler loads and finds all script tags with type="text/jsx"), it's actually being compiled and executed as JavaScript after the app.js file has already executed.
There are other somewhat hacky workarounds, but I'd suggest precompilation and possibly relying on a bundling system so that all of the JavaScript is loaded at one time (and all of the dependencies will be loaded in the correct order).

From what I can find on the internet the behavior is that browser loads the javascript files first that may be required for rendering any react components. So I guess that is an expected behavior. I can confirm that the reverse i.e., setting the value of abc in js and accessing from jsx works. I could not find many work arounds for this though.
Although this can be used I am guessing. The original purpose is to load heavy scripts lazily. Ideally I guess you would have to use js -> jsx binding.

Related

Require.js fails when including socket.io [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.

#section syntax instead of requirejs or browserify for angularjs application

I understand that requirejs and browserify can load my files dependent on its current context, and that it is amazing. I would really prefer to use the #section sections syntax that the razor engine uses. Was just wondering if there is a way to implement this into a typescript / angularjs application.
for example
index.html
#renderSection scripts;
// which could turn into something like
<script data-render="scripts"></scripts>
// the app.run() could declare all the scripts that will be needed on every
// page view
view.html
<script ng-section-repeat="injected in injection"></script>
// the ng-section-repeat is basically taking all the items in the
// typescript constructor and then finding out which ones are needed for
// that view.
I like the idea injecting application file dependencies in the view , without a configuration file and all the added extras that comes with the loaders.
I just want to easily define what files are needed in the actual view and get them loaded, with angular's dependency injection handling the dependency itself.
If you are handling all your dependencies with $inject then , as far as i can tell, dependency is technically already setup in the controllers, all one would need, is to load this as it is called. Which could even eliminate the need for the #section scripts completely
Update:
What i have done to sort of replicate the module loaders is to just use gulp-concat and define the file order in my gulp.config.js and then pass it to the gulp-src before running $.concat .this allows me to have the files in the gulp steam , in dependent order . They are however loaded on the first load. With gulp-uglify the files are tiny ( its now at 566Kb with 16 external libraries loading in 69ms . To put that into perspective it takes 209ms to load one google font ).
I dont know maybe i am not understanding browserify correctly but i honestly struggle to see the need for it, its seems extremely convoluted for something so simple
It is possible using external modules and an injector to do what you asked for:
I just want to easily define what files are needed in the actual view
import {UserFactory} from 'models/userFactory';
import {UserValidator} from 'models/userValidator';
import {Inject} from 'angular2/di';
and get them loaded, with angular's dependency injection handling the dependency itself.
Note: My example uses angular 2.x because I less familiar with angular 1.x and I'm sure you can do something really similar...
class SomeComponent {
userName: string;
userRating: number;
rating: number;
constructor(
#Inject(UserFactory) UserFactory
#Inject(UserValidator) UserValidator
)
{
this.UserFactory = UserFactory;
this.UserValidator = UserValidator;
}
}
Then you can use Browserify to create a bundle.js file that can be executed in a web browser.

Grunt-Karma-Jasmine: can not find module

I am trying to set up tests for my Angular.js project and I keep getting "$injector:nomod, Module 'result' is not available! You either misspelled..." error. I am sure that I am including "result" module in the "files" array inside "karma.config.js", basically it looks like this:
files: [
'../javascripts/jquery-2.1.4.min.js',
'../jquery-ui/jquery-ui.min.js',
'../D3/d3.js',
'libs/angular.min.js',
'libs/angular-route.min.js',
'libs/angular-animate.min.js',
'libs/selectize.js',
'libs/angular-selectize.js',
'libs/angular-mocks.js',
'simulator.js',
'*.js',
'services/**/*.js',
'qa/tests-*.js'
],
...
I thought initially that the ordering of the main module: 'simulator' (defined inside 'simulator.js' file) is wrong, so I specifically moved it upwards, before
the other modules, like the following stackoverflow thread recommends:
Angular module not available in Karma Jasmine test run
It did not help. Then I tried to make sure that the files are imported in the same order as in my angular apps' main entry file (except for angular-mocks.js and qa/tests-*.js), importing each single file, instead of using wildcards, but no success.
Jasmine definitely goes inside the test files but stumbles upon the line where I am trying to import the module "result":
describe('simulator.chartService', function() {
var chartService;
var graphConfig;
console.log("instantiating module result");
beforeEach(module('result'));
console.log("finished instantiating");
beforeEach(inject(function($injector) {
graphConfig = $injector.get('graphConfig');
chartService = $injector.get('chartService');
}));
it('should be created', function() {
expect(chartService.calcColors(10)).not.toBeNull();
});
});
So, I see that the error happens in-between two console.log() statements.
I suspect that still something can be wrong with the ordering of my files inside the array "files" in "karma.config.js". I have main module "simulator" which is dependent on other modules:
angular.module('simulator', ['ngRoute','ngAnimate','selectize','newexp2','newexp','login','edit','exps', 'result','templates','commons'])
Modules 'newexp2', 'newexp', 'login', 'edit', 'exps', 'result', 'templates' are all dependent on the module 'commons'.
How to correctly import interdependent modules inside the "files" array?
Is it just enough to place "simulator.js", main module, above all others,
or I also need to place all other modules before "commons.js"?
Another my suspicion is that angular.js library version that I downloaded from the official angular website, "angular-mocks.js", can be incompatible with other modules that I am using. I had such an issue with "angular-animate.js" file before.
As long as I surround my test code with $(function(){...}) (and all other my modules ARE surrounded with it) it does not generate the error while importing the result module, so I start seeing two console.log() statements without an error in-between, however, this generates some unknown error which prevents me from invoking the it part at all, whereas when I do not surround it with $(function(){...}), the it test is invoked, but the module result import fails.
So far I am pretty much stuck and do not know where to move and what to try. Any suggestion would be greatly appreciated.
OK, I figured it out. The issue was that ALL of my angular code was enclosed inside $(function(){...}). The solution is to remove all of the $function(){...}), then reorder javascript imports inside the main entry .html file, and then all of the testing starts working good.
The question might be better to mark as duplicate with:
Angular document.ready() issue

angular-slidezilla: <slider> not showing in site

I tried intgrating angular-slidezilla into a web site, but the slider elements do not show.
Observations:
I copied the .js file into the /lib folder and the .css into the /css folder.
the site uses requirejs; I added the source file into the requirements list.
I added the css as a stylesheet link next to the other css files in the index.html file.
To test, I copied the demo page (the entire part) into my HTML page and added $scope.slider1.val etc. variables to the AngularJS controller object. I also added a function which periodically changes the value of the scope variables.
When I deploy the site and load the page, I see the values changing every second (these are shown as text near the sliders). But the sliders themselves do not show.
"Inspect element" function shows a generated piece of DOM (div objects related to the slider), but the slider itself has size 0px*0px.
No errors in javascript console.
Can anyone give me a hint how to investigate further?
Found the solution. The javascript code in angular-slidezilla.js was never executed. As a result the widgets were not initialized and remained in their initial hidden state.
I needed to edit one line of javascript code to get it working:
// app.js
var app = angular.module("app", ['ui.bootstrap', ..., 'angular-slidezilla']);

Backbone.js not performing document.write at the correct time?

I have a backbone.js CMS of sorts, that accepts html and then renders it in the browser. The following is the template file (in .hamlc) that renders the backbone page object.
%h1.text= #page.get('title')
.text.page-content!= #page.get('content')
This works fine, until I have a <script> tag. I have a script tag for a widget (below)
<script src='http://www.opentable.com/frontdoor/default.aspx?rid=52900&restref=52900&bgcolor=8AA86B&titlecolor=0F0F0F&subtitlecolor=0F0F0F&btnbgimage=http://www.opentable.com/frontdoor/img/ot_btn_black.png&otlink=FFFFFF&icon=light&mode=short&hover=1'></script>
This widget uses document.write (which you can see if you look at the source). First, when I load the page it doesn't show anything (I've tested the widget in an html file by itself and it displays their normal god-awful ). When I inspect the element, it looks like the script tag was removed.
However, when I test with the following:
<script type="text/javascript">
alert(0);
</script>
It runs. Still nothing in the inspector though.
Finally, testing with the following:
<script type="text/javascript">
document.write('test');
</script>
It also runs. However, it completely destroys the page content and just shows 'test'.
According to this article about using document.write for widgets, it says it can't be run after the page load. I'm assuming that's what's happening here is that document.write is being run after page load and destroying all the content, given that's the technique backbone.js uses (appending/replacing elements in the DOM once the page is loaded).
How can I make my Backbone.js CMS accept script tags with document.write widgets without either not showing anything or destroying the entire page?
I cannot reproduce it, the template renders as it should:
$ coffee
coffee> hc = require './src/hamlc'
{ compile: [Function],
template: [Function],
__express: [Function] }
coffee> template = hc.compile ".text.page-content!= #content"
[Function]
coffee> template(content: 'Hello <script>Script</script>')
'<div class=\'page-content text\'>Hello <script>Script</script></div>'
and the script tag is persisted. Do you have the latest version installed?
You're calling document.write after the page has been loaded, so it'll overwrite the whole page. You could try putting the script tag in an iframe, or monkey patch document.write to behave differently after the page has been loaded. See the top answer on this question:
Dynamically added JavaScript overwrite the html page view (not the code)
If I understand correctly, you're trying to include the script tag for the widget inside a template, which means it's being inserted after the initial DOM is ready. That won't work for the reasons you mentioned; when the script executes, it will replace everything in the DOM.
You need to load the script before the initial DOM is complete, that is either in <head> or at the beginning of <body>. That in turn means that you have to include the script tag in your initial HTML as delivered by the server rather than trying to dynamically generate it client-side.

Resources