How to use the variable from a <script></script> after adding it? - reactjs

http://cloudinary.com/blog/how_to_build_an_image_library_with_react_cloudinary
(except I used create-react-app instead of manually configuring webpack)
Where the script is added to of index.html:
<script src="//widget.cloudinary.com/global/all.js" type="text/javascript"></script>
and then the functionality is included in a component:
uploadWidget() {
cloudinary.openUploadWidget({ cloud_name: 'CLOUD_NAME', upload_preset: 'PRESET', tags:['xmas']},
function(error, result) {
console.log(result);
});
}
However I am getting the error: 'cloudinary' is not defined
Is cloudinary supposed to be available there after simply adding the script? Am I missing a step?

Try to access it through window.cloudinary. Also make sure that the script is included before your React script is included.

Related

Unit testing in Kotlin JS

I have a simple project in Kotlin JavaScript using React. I've added unit tests, but when I run them, they seem to call main method of production code, and fail on initialization, when trying to reach unexsistent DOM structure. Despite the fact that the tested class does not reference React or DOM in any way.
The error looks the same when run from Intelij IDEA or by gradlew build (I've replaced the full path to my project with /APP/ for clarity):
Testing started at 17:51 ...
> Task :cleanBrowserTest
> Task :packageJson UP-TO-DATE
> Task :testPackageJson UP-TO-DATE
> Task :kotlinNodeJsSetup SKIPPED
> Task :kotlinNpmInstall
> Task :compileKotlinJs
> Task :processResources
> Task :mainClasses
> Task :compileTestKotlinJs
> Task :testProcessResources NO-SOURCE
> Task :testClasses
> Task :browserTest
(...)
Error: Target container is not a DOM element.
at render (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:25359:13)
at render_0 (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:29868:5)
at main (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:146311:5)
at Object.<anonymous> (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:146315:3)
at http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:146289:37
at Object.../example/kotlin/example.js (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:146292:2)
at __webpack_require__ (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:20:30)
at http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:146346:134
at Object../kotlin/example-test.js (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:146351:2)
at __webpack_require__ (http://localhost:9876/absoluteD:/APP/build/js/packages/example-test/adapter-browser.js?92ccabfdcfa982960828b65b2f4e2683080859b4:20:30)
HeadlessChrome 81.0.4044 (Windows 10.0.0) ERROR
Uncaught Error: Target container is not a DOM element.
at d:/APP/build/js/node_modules/react-dom/cjs/react-dom.development.js:24828:1 <- D:/APP/build/js/packages/example-test/adapter-browser.js:25359:7
(...)
> Task :browserTest FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':browserTest'.
> command 'C:\Users\Arsen\.gradle\nodejs\node-v12.14.0-win-x64\node.exe' exited with errors (exit code: 1)
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 10s
8 actionable tasks: 6 executed, 2 up-to-date
Minimal example:
./build.gradle.kts
plugins {
id("org.jetbrains.kotlin.js") version "1.3.70-eap-184"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
maven("https://kotlin.bintray.com/kotlin-js-wrappers/")
mavenCentral()
jcenter()
}
dependencies {
implementation(kotlin("stdlib-js"))
implementation("org.jetbrains:kotlin-react:16.13.0-pre.94-kotlin-1.3.70")
implementation("org.jetbrains:kotlin-react-dom:16.13.0-pre.94-kotlin-1.3.70")
implementation(npm("react", "16.13.1"))
implementation(npm("react-dom", "16.13.1"))
testImplementation(kotlin("test-js"))
}
kotlin.target.browser {
}
./settings.gradle.kts
pluginManagement {
repositories {
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
mavenCentral()
maven { setUrl("https://plugins.gradle.org/m2/") }
}
}
rootProject.name = "example"
./src/main/resources/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="root"></div>
<script src="example.js"></script>
</body>
</html>
./src/main/kotlin/Main.kt
import react.dom.*
import kotlin.browser.document
fun main(args: Array<String>) {
render(document.getElementById("root")) {
}
}
./src/main/kotlin/DummyClass.kt
class DummyClass {
fun foo(): String {
return "foo"
}
}
./src/test/kotlin/ExampleTest.kt
import kotlin.test.*
class ExampleTest {
#Test
fun foo() {
assertEquals(DummyClass().foo(), "foo")
}
}
The error does not occur if I don't reference production code at all (remove DummyClass().foo() from the test), or when main method does not call render(document.getElementById("root")).
PS: If it matters I run the code on Windows
This is not the right answer - but something that will unblock you immediately.
This answer pointed out that
the test environment doesn't supply the DOM with an app id.
So too is the case with our test framework - it is not supplying an element with id 'root'.
This led me to believe that the main/resources/index.html is not being used by the test framework. The exception trace confirms that - notice how it starts from __webpack_require__
The ideal solution would be to either have karma or webpack supply our code with the correct index.html; but I don't know how to accomplish that.
In the meantime, you can
Remove <div id="root"></div> as part of index.html
Have your kotlin code generate it, as below:
./src/main/kotlin/Main.kt
fun main(args: Array<String>) {
document.body!!.insertAdjacentHTML("afterbegin", "<div id='root'></div>" )
render(document.getElementById("root")) {
}
}
Hope that helps
I had the same issue and I fixed it. Thanks to the workaround of #Yogesh Nachnani I understood what was missing. In fact all resources files are not included. So, first I created a new workaround using fs-extra (copying files from resources to the local directory) and then as I was exploring Karma I figured out that the cleanest solution was to use proxies to redirect requests to resources. Therefore I used the following code into karma.config.js:
const path = require('path');
const resourcesSourcePath = path.resolve(__dirname, '../../../../build/processedResources/js/main');
const setupFile = path.resolve(__dirname, '../../../../src/test/setup.js');
config.files.unshift(setupFile);
config.proxies = {
"/strings/": "absolute" + resourcesSourcePath + "/strings/",
"/css/": "absolute" + resourcesSourcePath + "/css/",
"/images/": "absolute" + resourcesSourcePath + "/images/"
}
This way, if you have a lot of resources you won't have to wait for the copy of the content. However, I didn't find a way to launch karma on index.html, but as I can now access all resources, I just used the workaround proposed by #Yogesh Nachnani because the HTML file usually doesn't have much influence into tests (at least for me). Therefore I added a setup.js file which only contains:
document.body.insertAdjacentHTML('afterbegin', "<div id='root'></div>");
It prevents the rendering target error when you are using render(document.getElementById("root")){} for React.

angularjs directive not being loaded when angularjs-dragula package is required

I am in the process of migrating our .NET Framework project over to .NET Core. And where we previously relied on the BundleTable tools in .NET Framework. We are now using webpack.
I have a directive that uses a package 'angularjs-dragula'. The webpack entry definition is as follows
'bundles/grouping':
[
"./Scripts/angularjs-dragula.js",
"./App/components/grid.directive.js",
"./App/components/inline-edit.directive.js",
"./App/services/grouping.service.js",
"./App/components/grouping/grouping.directive.js"
],
I initialize the directive as follows:
(function () {
angular.module('App').requires.push(angularDragula(angular));
angular
.module('App')
.directive('appCustomGrouping', appCustomGrouping);
appCustomGrouping.$inject = ['urlService', 'groupingService', 'dragulaService' ];
function appCustomGrouping(urlService, groupingService, dragulaService) {
...
As it is, the page never loads grouping.directive. And there are no errors. Unless i remove the dragula file in the webpack entrypoint. The directive will then load, but complain:
ReferenceError: angularDragula is not defined[Learn More]
I have tried relying on webpack to import the package, and removed it from the entry definition. I installed angularjs-dragula into my node_modules, and used
var angularDragula = require('angularjs-dragula');
(function () {
angular.module('App').requires.push(angularDragula(angular));
angular
.module('App')
.directive('appCustomGrouping', appCustomGrouping);
appCustomGrouping.$inject = ['urlService', 'groupingService', 'dragulaService' ];
function appCustomGrouping(urlService, groupingService, dragulaService) {
...
However this results in the same behavior.
The angularjs-dragula package works, since we were using it before the move to webpack. However now it seems to be silently failing, and taking the rest of the directive with it?
How can I begin to diagnose this issue?
The AngularJS wrapper for Dragula is unusual in that it places on global scope a function named angularDragula. That function registers the dragula module with AngularJS when the function is invoked with angular as an argument. It returns a string with the module name "dragula".
angularDragula(angular)
angular.module("app",["dragula"])
.run(function(dragulaService) {
console.log(dragulaService);
})
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angularjs-dragula/dist/angularjs-dragula.js"></script>
<body ng-app="app">
<h1>Hello AngularJS!</h1>
</body>
the page never loads grouping.directive
How can I begin to diagnose this issue?
I would use the Developer Console to insert breakpoints. Then examine variables.
The above example loads AngularJS with Dragula and successfully logs the dragularService.

AngularJS app does not load on iPad / iPhone Safari (works only after page refresh / second load and afterwards)

I have a really weird issue with my AngularJS app on iPad / iPhone safari.
The issue occurs only of first load (after clearing history / website data).
The issue that the application wont start at all - I get a white page and the console (from MacBook develop tools) is full with errors,
Sometimes I'm getting lots of
TypeError: undefined is not an object (evaluating 'd.module')
ReferenceError: Can't find variable: angular
TypeError: undefined is not an object (evaluating 'd.$$minErr')
ReferenceError: Can't find variable: angular
TypeError: undefined is not an object (evaluating 't.noop')
ReferenceError: Can't find variable: angular
ReferenceError: Can't find variable: angular
...
Sometimes I'm getting Error: $injector:unpr - Unknown Provider
And sometimes Error: $injector:nomod - Unknown Provider
But if I hit page refresh after getting the white page / errors - all works just fine.
This is part of the third party js libs/plugins I include on my index.html
<script src="resources/plugins/head.load.min.js"></script>
<script src="resources/plugins/modernizr-custom.js"></script>
<script src="resources/lib/jquery/jquery-2.1.0.min.js"></script>
<script src="resources/lib/angular/angular.min.js"></script>
<script src="resources/lib/angular/angular-resource.min.js"></script>
<script src="resources/lib/angular/angular-route.min.js"></script>
<script src="resources/lib/angular/angular-animate.min.js"></script>
<script src="resources/lib/angular-translate/angular-translate.min.js"></script>
<script src="resources/lib/angular-translate/angular-translate-loader-static-files.js"></script>
<script src="resources/lib/angular-ui/ui-bootstrap-custom-tpls-0.14.1.min.js"></script>
<script src="resources/lib/ng-table/ng-table.min.js"></script>
<script src="resources/lib/file-upload/ng-file-upload-shim.min.js"></script>
<script src="resources/lib/file-upload/ng-file-upload.min.js"></script>
I'm really lost here...
Another thing: I have noticed on my Mac (Resources->Scripts) that if I open a file, lets say Resources->Scripts->FileNameOne.js the content is actually of another file FileNameTwo.js ??? is it a flaw of the dev tools of the Mac that confuses the names/content or can it be related to the problem???
Any Ideas?
Here is the complete solution with Grunt
Content of the Gruntfile.js
'use strict';
module.exports = function(grunt){
grunt.initConfig({
concat: {
dist: {
src: ['WebContent/resources/plugins/head.load.min.js', 'WebContent/resources/plugins/modernizr-custom.js',
'WebContent/resources/lib/jquery/jquery-2.1.0.min.js',
'WebContent/resources/lib/angular/angular.min.js', 'WebContent/resources/lib/angular/angular-resource.min.js', 'WebContent/resources/lib/angular/angular-route.min.js', 'WebContent/resources/lib/angular/angular-animate.min.js',
'WebContent/resources/lib/angular-translate/angular-translate.min.js', 'WebContent/resources/lib/angular-translate/angular-translate-loader-static-files.js',
'WebContent/resources/lib/angular-ui/ui-bootstrap-custom-tpls-0.14.1.min.js',
'WebContent/resources/lib/ng-table/ng-table.min.js',
'WebContent/resources/lib/websockify/util.js', 'WebContent/resources/lib/websockify/base64.js', 'WebContent/resources/lib/websockify/websock.js',
'WebContent/resources/lib/file-upload/ng-file-upload.min.js',
'WebContent/resources/js/services/*',
'WebContent/resources/js/services/dialogs/*',
'WebContent/resources/js/controllers/*',
'WebContent/resources/js/directives/*',
'WebContent/resources/plugins/*'],
dest: 'dist/myWebAppInOneFile.js',
},
},
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['concat']);
};
Then just call grunt from the relevant folder and you'll get your file
What build toolchain are you using. One option would be to concatenate all of the includes into a single file, this should stop the error where the wrong scripts are being loaded - As mentioned by Marcus H
Gulp
https://github.com/contra/gulp-concat
Grunt
https://github.com/gruntjs/grunt-contrib-concat

Correct way of using grunt's "bower_concat" and "angular-i18n"

If one is not using grunt's "concat" and "bower_concat", angular-i18n is used this way:
<html ng-app>
<head>
...
<script src="angular.js"></script>
<script src="i18n/angular-locale_de-de.js"></script>
...
</head>
</html>
(According to here: https://docs.angularjs.org/guide/i18n)
But... of course: I'm using concat and bower_concat.
I'm using them this way:
First I use bower_concat and create build/bower-concat.js
Note: bower_concat reads every bower.json of every subdirectory living in bower_components and it concatenates all the main files.
Note 2: the bower.json of "angular-18n" has "ignore": ["**/.*", ...
Then I concat all my js's (my controllers, etc), into build/inouse-concat.js
Finally I concat bower-concat.js with inhouse-concat.js into all-concat.js
<script src="build/all-concat.js"></script>
So I though that I could include the corresponding locale, "angular-i18n/angular-locale_de-de.js", in the third step, like this:
// inhouse js with bower's js with angular's i18n into one file
allJsConcat: {
src: ['build/bower-concat.js', 'bower_components/angular-i18n/angular-locale_de-de.js', 'build/inhouse-concat.js',],
dest: 'build/all-concat.js',
}
But this is not working. I'm getting:
Uncaught ReferenceError: require is not defined
Question: how would you recommend using grunt, concat, and bower_concat with angular's locale js? what am I doing wrong?
Damn, I hate to answer my own questions because of rushing in asking...
Anyway, this worked:
Gruntfile.js
bower_concat: {
all: {
dest: 'build/bower-concat.js',
cssDest: 'build/bower-concat.css',
exclude: [
'angular-i18n'
],
bowerOptions: {
relative: false
}
}
},
concat: {
...
allJsConcat: {
src: ['build/bower-concat.js', 'bower_components/angular-i18n/angular-locale_de-de.js', 'build/inhouse-concat.js',],
dest: 'build/all-concat.js',
}
}
The trick was using the exclude parameter of grunt-bower-concat.
There is also a mainFiles parameter that I think would do the trick too:
mainFiles
Some Bower components don’t list their main files or (more likely)
don’t have bower.json file at all. In this case bower-concat will try
to guess main file but sometimes it can’t or choose wrong one. You
could explicitly define main files for that components.
So I think that using this would work too:
mainFiles: {
'angular-i18n': 'angular-locale_de-de.js',
}
Without doing the "three file concat" (so its more elegant)

How to use CryptoJS with Angular

All is in the title. I want to use the CrytoJS lib in an AngularJS application and I can't get rid of this.
I install crytoJS with bower:
bower install cryptojslib
Then I load the lib I need :
<script type="text/javascript" src="/public/system/lib/cryptojslib/rollups/md5.js"></script>
<script type="text/javascript" src="/public/system/lib/cryptojslib/components/enc-base64-min.js"></script>
And I try to use the CryptoJS like that :
var pwd = CryptoJS.MD5(params.email+'|'+params.password).toString(CryptoJS.enc.Base64);
When I run this code, I've got the following error :
'CryptoJS is not defined'
I've read that it should be possible to wrap the CryptoJS into a module but I don't know how to do.
Any help would be greatly appreciated.
JM.
Shouldn't be any problems with AngularJS and CryptoJS. I setup a quick Plunker that has a hash created in a controller. No errors...
http://plnkr.co/edit/kzrr3EdHNXELVof6DVSp?p=preview
In the controller:
$scope.hash = CryptoJS.MD5("Message");
In the HTML:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/md5.js"></script>
Is this different than what you are trying?
include the jsfile from rollups folder.
Even I was also getting the same error 'CryptoJS is not defined'. After this change, CryptoJS object was available
var hashObj = CryptoJS.SHA512(myString);
var hashString = hash.toString(CryptoJS.enc.HEX);

Resources