46

Hey is there a way I can do this in haml?

:javascript
   var Tab = <%= @tab %>

I could just add a helper I guess like:

<script>
  var Tab = '<%= @tab %>'
</script>

But it'd be nice to use HAML!

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Alex Fox
  • 1,175
  • 2
  • 15
  • 27

2 Answers2

103

You can use the string interpolation syntax (#{...}) :

:javascript
   var tab = #{@tab}

Take care of correctly escaping, however.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
-23

This is a terrible way to structure code.

Inline JavaScript is bad enough. Inline JavaScript with ERb inside puts you straight into hell.

JavaScript should be in external static files. That way the browser can cache them, and you can use JavaScript as a real programming language.

In your case, I'd recommend something like:

(Haml file)

#tab= @tab

(CSS file)

#tab { display: none }

(Javascript file)

var Tab = $('#tab').innerHTML();

That way everything stays static and maintainable, and you're not mixing JS and HTML.

Marnen Laibow-Koser
  • 5,959
  • 1
  • 28
  • 33
  • 1
    One thing that escaped my notice the first time: JavaScript variable names should normally begin with a lowercase letter (unless the variable refers to a constructor). – Marnen Laibow-Koser Mar 15 '12 at 04:21
  • This is one of those reasons : http://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html – mhenrixon Jun 07 '12 at 07:48
  • @mhenrixon I have no idea what that link has to do with this answer. Please explain. – Marnen Laibow-Koser Jun 07 '12 at 17:13
  • 5
    Its downvoted because you are not answering the question but stating an opinion. Sometimes I use inline js just to try something out and to save flicking between files. Later, once working, I put it in its own file. So the question can not be judged as terrible without context. – Kris Jul 19 '12 at 15:44
  • @Kris I didn't say the question was terrible, I said this was a terrible way to structure code -- and it is. Whether you like to use it for quick experiments or not, this is not something that should make it into production code. And that's not my opinion; it's fact (every decent JS developer will say likewise, so far as I can tell). When a question is asked on how to implement a bad idea, I don't believe I'm helping the asker if I don't tell them it's a bad idea. – Marnen Laibow-Koser Jul 19 '12 at 15:51
  • But thats the thing we don't know this is production code or a spike, due to lack of context. So it can't be judged as terrible. I do think it is a good idea to say there could be a better way, but maybe in a nicer way :) – Kris Aug 27 '12 at 23:12
  • @Kris I very much doubt that anyone would be asking advice on here for a spike. Even if he were, he should know that—at least once he gets the spike done—this isn't a good idea. – Marnen Laibow-Koser Aug 28 '12 at 13:59
  • @Kris Also, even a spike should use as much proper practice as possible. – Marnen Laibow-Koser Aug 28 '12 at 14:06
  • 8
    @MarnenLaibow-Koser I'll happily explain my downvote. Your response does absolutely nothing to help the OP with his question. If there were no occasion when it was ever acceptable to use inline JS, then Haml wouldn't provide filters, but it does. This question, by the way, also applies to every other filter in Haml, of which there are many. *Of course* inline JS is often misused, but there are much better times and places to explain that than on a non-answer to a perfectly legitimate question. – Ian Greenleaf Young Nov 16 '12 at 20:18
  • @IanGreenleaf "If there were no occasion when it was ever acceptable to use inline JS, then Haml wouldn't provide filters, but it does." This is an illogical assertion. Just because a feature exists does not mean it's a good idea to use it. In fact, even though it's possible to embed JS and CSS into HTML, there is never any valid reason to do so outside of certain inflexible CMS situations (where Haml wouldn't be used in the first place): HTML is only about document structure. Behavior (JS) and presentation (CSS) have no place in HTML files. – Marnen Laibow-Koser Nov 19 '12 at 02:50
  • 4
    downvoted: not answer the question. – fotanus Feb 18 '13 at 01:49
  • 1
    @fotanus I explained a better way of accomplishing the goal. IMHO that's an answer. – Marnen Laibow-Koser Mar 11 '13 at 18:20
  • 2
    "..and you're not mixing JS and HTML" But you are mixing js and html storing data in the dom temporarily and then loading it in a js var. How is that better? – Mauricio Mar 15 '13 at 19:29
  • @Mauricio That's not mixing JS and HTML. The DOM always contains (potentially) JS-readable data, so putting more data in there is not a problem. Or do I misunderstand your concern? – Marnen Laibow-Koser Mar 20 '13 at 17:36
  • Legit use atleast here https://github.com/fnando/i18n-js – Karthik T Jan 03 '14 at 07:43
  • @KarthikT Can you provide a more specific link? I'm not sure what you're pointing to as a supposedly legit use. Anyway, that whole gem is problematic IMHO (and barely usable with recent Rails, since the asset pipeline breaks it): it's only really useful if you're breaking up your rendering between server and client, which generally isn't a great idea. – Marnen Laibow-Koser Jan 09 '14 at 19:55
  • @MarnenLaibow-Koser enabling `i18n-js` is shown with erb within a javascript section. This requires the method explained here to be accomplished in haml – Karthik T Jan 10 '14 at 03:05
  • @KarthikT But that's no more legitimate than any other use of js.erb. If I were using the i18n-js gem, I would put the locale in the DOM and have the JS read it as I've already recommended. There's no reason to use js.erb or js.haml here. – Marnen Laibow-Koser Jan 10 '14 at 03:16
  • 1
    I'm agree, I don't know why you have downvotes! – Leo Gasparrini Nov 17 '16 at 14:31
  • downvoted for cynical and opinionated non-answer – Gerard Simpson Jan 14 '19 at 02:37
  • The proposed alternative solution has nothing to do with interpolation, which was the question, and it's a bad solution as well. It's perfectly legitimate to return a purely-js response to a request, in which it'd be useful to have HAML/ERB interpolation. It's also very bad form to mix that data into the _content_ of an element, then hiding that content and pulling out the innerHTML, rather than just storing it as a data attribute. – Tim Sep 14 '20 at 04:41
  • @Tim A data attribute is a better solution in 2020, yes. I don’t believe it was available in 2011, when I wrote this answer (or at least I was not aware of it back then). As for the question of interpolation, I stand by my original statement: you basically never want to be interpolating in executable code, and even if you do, Haml is designed in such a way that it is heavily optimized for the syntax of SGML-family languages and requires too many workarounds to be of much use in other situations. (I love Haml, don’t get me wrong. But using it for non-SGML-type languages is a fool’s errand.) – Marnen Laibow-Koser Sep 15 '20 at 05:06
  • @MarnenLaibow-Koser, fair point about HAML not being a good solution for non-markup languages, but it is still perfectly viable. And yeah, data attributes are an HTML5 thing, quite right that they weren't available in 2011, sorry about that! But there's nothing fundamentally wrong with interpolation in a JS response. Storing that as hidden content in the DOM has the potential for some security issues or other bugs due to interaction with other JS, since it affects the actual DOM. – Tim Sep 17 '20 at 04:20
  • @Tim Interpolation in a JS response *is* fundamentally wrong—and I say that as a developer who’s done plenty of complex Ajax work. It’s simply never necessary if you design the application properly (in fact, the perceived need for interpolated JS usually masks a design problem if you look a little deeper), and it creates a lot of problems for testing and caching. As for the security issue, the data is getting to the client one way or the other, whether in a JS file or in the DOM. Interpolated JS creates worse security issues because it opens up a whole class of code injection possibilities. – Marnen Laibow-Koser Sep 17 '20 at 16:59