How to access custom javascript functions via browser-console in Rails 6 - ruby-on-rails

For the sake of debugging the javascript-part of a Rails 6 (version 6.0.0.rc1) web application I want to use my custom javascript functions also in the Chrome console (aka. Inspect).
Back when I used just static HTML files to build a website (as opposed to using a web-framework like Rails as of right now) you would simply embed the JS file in the DOM like this
<!-- custom JS -->
<script src="js/custom.js"></script>
and could instantly access and execute all custom functions that were placed in this file.
Background:
The JS file is placed at the correct rails 6 specific directory as provided in this article: How to require custom JS files in Rails 6
Note:
The rails 6 application also uses the JS file already, since the browser shows the console log message.
Here is the full content of the JS file:
// app/javascript/packs/custom.js
console.log("loaded custom.js successfully")
function sayHello () {
console.log("Hello good Sir or Madam!")
}
Expectation: I am expecting to open the browser's (Chrome) console and be able to use the sayHello() function in the console.
However, when I do so, I get an error message in the console stating:
Uncaught ReferenceError: sayHello is not defined

Try something like
sayHello = ()=>{
console.log("Hello good Sir or Madam!");
}
then you can evoke in console:
>sayHello();

Related

How to call a javascript function inside a rails view?

I did just a upgrade from RAILS 5 to RAILS 6 and I see that all rails views are not able to call a javascript function as before in RAILS 5.
I have an external javascript file located under
app/javascript/packs/station.js
This is is embeded in in app/views/layouts/application.html.erb as
<%= javascript_pack_tag 'station' %>
This is the code how I call the javascrpt function from html.erb file :
<%= text_field_tag(:station_text_field, ... ,
onkeyup: "javascript: request_stations(); ") %>
When I try to call a function thats is part of the station.js then I get an error in the browser developmer view: ReferenceError: request_stations is not defined
But I can also see in the brwoser view, under Debugger :
Webpack / app/javascript / packs / station.js
and the javascript function I want to call.
So it seems that this script was loaded by the browser.
In contrast, when I just copy and paste these few lines that represent this javascript function direct into the template view file (...html.erb), something like :
<script>
function request_stations ()
{
alert("calling request_stations");
};
</script>
then - it works as expected !
By default, variables/functions defined inside JavaScript files that are packed by Webpacker will not be available globally.
This is a good thing, because it prevents global naming conflicts. Generally speaking, you don't want to reference javascript functions/variables from your view. You instead want to write JavaScript in a way that attaches functionality to DOM nodes using their id or other attributes.
Here is a basic example based on the code you provided:
# in your rails view
<%= text_field_tag(:station_text_field, ..., id: 'station-text-field') %>
// in your javascript
function request_stations() {
alert("calling request_stations");
};
const stationTextField = document.querySelector("#station-text-field");
stationTextField.addEventListener('keyup', (event) => {
request_stations();
});
Agree with mhunter's answer.
This post helped me get a grounding on this difference in Rails 6: https://blog.capsens.eu/how-to-write-javascript-in-rails-6-webpacker-yarn-and-sprockets-cdf990387463
What I don't see in your question is whether or not you did this in app/javascript/packs/application.js:
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
require("station")
The big difference in Rails 6 is that you have to deliberately:
require a JS file
deliberately export something from that file
deliberately import that something, in the file where you want to use it.
So if there is a function in station.js that you want to use, connect the steps above. Start with a simple function in station.js that fires upon DOMContentLoaded, and add a console.log("hey, station.js is alive and well"). If you don't see it, then something in those 3 steps is not right.
In pre-Rails6, you had a "garden" of JavaScript, just by virtue of being in the asset pipeline. In Rails 6, you have to be more deliberate.

openpgp.initWorker is not a function

Please help...I am trying to get openPGP.js working in an existing ASP.Net MVC Web Application.
I first started by adding the following html script tags:
<script src="#Url.Content("~/Scripts/openpgp.min.js")"></script>
<script src="#Url.Content("~/Scripts/openpgp.worker.min.js")"></script>
and I got this error on loading my page:
ReferenceError: importScripts is not defined
So I did some research and added RequireJS to my page, like so:
<script data-main='#Url.Content("~/Scripts/openpgp.min.js")' src="#Url.Content("~/Scripts/require.js")"></script>
Then in the event handler in which I intend to run my decryption logic, I have the following code:
async function decryptBBRecording(commId) {
var openpgp = require(['openpgp']);
await openpgp.initWorker({ path: 'openpgp.worker.js' }) // set the relative web worker path
...
...
...
}
and it is on that "await" line that I am getting
TypeError: openpgp.initWorker is not a function
I'm thinking this is because I have not loaded the openpgp.worker.min.js file. But when I do so via script tag, I get the following errors:
ReferenceError: importScripts is not defined
and when I do so via require(["#Url.Content("~/Scripts/openpgp.worker.min.js")"]); I get this:
Error: Script error for "openpgp"
ReferenceError: importScripts is not defined
Please can you provide me with guidance on how to get this working?
Answer provided here.
You don't have to include openpgp.worker.min.js on the page directly. You also shouldn't need require.js and the call to require. Just include openpgp.min.js on the page, it will globally define openpgp, and then call openpgp.initWorker as you are doing.

How to use a 3D stl viewer on Ruby on Rails

I found this javascript plugin that allows to visualize STL files in 3D:
https://www.viewstl.com/plugin/
The example works very well, the problem is that I can not find how to put that into a rails template. I took all the javascript files to my assets/javascript, then I added the respective '// ​​= require' in aplication.js, I took the small script with the div:
<div id="stl_cont" style="width:500px;height:500px;margin:0 auto;"></div>
<script>
var stl_viewer=new StlViewer(
document.getElementById("stl_cont"),
{ models: [ { filename:"viewstl_plugin.stl" } ] }
);
</script>
and put them in my template but it does not work. Watching the console of my browser I found the following error: ReferenceError: importScripts is not defined. I saw that it has to do with web workers and that an importScripts only works inside them but this problem does not appear in the test.html so I guess something I'm doing wrong when putting them in rails that blocks or prevents the correct operation of importScripts.
I apologize for my lack of fluency in English.
Help :(

"document" in mozilla extension js modules?

I am building Firefox extension, that creates single XMPP chat connection, that can be accessed from all tabs and windows, so I figured, that only way to to this, is to create connection in javascript module and include it on every browser window. Correct me if I am wrong...
EDIT: I am building traditional extension with xul overlays, not using sdk, and talking about those modules: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules
So I copied Strophe.js into js module. Strophe.js uses code like this:
/*_Private_ function that creates a dummy XML DOM document to serve as
* an element and text node generator.
*/
[---]
if (document.implementation.createDocument === undefined) {
doc = this._getIEXmlDom();
doc.appendChild(doc.createElement('strophe'));
} else {
doc = document.implementation
.createDocument('jabber:client', 'strophe', null);
}
and later uses doc.createElement() to create xml(or html?) nodes.
All worked fine, but in module I got error "Error: ReferenceError: document is not defined".
How to get around this?
(Larger piece of exact code: http://pastebin.com/R64gYiKC )
Use the hiddenDOMwindow
Cu.import("resource://gre/modules/Services.jsm");
var doc = Services.appShell.hiddenDOMWindow.document;
It sounds like you might not be correctly attaching your content script to the worker page. Make sure that you're using something like tabs.attach() to attach one or more content scripts to the worker page (see documentation here).
Otherwise you may need to wait for the DOM to load, waiting for the entire page to load
window.onload = function ()
{
Javascript code goes here
}
Should take at least diagnose that issue (even if the above isn't the best method to use in production). But if I had to wager, I'd say that you're not attaching the content script.

jasmine not loading my custom js file

I am unable to get jasmine to load my custom javascript file, even though it works perfectly in the browser. I've reduced the javascript to the minimum to avoid any possibility of errors and I still get a failing test on the simplest thing.
Custom ARB.js file:
$(document).ready(function() {
alert('typeof ARB: ' + typeof ARB);
});
ARB = {};
ARB.VERSION = "V1.01.00 2012-08-24";
jasmine configuration file snippet (I'm on Rails 3.0.9):
src_files:
- "public/javascripts/**/*.js"
- "public/javascripts/ARB.js"
This test:
it('should define the custom javascript functions', function() {
expect(typeof ARB).toEqual('object');
});
fails with:
Expected 'undefined' to equal 'object'.
jQuery gets loaded and so does my application.js file. When running jasmine, I get no alert message, but I do when I run my app.
What am I missing?
UPDATE: If I remove the $(document).ready function, jasmine passes all the tests - what's that all about?
shioyama gave me the pointer that I needed to figure this out: my custom ARB.js file was getting loaded before the jquery files so it didn't have access to the $(document).ready function. What I had to do was explicitly spell out the order in which my javascript files were to be loaded. Here's what I put in my jasmine config file at /spec/javascripts/support/jasmine.yml:
src_files:
- "public/javascripts/**/jquery.js"
- "public/javascripts/**/jq*.js"
- "public/javascripts/**/application.js"
- "app/assets/javascripts/**/*.js"
- "public/javascripts/ARB.js"
I first force the main jquery.js file to load, then all the other jquery files, then application.js, then any other javascript files that are located in the assets directory, and finally my custom javascript file.
This works for me because I'm still on Rails 3.0.9 and starting the migration to 3.1+ and the asset pipeline.

Resources