Getting going with jsbundling-rails - ruby-on-rails

Trying to grok how to work with js files in Rails 7 using the jsbundling-rails gem and ES modules...
In short, I want to code up functions and have them available in the page.
Here's a simple example. Working with app/javascript/controllers/application.js....
If I paste
alert("HI");
I get an alert in the browser so I know I'm in the right file.
Now, if I paste a simple function
function hello() {
alert("hello");
}
That function does not appear in the compiled js file.
I've tried including the export keyword in front of the function as well...
export function hello() {
alert("hello");
}
I don't know if it's the gem or the way I am writing javascript, but I'm not sure how to proceed.

window.hello = function(){
alert("hello");
}

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.

"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.

casperjs: how to include other javascript files during unit tests in tests themselves?

I am doing some unit test in casperjs and I got stuck: how do include dependency file from the test itself? Included javascript file can be just a bunch of functions, and does not declare any interface (module.exports = ... etc).
I know I can include from the command line
$ casperjs test --include=./my-mock.js mytest.js
but how can I include files from the test itself?
Putting following on the top does not work for me... my_mock is undefined
casper.options.clientScripts = ["./my-mock.js"]; //push() does not help either
//mytest.js is below
// ------------------------------------------
casper.test.begin('ajax mock test', function suite(test) {
my_mock.setFetchedData("bla");
my_mock.doRequest();
test.assertEquals( ......);
test.done();
});
// ------------------------------------------
CasperJS version 1.1.0-DEV using phantomjs version 1.9.1
Using phantom.injectJs method is the best option I've found so far. E.g. you're having two files in your directory: "tests.js" and "settings.js". You want to include "settings.js" into "test.js". The first thing you should do with your "test.js" is write the following:
phantom.injectJs('settings.js');
casper.test.begin(...
...
The reason that clientScripts isn't working is that it is loaded on each page load, so you don't have access to the objects/functions defined in the file outside of a casper.evaluate() call.
You can use require() to pull in modules, however you may need to modify your included script to work with this method.
Here is what I changed your mytest.js to:
var my_mock = require('my-mock');
casper.test.begin('ajax mock test', function suite(test) {
my_mock.setFetchedData("bla");
my_mock.doRequest();
//test.assertEquals( ... );
test.done();
});
And this is a quick script (my-mock.js) that I threw together to print out when you use the functions you provided.
module.exports = {
setFetchedData: function(a) {
console.log('setFetchedData: ' + a);
},
doRequest: function() {
console.log('doRequest');
}
};
I found useful this sample demonstrating --includes option:
$ casperjs test tests/ --pre=pre.js --includes=inc.js --post=post.js
to load functions that you often use in your tests.

when & how dust.render will get call

I have written dust js I call render function from my jquery local function.
Anyone please example how dust render get back. Do I need to call in onload function or not?
dust.render("tmp_skill", json_object, function(err, html_out) {
//HTML output
$('#page').html(html_out);
console.log(html_out);
});
your code is ok, you can call the render method at any time. if you call it in the onload, you have to compile and load that template (tmp_skill) in the dust cache previously.
the steps to render dust are:
1) compile the template
2) load it to the dust cache with a name.
3) render the template
SO
var compiled = dust.compile("Hello world {name}", "tmp_skill");
dust.loadSource(compiled);
dust.render("tmp_skill", json_object, function(err, html_out) {
//HTML output
$('#page').html(html_out);
console.log(html_out);
});
Anything you need you can read our wiki. you will find a lot of documentation and examples here: https://github.com/linkedin/dustjs/wiki
I suppose this question is related to your previous question, How to write dustjs in php code without nodejs
I tested your code and it works just fine.
do check your browser's console to see if there are errors after loading the page.
also, do use the linkedin fork of dust: https://github.com/linkedin/dustjs - it's much more actively developed.

Why isn't jquery working in Rails 3.1?

If I go to http://localhost:3000/assets/application.js my code (which works fine in 3.0) exists, because I've referenced it fine in the new application.js assets pipeline file:
$(document).ready
(function(){
$('input.ui-date-picker').datepicker({
dateFormat: 'dd-mm-yy'
});
});
But it's not being called. Jquery is present, too, and my gemfile got upgraded ok. What could be wrong?
OK, the problem was that I had a number of bits of code within a .js file I'd called various.js, and not all of them were wrapped in $(document).ready... }); Once I added that to each separate bit of code it worked fine. Also, I have to restart the server each time I make a change to the .js file - just touching it doesn't work for me. I found a simple Hello World alert really useful in debugging this (just in case anyone out there is as new to jquery as me!):
$(document).ready(function() {
alert("Hello world!")
});

Resources