Using Ruby Variables in JavaScript - javascript

I'm new to Ruby so I had a question in regards to using some variables throughout my codebase. I have a variable declared in my Ruby file as follows:
#pages = 350
Now, I know that in HAML, I can simply do:
-if #pages = 350, and in HAML with inline javascript, I can do something like:
:javascript
console.log("#{#pages}");
However, I am linking an external JavaScript file in my HAML document, and I was wondering if it would be possible to use my Ruby variables in my external JS document? I need some variables in order to build what I am trying to build. Thanks!
Update as per one of the answers:
In my HAML file, I have the following:
:javascript
printPages(3);
In my external JS file, I have:
$(function() {
window.printPages = function(pages) {
console.log(pages);
}
});

I you are loading static javascript files I really would not recommend trying to insert variables into that code.
Instead, think about how you would provide that to your javascript code.
You could send it to that code as an argument.
<script type="text/javascript" src="./my-external-script.js"></script>
:javascript
runMyExternalFunction(#{#pages})
Or you could add the variable as a data attribute on your page, and your javascript could look for that when it loads.
Haml:
%body data-pages=#pages
JS:
console.log(document.body.dataset.pages) // value of #pages
Update about your javascript:
Using jquery's on page ready event $() for declaring the function is a bad idea. That means that it waits for everything on the page to be compeletely loaded, and then declares the function your page needs.
What you should be doing is setting up all the function that will be needed right away, and then calling those functions when the page is loaded.
They way you have it, the page loads, printPages() is executed (which doesn't exist yet), and then after all that printPages is created and put into the global scope.
So remove the $() from your external script and add it to your HAML instead.
In fact, if your aren't doing anything super fancy with transpiling or bundling, then you can simply declare the function in your external JS file, and it will be available globally. This doesn't work with your code because they way you've declared the function, it would only be available to code within that $() callback.
// js file
function printPages(pages) {
console.log(pages);
}
HAML:
$(() => {
printPages({#pages})
})

Related

Laravel compressing javascript using mix.scripts(); renames function in compressed file

I am compressing a js file like this:
mix.scripts('resources/assets/js/pages/login.js', 'public/js/login.js');
My pre-compressed file contains this function:
function zoomInForm() {
$('#login-page').toggleClass('zoom animated');
........ ........
}
But in my compressed file the function zoomInForm is renamed so I can never call the zoomInForm(); function on my page.
How can I just compress a js file to one line without removing functions?
If the minifier renames the function, it also renames every place that you call it within the JS files.
Generally, you should NEVER have JavaScript outside of your JS files. Not in a script tag, not in an onclick attribute.
If you want to fx. listen to button click, you should create the listener in the JS:
$('#login-page').click(function(){
zoomInForm();
);
While cssBlaster21895 provides you with a real solution to your specific problem, I believe a more correct solution would be to move your JavaScript logic to your JS files.
You can prevent function from being renamed. You can pass uglify options into mix options.
mix.options({
uglify: {
"mangle": {
"except": ["zoomInForm"]
}
}
});
Maybe it can help,but maybe there something wrong with your whole script at all, even double declaring same function, just a guess...
Or try declaring a function the other way:
var zoomInForm = function(){...}
Then call it when you need with zoomInForm() later in the script and see whats happening.

Rails Javascript - Calling a javascript function from the view

I have a javascript file abc.js. I have kept it inside app/assets/javascripts/abc folder.
In my application.js file, I have given
//= require abc/abc
In my view, I need to display the object that is returned by a function inside the abc.js file.
I am calling the function by the following command
%h4.sub-header Test Project
%textarea.form-control{rows: 10}
:javascript
abc.diff(#a, #b)
I am getting the a & b values from the controller.
But the function is not being called. Instead the sentence "abc.diff(a,b)" is being displayed.
Could anyone tell me how to call the function inside my view?
Inside haml javascript blocks you can just do string interpolation. Also indentation is very important in haml (obviously). So your view should look like:
%h4.sub-header Test Project
%textarea.form-control{rows: 10}
:javascript
abc.diff(#{#a}, #{#b});
Without more info it is hard to say more, but in general this is not the preferred way: your code should be precompiled in javascript assets, and generally I define variable or add data attributes to specific items.
So either something like
:javascript
var a = #{#a};
var b = #{#b};
ad inside abs.js.coffee write
$ ->
abc.diff(a,b)
The cleanest solution imho is something like:
%body{'data-a': #a, 'data-b': #b}
and inside abs.js.coffee write
$ ->
a = $('body').data('a')
b = $('body'_.data('b')
abs.diff(a,b)
Of course, this depends whether it applies to your solution, my apologies for digressing :)

How to include javascript file only once

I want to give clients an HTML block they can include in their site, and this HTML will contain some table and image, plus a javascript that will make manipulations over the HTML block.
so I give them the HTML :
<a data-theme="1" data-srv="http://localhost:50987/" class="block1" href="http://myserver/payment/Details">outer information</a><script type="text/javascript" src="http://myserver/Scripts/checkout.js"></script>
in checkout.js I have included JQuery if no Jquery exists in document and do manipulation over the element $('a.block1') ... the problem is when someone puts this block of HTML more then once over the same page, I want that the client will not call "checkout.js" more then once,
I've tried declaring global var inside "checkout.js" and check if it's exists, it works good to stop doing the same manipulation more then once but I want to stop the call to JS al together .
Javascript runs after it loads, you can't stop the JS running, if it is referenced multiple times. It won't be loaded multiple times, so the overhead of it running again is basically nil.
To stop the behavior of the javascript happening again, just put the check at the top level of the file, put the rest of the file in the conditional, and write to a global variable to make sure you don't run again.
if (window._your_unique_id === undefined) {
window._your_unique_id = true;
// the rest of your javascript
}
that will mean nothing in the script runs. You can still define whatever you like in that if statement, though if you define functions and variables in there, you may have to explicitly put them on the window object, because they'll otherwise be local (but then, it is bad practice to have anything implicitly defined global anyway, so it shouldn't make any difference if your code is well structured).
Just deploy your code as a module.
Ie.
(function(window){
if(window.CheckoutModule) return;
// now you're certain there's no global module loaded
var CheckoutModule = window.CheckoutModule = {};
// you can, ie, add a jQuery check here.
if('undefined' != typeof jQuery) {
// do your jQuery thing here.
}
return ;
})(window, jQuery);

Use TAL:defined variable in javascript

I'm creating a page template for a plone-based website. I've defined some variables using the template attribute language:
<tal:macro metal:define-macro="sample" tal:define="var python: here.getThisVar();">
Now I would like to use var in an extern javascript file, that I call by clicking a button inside my template. How can I transfer my variable, that I can work with it in my javascript file?
In your template define a javascript variable by writing it out using TAL like this:
<script type="text/javascript" tal:content="string:var MY_VAR=${view/myVar};"></script>
Now MY_VAR should be available in scope of your external js as long as you call it after the line above...
Another way: inject your variable into HTML using an HTML 5 data attribute::
<div id="myVar" tal:attributes="data-myVar python:here.getThisVar();">
Then read it using JAvaScript/jQuery::
$('#myVar').data('myVar');
There are a variety of ways to do it. All involve constructing Javascript code as if it's text, then returning the result for insertion into a page or rendering as a JS resource in the javascript registry.
If you'd like a robust example that includes provisions for message translatability and works with the JS resource registry, see the way Plone itself does it: https://github.com/plone/Products.CMFPlone/blob/4.2.7/Products/CMFPlone/browser/jsvariables.py

Give preference to JS file function over HTML file

I have two functions of the same name; let's say foo().
One in the HTML file and one in the JS file, which is included in the HTML file. The problem is I want to give preference to the JS file function rather than the HTML file function.
Is there any way to do that, or is there any syntax in JavaScript like [JSFileName].foo(), that may perhaps call the function in the JS file?
Not sure why you want to have two identically-named functions.
The snarky answer is: Just remove the reference to the function you don't want. (If you have control over your html, such a situation shouldn't exist.)
The answer you're looking for: Place the external script tag after the inline script tag.
Make sure the script tag for the js file is after the HTML script tag in which foo is declared.
It's not clear from your question why you have two functions named foo, but based on your [JSFileName].foo() attempt at a solution, I might suggest using objects as namespaces. In your script you could do:
var myScriptFunctions = {
foo: function() {
// do foo stuff
}
}
You can call it with myScriptFunctions.foo() and you won't have two functions competing for the global name foo.

Categories

Resources