I'm working on porting a JS library to rails. This will be my first gem that I'm attempting to create and I seem to have run into a bit of a snag.
The issue that I have is that there will necessarily be some JavaScript elements to the gem. However, I seem to be unable to find out how to do this.
Example:
/lib/rotrails.rb
module RotRails
def self.isSupported
#Call JS function "isSupported() in /vendor/assets/javascript/rotrails.js
end
end
/vendor/assets/javascript/rotrails.js
Function isSupported() {
return !!(document.createElement("canvas").getContext && Function.prototype.bind);
}
Any assistance on how to solve this problem as well as pass the result back to the Rails Gem would be appreciated.
Update: To clarify, the rails part is logic calculations and the JavaScript is the frontend for the program. I am looking for the most logical way to have the two communicate or a reference to how to work with JavaScript when creating gemfiles.
Thanks!
Did you consider to use (or simply try) https://rails-assets.org/ instead of porting your js library manually ?
Related
I have a rails application which is serving up a number of views which include specific data from the database to be manipulated by some javascript, specifically for use with Chartjs.
Options I have explored are:
Use an ajax call to pull the data off the server. I don't like this one because the user isn't changing any data, I have access to all the data when I render the page, there ought to be a better way.
Use <script> tags in the view ERB and simply have ERB interpolate the variable. This seems a little hacky and definitely doesn't take advantage of all my beautiful haml. But it is easy and allows me to put javascript variables on the page which can then be picked up after the document.onload.
Gon. Great gem and very easy. But should this really require a gem?
I feel as though the solution should involve the asset pipeline and some sort of rails interpolation, but I can't seem to make that work very cleanly. What is the elegant rails 4 way for solving this?
Thanks everyone!
There are many ways to pass data from server-side to javascript, I'll list two of the most common (that don't use a gem or other external tools) below:
Use the second method you described, and interpolate ERB tags inside the javsacript. This is ugly, hacky and is not even close to best practice.
Use data attributes. You can modify your HAML to include additional attributes, like "data-my-variable", and access it via javascript (example using jQuery: $(element).data("my-variable")).
The data attribute method is, in my opinion, the cleanest way of doing this, it's exactly the purpose of data attributes.
Now, I don't know HAML, I've only worked with ERB before, but I found this answer by Mandeep, which explains how you can add data attributes to your HAML:
%a{"data-my-variable" => "my data", href: "#"}
OR
%a{href: "#", :data => {:my_variable => "my data"}}
EDIT: Sorry, I found your question along with other, newer, questions, I just assumed it was recent, and not from over a year ago :)
My quick question is, should I begin using a javascript framework at the same time that I build my project with symfony or can I do it later without major troubles?
I have a small project of one page app written in flat PHP and jquery. Now I'm trying to port my project to symfony and I would like to use a javascript framework too. After one month of learning symfony I think that I begin to understand how it works, but I have a mess in my head with all those javascript frameworks available.
I think that is better to focus all my attention to symfony and once I fully understand how it works try to use a framework for javascript.
But I'm afraid of using a javascript framework implies changing a lot of my symfony code and twig templates. Right now, I'm using repositories and services to get data for the controller and then return it to javascript in JSON format. I understand that this shouldn't change (at least the part where I get the data) but I read some articles of people using bundles like FOSRestBundle and JMSSerializerBundle to return the data and using templates from javascript like mustache to render it, so I'm a little confused and I don't know if this will be a big change or if this is needed between symfony and javacript framework.
EDIT:
When I say javascript framework I'm talking about a combination of backbone + chaplin or marionette, for example. I think that jquery is just a library, not a framework, and backbone needs jquery to work.
All websites are completed by JS now, to be more user friendly and interactive, so yes of course you can use JQuery right now, from the beginning of your project because if you don't you will lose time by refactoring your actions to works with JS interactions and callback !
In addition, it will learn you how to manage JS in a Symfony project. You are free to use a vendor bundle or not to return JSON. You can simply do like that :
// action :
public function myAjaxAction()
{
// do something
return new Response(
json_encode(
array(
'success' => 0,
'error' => 'No image found.
)
));
}
And to finish, some documentation of Symfony2 use JQuery, like this : http://symfony.com/doc/current/cookbook/form/form_collections.html
So yes you can use JQuery now !
I'm not getting you. If you want to convert flat JS into JS framework in the future, why don't you use that from now on? From my experience, it's not easy work to convert your js(jquery way) into REAL Backbone way. Because you need to reconstruct all of your js code, even symfony code.
Though it's harder to use two new kind of technologies for you, I think you should try it.
Yes, you can use it very easily. Symfony is mostly for backend. You can put in Backbonejs or Angularjs for front-end stuff.
I have a rather robust project that has all of its templates implemented in Slim and a little Haml. I'm considering moving the project over to a Node.js based structure (probably built atop Tower.js or something similar; maybe Meteor), however I would like to continue using Slim or Haml for the templates rather than shifting over to another template engine.
Has anyone done this or spent the time to figure out how to accomplish this so far, and if so, what were your findings?
Tower.js wraps the express.js template engine system, so you should be able to use any express.js template engine by adding the following to the configuration Tower.View.engine = "haml"
Tower.js uses mint, which has HAML built in, so you just need the haml module in your directory.
Slim is problematic though. First its not within mint.js directly, so you'll need to register a new template engine. Todo that you'll need to
create a function customAdapter that mint.js can use, you can look at the mint.js sourcecode. Heres an example of the haml adapter function:
function(content, options, callback) {
var result;
result = require('hamljs').render(content, options || {});
if (callback) {
callback.call(this, null, result);
}
return result;
}
you'll need to add the adapter to mint.js by doing require("mint").engines.slim = customAdapter
But there's no express.js engine for Slim, and since Slim contains ruby code snippets, it isn't likely there will be.
If you really want to do it so you'll need to create your own javascript parser for the template files (probably using something like http://opalrb.org/ , though with no specific ruby libraries), and then create an express.js engine (which I don't know how to).
I doubt it will be a very fruitful exercise.
I suggest you either convert your Slim files to haml (or jade, or any template engine that can be used by express.js) or don't make the move.
I could also not find any way to automatically convert Slim to haml or any other template engine (probably due to the fact that it contains ruby code), so you will have to do the conversion entirely manually.
For a Rails 3.1 app, some of my site wide JavaScript is only included when certain real time, instance specific conditions are met. This means I can't put it in the new asset pipeline's application.js because that isn't parsed by erb for embedded Ruby within the current context. Basically, I'm including keyboard shortcuts, based on the current_user that is logged in.
My question: where should this JavaScript with embedded code go, so that the embedded Ruby is still parsed for each page access with the proper context (i.e. current, logged in user)?
The answer seems to just be to put it in the application.html.erb layout view at the bottom, but this seams like I'm hiding away javascript code in a non intuitive location.
I've tried creating an application2.js.erb file, but then I got errors about undefined variables, which I think might be because the asset engine only parses this file once before the output is cached and the scope isn't correct yet for things like current_user.
So, using application.html.erb works just fine here, and this isn't so much a question of how to get it to work functionally. Instead, I'm wondering if there's a more elegant way to incorporate the asset pipeline model here with my requirements and still keep most of my JavaScript in the assets/javascripts directory.
You should try to create app/assets/javascripts/application2.js.erb (or whatever better name you come up with)
And then put something like this in your app/assets/javascripts/application.js:
//= require application2
And then you can have
<%= javascript_include_tag 'application2' %>
wherever you want - for example in your application.html.erb.
Btw, if you want to customize what's included on a per-view basis you might find content_for useful. Check out this screencast
Ok, about unobtrusive js. It will be just a cocept (HAML):
In your view somewhere
# hotkeys are "Ctrl+C", "Ctrl+A"
-current_user.hotkeys.each do |hotkey|
%hotkey{ "data-key" => hotkey.key, "data-behavior" => hotkey.fn }
Then in your application.js
$(document).ready(function(){
if($("hotkey").length > 0){
$("hotkey").each{function(this){
key = $(this).data("key");
fn = $(this).data("behavior");
$(document).bind('keydown', key, fn);
}}
}
})
So just the same JS will extract from HTML hotkeys data and then bind it.
As some people have pointed out, the two options are:
Put your javascript inside the view (and as you say, this doesn't feel quite right).
Put it in a javascript file. Make a conditional inside your view that includes this javascript file if certain conditions are met.
If you need to pass more instance variables from the controller to your javascript, this gem called gon can make your life easier.
This allows you to use the default asset pipeline using the following javascript:
if(gon.conditional){
//your embedded js code here
}
If you want to know more about this gem, checkout this railcast where everything gets explained.
I am trying to use update some calculations everytime a person modifies a text field. I have many question about how to know the id text field, how to store it in a variable, etc. I am a newbie with ruby and javascript and there are many questions. Could you please tell me where I can find more information that explains step by step how to proceed with this?
Thank you very much.
I highly recommend using jQuery with Ruby on Rails... it makes this sort of thing much easier, and is going to be the standard as of the next version (3.1).
In jQuery, you do something like:
$('#my_field').change(function() {
$('#result').val(function() {
do something...
});
});
And you can use a js.erb template to embed Ruby in the JS to get data from the controller. Ryan Bates' Railscasts series has several examples of using Javascript in RoR for dynamic content.
Also, NetTuts+ has this tutorial for using Unobtrusive JavaScript in Rails 3.