Typescript include modules in browser? - javascript

I am just getting started with TypeScript (and front end development in general) coming from a c# background so sorry if this is a really basic question, but I can't figure out where I'm going wrong...
What I'm trying to do for now is create a really basic program to retrieve some sample data from a url in JSON format, parse to TS classes, and display it on the page.
In order to get the json response I found this answer that recommends using a node package. I got it installed and it seems to be ok (at least TS doesn't give me any errors).
I also figured out that I need to compile (not sure if that's the right term?) with Browserify to make it browser compatible since it's using a node module. I did that but now when I try to run in a browser it's telling me my method is not defined.
export class Keynote {
KeyValue: string;
Description: string;
Parent: string;
}
Retrieval class is:
import {Keynote} from "./Keynote";
import * as request from "request-promise-native";
function GetKeynotes(): Array<Keynote> {
const baseUrl = 'https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteProvider.php';
var options = {uri: baseUrl};
const result = JSON.parse(request.get(options));
return result;
}
and html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Keynotes Testing</title>
<script src="bundle.js"></script>
<script>
function Retrieve() {
var notes = GetKeynotes();
document.getElementById('container').innerText = JSON.stringify(notes);
}
</script>
</head>
<body>
<div>
<button content="Get some notes" onclick="Retrieve()">Get some notes</button>
</div>
<div id="container">
</div>
</body>
</html>
Browserify is really long so I didn't want to copy here but you can see it at https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteDisplay.html in the source if you want.
When I click the button I get this error in the browser:
KeynoteDisplay.html:9 Uncaught ReferenceError: GetKeynotes is not defined
at Retrieve (KeynoteDisplay.html:9)
at HTMLButtonElement.onclick (KeynoteDisplay.html:16)
Retrieve # KeynoteDisplay.html:9
onclick # KeynoteDisplay.html:16
GetKeynotes is defined in my typescript, and on the 5th line of bundle.js I see a function with that name... Why is it undefined?
UPDATE
Ok I have played with jspm and SystemJs but I still don't have something right. I referenced the module with jspm and did a bundle to build.js and uploaded the whole thing just to make sure everything is there. Here are the tags in my html for scripts:
<script src="../../jspm_packages/system.js"></script>
<script src="../../config.js"></script>
<script src="build.js"></script>
<script>
System.import("Sandbox/TypeScript/build.js")
function Retrieve() {
System.import("Sandbox/TypeScript/build.js")
var notes = GetKeynotes();
document.getElementById('container').innerText = JSON.stringify(notes);
}
</script>
When I press the button I can debug in my function, but it still gives the error, 'GetKeynotes is not defined' just like before... Again I can see a function with that name in the build.js file so I don't understand why it's not finding it.
I also tried System.import("Sandbox/TypeScript/KeynoteRetrieval.js") but it gives the error:
Uncaught (in promise) Error: (SystemJS) Node tls module not supported in browsers.
Error loading https://revolutiondesign.biz/Sandbox/TypeScript/KeynoteRetrieval.js

Related

How to use module from Github in javascript?

I am trying to use a library from GitHub found here: https://github.com/cubing/jsss
the readMe has an example of how to use it:
// index.html
<script src="index.js" type="module" defer></script>
<select id="eventID">
<option value="333" selected>3x3x3</option>
<option value="444">4x4x4</option>
</select>
<button id="new-scramble">New scramble</button><br>
<div id="scramble-string"></div>
// index.js
import { randomScrambleStringForEvent } from "scrambles";
const eventSelect = document.querySelector("#eventID");
const scrambleStringElem = document.querySelector("#scramble-string");
async function newScramble() {
scrambleStringElem.textContent += " ⏳";
const scrambleString = await randomScrambleStringForEvent(eventSelect.value);
scrambleStringElem.textContent = scrambleString;
}
document.querySelector("#eventID").addEventListener("change", newScramble);
document.querySelector("#new-scramble").addEventListener("click", newScramble);
newScramble(); // Initial scramble
The repo is full of so many folders I am not sure which ones I need. I used the src to and put this in a folder called libs with but I have no idea if this is right. I tried using the whole repo and it still didn't work. Whenever I try following the "full example" that they have I get an error. As someone who has never done this before:
Where do I put the index.js file
what files do I need to copy to my project to make this work
Putting index.html and index.js in the root directory I get the error
'Uncaught TypeError: Failed to resolve module specifier "scrambles". Relative references must start with either "/", "./", or "../".'
When adding the correct directory to scrambles, I get the error
'Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.'
In short I have no idea what I am doing and no idea how to use this in my project, please help...

Using express-babelify-middleware with FeathersJS

I am trying to use express-babelify-middleware
with FeathersJS and the error shows up in the browser console:
ReferenceError: main_run is not defined
I take this to mean that babelify is not working or I am using it incorrectly as main_run is in the global namespace of the src in my html file.
Here is my setup using the structure from feathers generate:
public/index.html:
<!DOCTYPE html>
<html>
<head>
<title>babelify test</title>
<script src="main.js"></script>
<script>
main_run()
</script>
</head><body>
<p>Testing feathers with babelify</p>
</body></html>
public/main.js
const external_module = require('./test')
function main_run(){
external_module()
}
public/test.js
module.exports = function(){
console.log("Hello world for an external module")
}
among the .uses of src/app.js:
...
const babelify = require('express-babelify-middleware')
...
app.use(compress())
.options('*', cors())
.use(cors())
//the line that is not working:
.use('/main.js', babelify( path.join(app.get('public'), 'main.js') ))
.use(favicon( path.join(app.get('public'), 'favicon.ico') ))
.use('/', serveStatic( app.get('public') ))
When I visit localhost:3030/main.js I can see the file, but the functions look to be in a function of their own, so I don't know how to get into that function.
Silly problem, one can't access browserified code in the html file that calls it. So public/index.html can't access main_run unless it is attached to the window object. There is a similar question
here.
Other than that, my code works perfectly.
In main.js place the following code at the bottom:
window.main_run = main_run
Then in index.html replace the main_run() line with:
window.main_run()
This will write the contents of test.js to the console.

How to get rid of "Uncaught SyntaxError: Unexpected token <" in ReactJs?

Just started my ReactJS and stuck at my very first try. I have a very basic code that throws "Uncaught SyntaxError: Unexpected token <".
index.html
<!doctype html>
<head>
<title>My first ReactJs</title>
</head>
<body>
<div id="container"></div>
<script src="react.js"></script>
<script src="script.jsx"></script>
</body>
</html>
script.jsx
var MessageButton = React.createClass({
render: function(){
return (
<button>Hello World</button>
);
}
});
React.render(<MessageButton/>, document.getElementById("container"));
Assuming that it could be missing JSX transformer library, I searched for it but couldn't find download anywhere. I work offline most of the time, so I do not wish to use plunkr or jsbin. Could do with some help.
First: Specify the type attribute of your JSX scripts so the browser doesn't try to execute them as JavaScript.
<script type="text/jsx" src="script.jsx"></script>
Second:
Either:
Load the JSXTransformer script (which requires an older version of React)
or
Compile the JSX using Babel:
Example taken from the docs:
babel --presets react src --watch --out-dir build

How is it possible to make json query client side [duplicate]

I have the following Node.js project (which is a Minimal Working Example of my problem):
module1.js:
module.exports = function() {
return "this is module1!";
};
module2.js:
var module1 = require('./module1');
module.exports = function() {
return module1()+" and this is module2!";
};
server.js:
var module2 = require('./module2');
console.log(module2()); // prints: "this is module1! and this is module2!"
Now I want to create a client.html file that will also use module2.js. Here is what I tried (and failed):
naive version:
<script src='module2.js'></script>
<script>alert(module2());</script> // should alert: "this is module1! and this is module2!"
This obviously doesn't work - it produces two errors:
ReferenceError: require is not defined.
ReferenceError: module2 is not defined.
Using Node-Browserify: After running:
browserify module2.js > module2.browserified.js
I changed client.html to:
<script src='require.js'></script>
<script>
var module2 = require('module2');
alert(module2());
</script>
This doesn't work - it produces one error:
ReferenceError: module2 is not defined.
Using Smoothie.js by #Torben :
<script src='require.js'></script>
<script>
var module2 = require('module2');
alert(module2());
</script>
This doesn't work - it produces three errors:
syntax error on module2.js line 1.
SmoothieError: unable to load module2 (0 )
TypeError: module2 is not a function
I looked at require.js but it looks too complicated to combine with Node.js - I didn't find a simple example that just takes an existing Node.js module and loads it into a web page (like in the example).
I looked at head.js and lab.js but found no mention of Node.js's require.
So, what should I do in order to use my existing Node.js module, module2.js, from an HTML page?
The problem is that you're using CJS modules, but still try to play old way with inline scripts. That won't work, it's either this or that.
To take full advantage of CJS style, organize your client-side code exactly same way as you would for server-side, so:
Create client.js:
var module2 = require('./module2');
console.log(module2()); // prints: "this is module1! and this is module2!"
Create bundle with Browserify (or other CJS bundler of your choice):
browserify client.js > client.bundle.js
Include generated bundle in HTML:
<script src="client.bundle.js"></script>
After page is loaded you should see "this is module1! and this is module2!" in browser console
You can also try simq with which I can help you.
Your problems with Smoothie Require, were caused by a bug (https://github.com/letorbi/smoothie/issues/3). My latest commit fixed this bug, so your example should work without any changes now.

How to create QUnit tests with reference to another class?

I'm trying to add unit testing for JavaScript into my web site. I use VS2013 and my project is an ASP.NET web site.
Based on recommendations (http://www.rhyous.com/2013/02/20/creating-a-qunit-test-project-in-visual-studio-2010/) I've done so far:
Created new ASP.NET app
Imported QUnit (using NuGet)
Into "Scripts" added links to js-file in my original web site (files PlayerSkill.js - containts PlayerSkill class and trainings.js - contains Trainer and some other classes)
Created new folder "TestScripts"
Added TrainingTests.js file
Wrote simple test:
test( "Trainer should have non-empty group", function () {
var group = "group";
var trainer = new Trainer(123, "Name123", group, 123);
EQUAL(trainer.getTrainerGroup(), group);
});
Notice: my trainings.js file among others contains
function Trainer(id, name, group, level) {
...
var _group = group;
this.getTrainerGroup = function () { return _group ; }
};
When I execute my test I see error: Trainer is not defined.
It looks like reference to my class is not recognized. I feel like linking file is not enough, but what did I miss?
Please help add reference to the original file with class and run unit test.
Thank you.
P.S. Question 2: Can I add reference to 2 files (my unit test will require one more class which is in another file)? How?
You should add all the relevant logic of your application to your unit testing file so they all execute before you run your tests
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Test Results</title>
<link rel="stylesheet" href="/Content/qunit.css">
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="/Scripts/qunit.js"></script>
<script src="/Scripts/PlayerSkill.js"></script>
<script src="/Scripts/trainings.js"></script>
<script src="/TestScripts/TrainingTests.js"></script>
</body>
</html>
You should not use linked files because they will not exist physically in the script folder.
If you really want to use them you should let the Visual Studio intellisense resolve the physical path of the file like this.
Type the script tag <script src=""></script>
Place the cursor inside the quotes in the src attribute and press CTRL + SPACE
Search your files and let the resolved path untouched
If your project location changes you must update the linked files and also the script references.
{Edit1}
Solution 2:
You could also use an MVC Controller and a Razor View to create your unit testing page and the linked files will work as expected with the only issue that you will have an extra controller in your project but this is not bad at all if for example you want to test the loading of content using ajax that is by default blocked by the browser if they are run from a local file.
Solution 3:
You can also setup a new MVC project just for your javascript unit testing just as you usually setup a new project for any server side code and this will help to prevent your testing to interfere with your production code
{Edit 2}
Solution 4:
As part of the javascript ecosystem you could use grunt or gulp to automate the copy of your scripts from anywhere to your project before running the tests. You could write a gulpfile.js like this
var sourcefiles = [/*you project file paths*/];
gulp.task('default', function () {
return gulp.src(sourcefiles).pipe(gulp.dest('Scripts'));
});
And then run it opening a console and running the command gulp or gulp default
Looks like trainings.js is not defined when calling TrainingTests.js . See this question for more details regarding why this happens! Once that is fixed it does work. And yes similar to trainings.js you can have any number of files in any folder as long as you reference them properly. I have created a sample fiddle accessible # http://plnkr.co/edit/PnqVebOzmPpGu7x2qWLs?p=preview
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="http://code.jquery.com/qunit/qunit-1.18.0.js"></script>
<script src="trainings.js"></script>
<script src="TrainingTests.js"></script>
</body>
In my case I wanted to run my tests from within my ASP.NET web application, and also on a CI server. In addition to the other information here I needed the following, otherwise I experienced the same error as the OP on my CI server:
Add one or more require() calls to test scripts.
Set the NODE_PATH environment variable to the root of my application.
Example of require()
Within my test scripts I include a requires block, the conditional allows me to use this script from a web browser without needing to adopt a third-party equivalent such as requirejs (which is convenient.)
if (typeof(require) !== 'undefined') {
require('lib/3rdparty/dist/3p.js');
require('js/my.js');
require('js/app.js');
}
Example of setting NODE_PATH
Below, 'wwwroot' is the path of where /lib/ and other application files are located. My test files are located within /tests/.
Using bash
#!/bin/bash
cd 'wwwroot'
export NODE_PATH=`pwd`
qunit tests
Using powershell
#!/usr/bin/pwsh
cd 'wwwroot'
$env:NODE_PATH=(pwd)
qunit tests
This allowed me to run tests both within my ASP.NET web application, and also from a CI server using a script.
HTH.
If you're wondering how to make your tests see your code when running from command line (not from browser!), here is a bit expanded version of Shaun Wilson's answer (which doesn't work out-of-the-box, but contains a good idea where to start)
Having following structure:
project
│ index.js <--- Your script with logic
└───test
tests.html <--- QUnit tests included in standard HTML page for "running" locally
tests.js <--- QUnit test code
And let's imagine that in your index.js you have following:
function doSomething(arg) {
// do smth
return arg;
}
And the test code in tests.js (not that it can be the whole content of the file - you don't need anything else to work):
QUnit.test( "test something", function( assert ) {
assert.ok(doSomething(true));
});
Running from command line
To make your code accessible from the tests you need to add two things to the scripts.
First is to explicitly "import" your script from tests. Since JS doesn't have sunch a functionality out-of-the box, we'll need to use require coming from NPM. And to keep our tests working from HTML (when you run it from browser, require is undefined) add simple check:
// Add this in the beginning of tests.js
// Use "require" only if run from command line
if (typeof(require) !== 'undefined') {
// It's important to define it with the very same name in order to have both browser and CLI runs working with the same test code
doSomething = require('../index.js').doSomething;
}
But if index.js does not expose anything, nothing will be accessible. So it's required to expose functions you want to test explicitly (read more about exports). Add this to index.js:
//This goes to the very bottom of index.js
if (typeof module !== 'undefined' && module.exports) {
exports.doSomething = doSomething;
}
When it's done, just type
qunit
And the output should be like
TAP version 13
ok 1 Testing index.js > returnTrue returns true
1..1
# pass 1
# skip 0
# todo 0
# fail 0
Well, due to help of two answers I did localize that problem indeed was in inability of VS to copy needed file into test project.
This can be probably resolved by multiple ways, I found one, idea copied from: http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
Solution is simple: add tag dynamically
In order to achieve this, I've added the following code into tag:
<script>
var fileref = document.createElement('script');
fileref.setAttribute("type", "text/javascript");
var path = 'path'; // here is an absolute address to JS-file on my web site
fileref.setAttribute("src", path);
document.getElementsByTagName("head")[0].appendChild(fileref);
loadjscssfile(, "js") //dynamically load and add this .js file
</script>
And moved my tests into (required also reference to jquery before)
$(document).ready(function () {
QUnit.test("Test #1 description", function () { ... });
});
Similar approach also works for pure test files.

Categories

Resources