How do I use Dojo Toolkit in an Electron application? - dojo

I'm exploring Electron and I've run into a roadblock. I can't figure out how to load the Dojo Toolkit and use it in Electron.
For example, here is the simple "Hello World" for Dojo:
<!DOCTYPE html>
<html>
<head>
<title>Tutorial: Hello Dojo!</title>
</head>
<body>
<h1 id="greeting">Hello</h1>
<!-- load Dojo -->
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"
data-dojo-config="async: true"></script>
<script>
require([
'dojo/dom',
'dojo/dom-construct'
], function (dom, domConstruct) {
var greetingNode = dom.byId('greeting');
domConstruct.place('<em> Dojo!</em>', greetingNode);
});
</script>
</body>
</html>
That works fine in a browser, but doesn't work at all in Electron. After a couple hours of googling and trying 50 different experiments I've gotten nowhere.
Can someone please enlighten me?

While you can disable node-integration as Shwany said, I believe that will effectively render the ipc modules useless, which will probably pose undesirable limitations since you won't be able to communicate between the main and renderer processes.
However, it is possible, with a bit of finagling, to get Dojo to play nice with Electron. There are only a couple of things you need to do in your entry page.
Firstly, force the host-node has feature to false. This can be done by setting it in dojoConfig.has, e.g.:
var dojoConfig = {
async: true,
has: {
'host-node': false
}
}
Secondly, as Shwany pointed out, Dojo is going to see the already-existing require, so we need to move that out before loading Dojo:
// Move Electron's require out before loading Dojo
window.electronRequire = require;
delete window.require;
After loading dojo.js, you can move Dojo's require elsewhere and move Electron's back, if you wish. Whether you want to do this may depend on how you intend to code the client side of your application. Ostensibly, Dojo's global require is never needed, since you can request a context-sensitive require in any defined module via the 'require' module ID.
If you want to see a scaffolded Electron application incorporating Dojo, I created a boilerplate a few weeks ago (though be advised it's currently relying on a fork of electron-packager). If you want to see an example of a more full-blown Electron/Dojo application, I wrote a music player called Nukebox a couple of months ago which uses Dojo and dgrid (though its scaffolding is a bit different than the newer boilerplate).

I have your test code working in Electron.
First, I assume you are trying to load dojo.js from the web. //ajax.googleapis... etc will probably attempt to pull the file from the file system. I added http: to the front of it. That allowed me to open a .html file in the browser and work. I am not sure if that was an oversight or not.
Secondly, because the browser-window has node-integration on by default, 'require' is already defined and it does not understand what you are passing to it because it expects a path not an array. If you construct your browser window with node-integration turned off it should work:
app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600, "node-integration": false});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.openDevTools();
mainWindow.on('closed', function() {
mainWindow = null;
});
});
Note the "node-integration": false. This may cause additional issues if you want to use node integrations in your app. However, your code should work.

Related

NuxtJS possible to generate JUST plain HTML?

I'm really curious if I use NuxtJS right.. I just want to generate HTML pages, so basically I dont need ANY JavaScript!
But Everytime I do generate any page with Nuxt There is a lot of JS in there.
Now I managed to remove ClientSide Scripts with:
render: {
injectScripts: false
},
in the nuxt.config.js .. but now anyway there is a inlineJS script with:
window.__NUXT__={staticAssetsBase:"/_nuxt/static/1614565042",serverRendered:!0,routePath:'"/"'}
or even
<script>window.__NUXT__={staticAssetsBase:"/_nuxt/static/1614566041"}</script>
<script src="/_nuxt/3dacfb6.js" defer></script>
<script src="/_nuxt/47380cc.js" defer></script>
<script src="/_nuxt/fbdf180.js" defer></script>
<script src="/_nuxt/77b577f.js" defer></script>
<script src="/_nuxt/04f2e32.js" defer></script>
in the generated HTML.. I dont understand why there is not a simple mode to just generate very simple HTML pages without ANY overhead.
Its just about re-using components for me and using some very simple variables..
No JS have to be used at all and CSS I'm generating & combining with YARN, so no need for anything else..
Also i dont like the data-* tags .. I really dont need them. I want to create simple HTML pages with no function on clientside, but still having the function of "components" which is injected (serverside) and re-use in multiple pages.
I run Nuxt with this config:
target: 'static',
render: {
injectScripts: false
},
hooks: {
'vue-renderer:ssr:context'(context) {
const routePath = '';
context.nuxt = '';
},
},
to remove as much JS and standard stuff as possible... but seems it still not possible to remove Everything and just generate a plain HTML without anything extra.
So the question is:
How can I generate static pages with NuxtJS and not having to include ANY JS file.. specially not the standard NUXT-JavaScript code?
If you think I better should not use NuxtJS for simple clean HTMl pages tell me :)
Nuxt is not meant to be used as SSR only, it does have the whole hydration part that will bring interactivity to your app even when going full static. You could probably use another SSG like 11ty or hugo to not have any JS loaded.
But you can also use vue-lazy-hydration and prevent the hydration at the top level of your app. It's still kinda in beta but it should do the trick.
“If you think I better should not use NuxtJS for simple clean HTMl pages tell me :)”
You would be better off not using Nuxt. It’s a JavaScript framework built on top of Vue, which makes it super simple to develop SSR SPA applications.
You mention you don’t want to use JavaScript, but you would like access to components and simple variables. To me it sounds like you’d be much better off using PHP, and might enjoy the Laravel framework (though I’d recommend plain old PHP if you don’t want the overhead of an entire framework).
Laravel

What's the best way to add JQuery to Enduro.js

I'd like to be able to use Jquery in my Enduro.js project, but there is not a single sample using it on github Enduro.js page
Libraries seem to be loaded in Enduro.js using RequireJS, wth the line found at the bottom of the default index.hbs :
{{!-- <script data-main="/assets/js/main.js" src="/assets/vendor/requirejs/require.js"></script> --}}
and the following code found un "assets/js/main.js" by default in all Enduro.js samples :
require.config({
baseUrl: '/assets/',
paths: {
// 'jquery': 'vendor/jquery/dist/jquery.min',
},
})
require(['jquery'], function ($) {
$(document).ready(function () {
console.log('requirejs ready to use')
})
})
The Jquery "path" line is commented out, and there is no /vendor directory in /assets by default.
Is there an automated way to install jquery in Enduro.js or is it just simply about creating by hand a /vendor folder, and copying /Jquery inside it ?
Well, there are many ways to use JQuery in Enduro. I'm not sure if it is the best way to import it (it could exist better ones).
In my current project, I'm using the CDN for reasons of efficiency. If you have no problem using CDNs I'd recommend it.
just copy this code:
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous">
</script>
And then, paste it just before closing the body tag.
Another way is to create a folder inside /assets/js called 'vendor' and there, you cat put the jquery-3.3.x.min.js (Or whatever version you would like to use). Of course, you have to download it first from the official site.
After doing that, you just have to import it via HTML (before closing body tag):
<script src="assets/js/vendor/jqueryfile.js"></script>
NOTE: Creating the folder called 'vendor' is optional, you just could paste the file inside /assets/js. And make sure you type the right path to import it.
NOTE 2: remember that you should never touch the files inside _generated, so if you paste the file inside _genereated/assets/js, everything is going to work, but when you migrate your site to production or anywhere else the app will crash.
Hope this helps.

dynamic HTML with worklight?

Is there any way to perform "last minute" substitutions in the HTML (or other) resources that are part of your worklight application?
For example, I want to set the lang and dir attribute on the <html> element based on the end-user's locale.
some background:
I realize I can do dynamic DOM manipulation, but my question comes more from a background of client-server architecture where you have an opportunity on the server-side to replace some variables etc. in your HTML (or other resources) based on the requester's context. We have an existing app already and I'm investigating what it would take to integrate it with worklight including (for performance reasons) moving files from the server-side to the client-side without incurring too much refactoring of the current code.
Update: per the edit to your question, I don't think the below will make any significant impact on your app. Since you say you may move files from the server to client, this means like network traffic and with today's devices I suspect this may even be a boost to the performance rather than a penalty.
My suggestion is to try the below if the above is what you're planning to do.
I'm not even sure how else would you even do that from the server - change the application's UI based on the user's device local's, from the server. Doesn't make much sense to me to do that remotely.
To answer your question, I'll provide some background information that is relevant, I think, to a good user experience in this kind of scenario (as I see it):
By default, Worklight dismisses the splash screen once the framework has finished loading.
However, if you're using Worklight 6.2 then you can use the extended Splash Screen feature to display the splash screen for a longer duration, and during that time you could perform the required tasks -- like altering the UI based on the user's locale. Once you're done, you can then programmatically dismiss the splash screen on your own.
Reading materials:
Common UI Controls training module (slide #29)
Managing the splash screen user documentation topic (for both JS and Native support)
Example:
You need to uncomment the following in common\js\initOptions.js:
// # To disable automatic hiding of the splash screen uncomment this property and use WL.App.hideSplashScreen() API
//autoHideSplash: false,
You can then dismiss the splash screen when ready:
function wlCommonInit() {
function changeUiBasedOnLocale();
...
...
}
function changeUiBasedOnLocale() {
... // get device local
... // use JS to alter CSS
WL.App.hideSplashScreen();
}
Any basic DOM manipulation will help. Here is one example with D3.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Test</title>
<script type="text/javascript" src="d3.js"></script>
</head>
<body>
<script type="text/javascript">
d3.select("html").attr("lang","en_EN");
</script>
</body>
</html>

Dojo Builds...? What now?

A while back, I looked into a solution for the "flash of unstyled content" when using Dojo and Dojo themes. Someone suggested to combine everything by creating a build, and it'll reduce the load/parse time and remove the need to use preloader overlays, etc.
However, it seems like Dojo is severely lacking in straightforward, "real world" useage examples and tutorials for a lot of its functionality, this especially. A lot of the resources tell you how to set up a build, but not how to implement it.
Let's say I have this in "pageinit.js":
require([
'dojo/parser',
'dojo/dom',
'dojo/dom-class',
//etc...
'dijit/form/ValidationTextBox',
'dijit/form/CheckBox',
// etc...
// Dom Ready call
'dojo/domReady!']
function(
Parser,
Dom,
Class,
// etc...){
// do stuff with parser, dijits, so on.
}
)
Some of the require calls were removed for brevity, but there's a handful of dom requires, style classes, some dijits, etc. When this page loads, there's the flash of unstyled content and then it's fine.
Using the Dojo Web Builder, I selected the modules I'm using, and ran it. It downloaded a zip with a lot of files under it, including a new dojo.js and custom_layer.js.
So my question is now, how do I use these new combined and minified files in place of my "non-build" version? What do I require? Or do I?
So confused...
First, let's understand how the AMD(require/define) API works.
require([
'dojo/parser',
'dojo/dom',
'dojo/dom-class'
], function(parser, dom, domClass){
});
This is going to call the require function, specifying that I need three modules in order to do some work. require will get each module. If will determine if the module has been loaded. If it hasn't it will asynchronously get the file, and load the module into the javascript runtime. Once require has retrieved all of your required modules, it will execute your callback (the function) passing the modules as arguments to the function.
Next, let's understand the build. The dojo build does exactly what you describe. It will compress a bunch of the individual files into a single file. this will make the page load quicker and prevent that 'flash' that you describe.
Finally, putting it all together, you should include the custom_layer.js file along with the dojo.js file.
<script type="text/javascript" src="path/to/dojo/dojo.js" />
<script type="text/javascript" src="path/to/custom_layer.js" />
The web browser will load these two files and evaluate the code. Instead of lazily loading each module in it's own file, the module will already be loaded because it was defined in the custom_layer.js.
So, the answer to your final question is that you should NOT change any of your code based on the specific version of code (source vs custom build) that you are using. Using the AMD api, it should just work.
Not sure if it's best practice or not, but I was seeing the flash of unstyled content when I first started (a few days ago), and saw several examples somewhere that takes care of by just hiding the <body>. Parse will unhide it when it's ready to show something.
<body style="visibility: hidden;">

Google's hosted dojox.gfx

I'm using the following html to load dojo from Google's hosting.
<script src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("dojo", "1.1.1");</script>
<script type="text/javascript">
dojo.require("dojox.gfx");
...
This errors out on the requre line with an error like dojox.gfx is undefined. Is there a way to make this work, or does Google not support the dojox extensions?
Alternatively, is there another common host I can use for standard dojo releases?
Differently from when you reference the .js files directly from the <script> tag (note that google js api also supports this, see here), google.load is not synchronous. This means that when your code reach google.load, it will not wait for dojo to be fully loaded to keep parsing; it will go straight to your dojo.require line, and it will fail there because the dojo object will be undefined.
The solution (if you don't want to use use the direct <script> tag), is to enclose all your code that references dojo in a start function, and set it will as a callback, by doing:
google.load("dojo", "1.1.1", {callback: start});
function start() {
dojo.require("dojox.gfx");
...
}
or
google.setOnLoadCallback(start);
google.load("dojo", "1.1.1");
function start() {
dojo.require("dojox.gfx");
...
}
A better question is - why would you want to? If you are developing on your localhost then just use a relative path, if you're developing on an internet facing server - stick the dojo files on that.
Also - make sure you're not falling foul of the same origin policy
I believe that google becomes the namespace for your imported libraries. Try: google.dojo.require.
Oh! And as pointed out below, don't forget to use google.setOnLoadCallback instead of calling your function directly.
dojox is practically unmaintained, and will be taken out from dojo-2. There are major problems with most widgets in dojox, there is only a few good.
IMHO dojo should be self-hosted, because there are always things what you need to overwrite - for example, you need some fix in this dojox.gfx.