Dynamically load JSX file in JavaScript - javascript

I am trying to implement a wrapper API file for a ReactJS component.
For example, /js/test.react.js
/** #jsx React.DOM */
var TESTCLASS = React.createClass({
render : function() {
return (
<div> Test </div>
);
}
});
I have written a wrapper JavaScript file for that:
var testClass = {
load: function () {
var script = document.createElement("script");
script.type = "text/jsx";
document.head.appendChild(script);
script.onload = function(){
React.render(
<TESTCLASS/>,
document.body)
};
script.src ="./js/test.react.js";
}
};
Then I can use the wrapper API JavaScript in a third-party HTML.
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script type="text/jsx" src="test.js"></script>
</head>
<body>
<div id="content"></div>
<script>
testClass.load();
</script>
</body>
</html>
However, it seems to me /js/test.react.js cannot be dynamically loaded as pure JavaScript file. Can any expert explain to me the reason and provide a proper solution to write my wrapper API JavaScript file?

JSXTransformer*.js exports a global JSXTransformer object which has an exec() function, which transpiles JSX then eval()s the result.
You could try running JSXTransformer.exec() with the script's contents onload first.
Also, FYI, the #jsx pragma is no longer required as of React 0.12 :)

Related

Function not working if src is a variable?

With this HTML the function myFunc() can be executed. https://myurl.de/myjs.js has the function myFunc in it.
<head>
<script type="text/javascript" src="https://myurl.de/myjs.js"></script>
<body>
<script type="text/javascript">
myFunc();
</script>
</body>
</head>
But with the second HTML I get an Error: Uncaught ReferenceError: myFunc is not defined.
https://myurl.de/settingsFile.js is a file that includes this url in a var: https://myurl.de/myjs.js so basically SettingsFile.UrlToMyJS is this https://myurl.de/myjs.js
<head>
<script src="https://myurl.de/settingsFile.js"></script>
<script type="text/javascript" id="myid"></script>
</head>
<body>
<script type="text/javascript">
document.getElementById('myid').src = SettingsFile.UrlToMyJS;
myFunc();
</script>
</body>
When I console.log(document.getElementById('myid')) this is the output:
<script type="text/javascript" id="myid" src="https://myurl.de/myjs.js></script> which is correct. It looks exactly like the script in the head of the first html (with the difference that it has the id="myid").
Yet it does not work. Why and how can I fix it?
settingsFile.js:
var defaultURL = 'https://myurl.de/';
var SettingsFile = {
UrlToMyJS : defaultURL + 'myjs.js',
}
The reason it's not working is that you can't add a src to a script element that's already in the DOM — or rather, doing so doesn't do anything. The script element has already been processed.
Instead, create it and then append it:
var script = document.createElement("script");
script.onload = function() {
myFunc();
};
script.src = SettingsFile.UrlToMyJS;
document.head.appendChild(script);
// If you need to support IE8, use the following instead of the previous line:
//document.getElementsByTagName("head")[0].appendChild(script);
That waits for the script to load, then calls myFunc (which should exist by then).
Also note that as I and Jeremy pointed out in the comments, body doesn't go in head, it goes after. It's also generally best to put script tags at the end of body (if you're not using async or defer attributes on them or type="module"). So in all, something like:
<head>
<!-- head stuff here -->
</head>
<body>
<!-- content here -->
<script src="https://myurl.de/settingsFile.js"></script>
<script type="text/javascript">
var script = document.createElement("script");
script.onload = function() {
myFunc();
};
script.src = SettingsFile.UrlToMyJS;
document.head.appendChild(script);
// If you need to support IE8, use the following instead of the previous line:
//document.getElementsByTagName("head")[0].appendChild(script);
</script>
</body>
Another option is to use document.write. This sort of thing may be the last at-least-partially appropriate use of document.write during the main parsing of the page:
<head>
<!-- head stuff here -->
</head>
<body>
<!-- content here -->
<script src="https://myurl.de/settingsFile.js"></script>
<script type="text/javascript">
document.write('<script src="' + SettingsFile.UrlToMyJS + '"><\/script>');
</script>
<script>
myFunc();
</script>
</body>
You can try creating a element and then appending it to your title
For Example (script code) :
var script = document.createElement("script");
script.src = "YOUR_SCRIPT_SRC_HERE";
document.getElementsByTagName('head')[0].appendChild(script);
Here I am creating a new tag in html and then appending it to the head of your html. Even as T.J. Crowder mentioned in the comment try removing your body from the head

Javascript trouble in dynamically call another class in other js file

I'm trying to make a javascript function to call another .js file like this:
scriptCaller.js
function callScript(file){
var script = document.createElement('script');
script.id = file;
script.type = 'text/javascript';
script.async = true;
script.src = "script/"+file+".js";
document.getElementById('scriptSection').appendChild(script);
}
Then I create some class to be called by that script in other file:
divGenerator.js
function divGenerator(){
var self = this;
var div = document.createElement('div');
this.tag = function(){
return div;
}
/*and some other function to style the div*/
}
Then i make the main file to be executed:
main.js
function build(){
callScript('divGenerator');
}
function main(){
var test = new divGenerator();
/*execute some function to style the div*/
document.getElementById('htmlSection').appendChild(script);
}
All the three file will be called in a HTML files that will execute the main function:
myPage.html
<html>
<head>
<title>myPage</title>
</head>
<script src="scriptCaller.js"></script>
<script src="main.js"></script>
<body>
<div id="htmlSection"></div>
<div id="scriptSection"></div>
</body>
</html>
<script>build();</script>
<script>main();</script>
If I correct it should display the styled div, but what I got is an error that said:
TypeError: divGenerator is not a constructor[Learn More]
But, when I move the divGenerator() class to myPage.html it works fine. Any idea to solve this problem?
You need to add scriptCaller.js and divGenerator.js to your html script element.
<html>
<head>
<title>myPage</title>
</head>
<script src="scriptCaller.js"></script>
<script src="main.js"></script>
<script src="scriptCaller.js"></script>
<script src="divGenerator.js"></script>
<body>
<div id="htmlSection"></div>
<div id="scriptSection"></div>
</body>
</html>
<script>build();</script>
<script>main();</script>
You have couple of problems in your code. First of all, do not assign id to script element same as the "exported" global constructor name. You need to remember that anything with id attribute (and name) automatically gets exposed as global variable on window object. It means that divGenerator in your case is going to be reference to HTMLScriptElement, not a constructor function.
Second problem is related to timing, since you are loading script with async attribute. This is good, but you need to realise that in this case you can't expect that script will be loaded when you call main after build(). I would suggest to wrap script creation into promise:
function callScript(file){
return new Promise(function(resolve) {
var script = document.createElement('script');
script.id = 'script-' + file; // Note different id
script.async = true;
script.src = "script/" + file + ".js";
script.onload = resolve
document.getElementById('scriptSection').appendChild(script);
})
}
and use it like this:
<script>
build().then(function() {
main();
})
</script>

How could I pack all js files, CSS , embedded scripts into a js plugin

I wrote a JS plugin to client's website can load comments from our database via CORS method.
My goal is to wrapper my whole code into an easily embeddable plugin.
Just like the facebook js plugin, Google Analytics plugin. They are easy to install on a website.
My plugin depends on other libraries, such as jquery, underscore, backbone, handlebars, and also my scripts and CSS.
I studied Require.js it seems suitable to do this job for me.
I need to generate an all-in-one javascript plugin, e.g.,. "awesome-comments.min.js".
Some articles suggest me to put all the dependent js files with require.config.
But I'm having no idea how could I do other stuff such as my js scripts with require.js.
Is there any similar application or tutorial has the same function. Thanks.
sample_with_requireJS.html
<html>
<head>
<script src="js/require.js" data-main="js/main"></script>
</head>
<body>
<div id="load_awesome_comments"></div>
</body>
</html>
js/main.js
  require.config({
    baseUrl: "http://mywebsite/assets/",
    paths: {
      "jquery": "jquery-9e7b5a8e0157d7776b987d8963c9c786.js?body=1",
      "underscor": "~~~",
...
    }
  });
sample-without-requireJS.html (This is my current workable html sample, mixed with js, css and html DOM)
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"/>
<script src="http://localhost:3001/assets/jquery-9e7b5a8e0157d7776b987d8963c9c786.js?body=1" data-turbolinks-track="true"></script>
<style>
body {
/*background-color: linen;*/
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$(document).on('click','.show-more',function () {
var $this = $(this);
....
});
});
window.onload = function(){
.....
}
Handlebars.registerHelper('if_even', function(conditional, options) {
....
});
</script>
<!-- Setup our templates -->
</head>
<body>
<div id="load_awesome_comments"></div>
<script type="text/javascript">
$(document).ready(function() {
function hideFurtherComments(){
.....
}
var Comment = Backbone.Model.extend({
....
});
var Comments = Backbone.Collection.extend({
model: Comment,
url: fetch_comments_url,
initialize: function() {
....
},
deferred: Function.constructor.prototype,
fetchSuccess: function(collection, response) {
collection.deferred.resolve();
},
});
var comments = new Comments();
var CommentView = Backbone.View.extend({
el: $("#comments_section"),
render: function() {
....
},
});
var EmptyCommentView = Backbone.View.extend({
el: $("#empty_comments_list"),
render: function() {
....
},
});
var commentView = new CommentView({
collection: comments
});
var emptyCommentView = new EmptyCommentView({
collection: comments
});
comments.deferred.done(function() {
....
});
});
var og_url = $("meta[property='og:url']").attr("content");
$("#original_news_article_link").attr("href", og_url)
</script>
<script src="js/require.js" defer async="true" ></script>
</body>
</html>
Give a look at https://webpack.github.io and http://browserify.org/. Their purpose is to do exactly what you need. You pack all of your Javascript code, Javascript dependencies and CSS in one sole JavaScript file.
The advantage of this method is that users can make use of your module just by including a single JavaScript file; no need to worry about dependencies.
The drawback is that, given that the dependencies are all included in the single file, if in a page you have three modules packed this way that use jQuery, for example, the jQuery code will be downloaded three times.

How do I reference jQuery from my HTML/JavaScript application?

I keep getting Uncaught ReferenceError: $ is not defined error.
I assume everything is ok and working. My JQuery code is inside my Javascript file. I assume that isn't how it works? Should I have a JQuery file?
I have this inside the head of my HTML
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
This is my Javascript file:
function typing(id, sentence){
var result = $.Deferred();
var index=0;
var intObject= setInterval(function() {
document.getElementById(id).innerHTML+=sentence[index];
index++;
if(index==sentence.length){
clearInterval(intObject);
}
}, 100);
return result.promise();
}
var sleep = function(ms) {
var result = $.Deferred();
setTimeout(result.resolve, ms);
return result.promise();
};
typing('container','Subject Name:').then(function() {
return sleep(500);
}).then(function() {
return typing('container',' Carlos Miguel Fernando')
});
Where did I go wrong?
Your question is fairly unclear, but essentially, you just have to make sure jQuery is loaded before your code. So for instance:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="your-code.js"></script>
or
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script>
// Your code
</script>
But not
<!-- Not like this -->
<script src="your-code.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
Note the order of tags.
These tags do not need to be in the head, and in fact, putting them there is not best practice. They must be in head or body. Best practice barring a specific reason to do something else is to put them at the very end of body, e.g.:
<!-- site content here -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<script src="your-code.js"></script>
</body>
</html>

Node,express,jade rendered pages doesn't data-bind with knockout.js

I'm running a Node server with express which renders jade. I'm trying to make my client side use knockout.js but the view never updates... I don't get any errors in the console and I just can't figure out what is wrong.
Page:
extends layout
block content
script(src='knockout/knockout-2.2.1.debug.js', type='text/javascript')
script(src='js/app.js', type='text/javascript')
p Hi,
strong(data-bind="text: firstName")
rendered html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<script src="knockout/knockout-2.2.1.debug.js" type="text/javascript"></script>
<script src="js/app.js" type="text/javascript"></script>
<p>Hi,<strong data-bind="text: firstName"></strong></p>
</body>
</html>
app.js:
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
}
ko.applyBindings(new AppViewModel());
is there something I'm missing here or is it just not possible to make this happen with Node.js and express?
You need to make sure you call ko.applyBindings() after the DOM has already been loaded.
Either wrap the code in app.js in window.onload, in jQuery's ready() function, or move your script tag to be below <p>Hi,<strong data-bind="text: firstName"></strong></p>.
// this is my js file
(function () {
//START THE APP WHEN DOCUMENT IS READY
$(function () {
function AppViewModel() {
var self = this;
self.firstName = "Hamza";
// self.lastName = ko.observable("Bertington");
}
ko.applyBindings(new AppViewModel());
});
})();

Categories