How do I use my Jquery plugin in the Rails asset pipeline? - javascript

My company introduced a way to use social share buttons without providing tracking data to the social sites on page load: jquery.socialshareprivacy.
How can I use it in a Rails 3.2 asset pipeline?

The plugin consists of a JS file and a directory with css and images.
Rails 3.2 comes with jQuery 1.9.x and the jquery.socialshareprivacy.js uses functions, removed in 1.9 (.live $.browser), so you have to patch it (get patch at first gist) Using the asset pipeline requires to use different file paths for the images, so I patched the CSS (see second gist) and turned it into an SCSS (append .scss to the filename).
I basically turned three url() into image-url().
I put the JS in vendor/assets/javascripts and the whole CSS+images folder (socialshareprivacy) under vendor/assets/stylesheets
When I place the share buttons on a page (see this documentation), I set the image urls in the options:
<div id="socialshareprivacy"></div>
<script type="text/javascript">
$(function(){
$('#socialshareprivacy').socialSharePrivacy({
'css_path': '<%= asset_path 'socialshareprivacy/socialshareprivacy.css' %>',
services: {
facebook: {dummy_img: '<%= asset_path 'socialshareprivacy/images/dummy_facebook.png' %>'},
twitter: {dummy_img: '<%= asset_path 'socialshareprivacy/images/dummy_twitter.png' %>'},
gplus: {dummy_img: '<%= asset_path 'socialshareprivacy/images/dummy_gplus.png' %>'}
}
});
});
</script>
If you need it in several places, consider turning it into a partial.

Related

Calling a CoffeeScript function across all views (Ruby on Rails)

this is my first StackOverflow question, so I hope I ask it right!
I have a Ruby on Rails web application where in our javascript files, I have the following CoffeeScript code, which detects when a button with id="submit" is pressed and then scrolls to the first error that appears, if any (the "submit" buttons are used in our forms):
#scroll_to_error = ->
document.getElementById('submit').onclick = ->
if $('.alert-danger:visible:first').length > 0
$('html, body').animate { scrollTop: $('.alert-danger:visible:first').offset().top - 220 }, '1000'
return
I have the file included in our application.rb file in the config folder, so that it can be called in any HTML file in the views section ~~ however, I was wondering if there were a way so that it can be called in all the views that I have. Is there a certain way to do this?
Hope this is suffice info - sorry I could not provide more code snippets, as I am coding for a company (hence the "our").
One way to do this is to expose your code in a function so you can call it from the views.
Coffeescript file:
window.SomeNamespace ||= {}
window.SomeNamespace.scroll_to_error = ->
document.getElementById('submit').onclick = ->
if $('.alert-danger:visible:first').length > 0
$('html, body').animate { scrollTop: $('.alert-danger:visible:first').offset().top - 220 }, '1000'
View file: (say you are using erb)
<script>
$(function(){
window.SomeNamespace.scroll_to_error()
});
</script>
A better way to do this, however, is to separate view code and javascript code. elementaljs offers a small Javascript behaviors library for Rails, which I like a lot. You can "attach" a javascript behavior to a specific html element via data attribute, and the library does the above work for you.
Try something like this?
scrollToError = ->
$('*[data-scroll-to-error="true"]').click ->
alertElement = $('.alert-danger:visible:first')
if alertElement.length > 0
$('html, body').animate {
scrollTop: alertElement.offset().top - 220
}, '1000'
# Run with turbolinks.
$(document).on 'page:change', scrollToError
and a submit button with the data-scroll-to-error attribute set.
<input type="submit" data-scroll-to-error="true" />
I find this statement of yours confusing:
I have the file included in our application.rb file in the config
folder, so that it can be called in any HTML file in the views section
Assuming this is a standard Rails project, you should have included the file containing the Coffeescript code in assets/javascripts/application.js (the manifest file), and since application.js is the JS file required in the layout (isn't it? :-/), this code would execute on all of your views. I don't see how config/application.rb is involved here.
Update: Adding more information.
If you're unsure about how to application.js file (a manifest file) is used, please take the time to go through Rails' official documentation about it (especially the section about manifests).
http://guides.rubyonrails.org/asset_pipeline.html#manifest-files-and-directives
In your case, you'll want to modify application.js to include:
...
//= require error
...
Basically, you list all the asset files that you want loaded along with all pages that use a layout (probably application.html.erb), and then mention only the manifest file the layout. That way, Rails can concatenate and minify to generate a single asset file. The default application. manifest files are automatically precompiled - so you don't need to manually add new assets to the precompile list.
The reason why I wrote the selector as *[data-scroll-to-error="true"] was personal preference - the code reads better to me that way. If you're sure that the ID submit is (and will be in future) applied only to elements that require scrolling to error, then it's fine to change the first selector to $('#submit').click ->

How do I include custom javascript on/for a single page in Rails?

I have an interactive header for my site located in /views/layouts/_header.html.haml.
I want all the JavaScript for the header to be collected into a single file. Most importantly, I'm using Twitter Typeahead and Bloodhound for a search field with auto-suggest. A lot of this JavaScript has to be run after the header is rendered, so its inclusion in application.js (which is included on my page in application.html.haml) doesn't work, as this runs before the header is rendered.
I added search-bar.js under /assets/javascripts/ which contains all the JS I need to run on this page.
At the bottom of my _header.html.haml I just linked with a regular script tag.
%script{src:"/assets/movie-search-bar.js", type:'text/javascript'}
This works fine locally, but on my dev server I get a 404 for that asset. Is it possibly throwing out the static file for performance reasons? Even if it does work, by having it included in the asset pipeline, wouldn't the script be loaded twice (once as an individual script, and once in application.js)?
I'm getting the impression that this is not the best way to isolate the javascript of a partial into its own file. What is the best and most "railsy" way to ensure that the script is loaded once, after _header is rendered, and isolated within its own JavaScript file?
EDIT: Could this perhaps be as simple as moving the following lines to the bottom of my footer partial? Is this considered good practice in Rails?
#{ stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true }
#{ javascript_include_tag 'application', 'data-turbolinks-track' => true }
You can use javascript_include_tag on scripts other than application.js. First, make sure your script is in app/assets/javascripts folder: app/assets/javascripts/movie-search-bar.js.
Then use the javascript_include_tag helper in your view:
javascript_include_tag 'movie-search-bar'
And tell Rails to precompile that asset.
config.assets.precompile << "movie-search-bar.js"
Well I have done this task .If you want to include a particular javascript in your view .First create a folder in your views folder .For example page_js and then create some partial like _file.html.erb .And place your javascript into it .And then render that file wherever you want .So your javascript will work for that particular page only .If it doesn't work then tell me .

Devise logout not working

I'm using the latest version of devise and rails 4.2.4.
I've my home page
public/index.html
which contains heavy javascript. But when I load it from some other page, it doesn't load with all the effects. So included
$(document).on('page:load', ready);
<script src="/js/modernizr-2.6.2.min.js"></script>
<script src="/js/main.js"></script>
in application.js file.
But then
Logout
<%= link_to "Logout",destroy_user_session_path, method: :delete %>
doesn't work! It gets rendered as GET /users/sign_out.
When I remove those links from application.js, it works fine.
Any workaround for this issue?
Your javascript has an error in it.
--
Each time you use method: :delete or method: :patch, Rails populates a form with the appropriate verb, using Javascript to set it correctly:
[link_to] dynamically creates an HTML form and immediately submit the form for processing using the HTTP verb specified. Useful for having links perform a POST operation in dangerous actions like deleting a record (which search bots can follow while spidering your site). Supported verbs are :post, :delete, :patch, and :put. Note that if the user has JavaScript disabled, the request will fall back to using GET
The above is true if your javascript is broken (IE you have an error preventing it from working properly on the page).
--
Since you haven't posted your JS, I cannot give you any specifics.
However, I can say that your JS should be as unobtrusive as possible.
Using <script> anywhere in your Rails app is bad practice; you should have the files concatenated in your application.js with the help of sprockets manifest directives:
#app/assets/javascripts/application.js
//= require main
//= require modernizr
The issue is that most browsers do not support the DELETE method, the request will actually be submitted as GET, with a data-method="delete" attribute. This relies on the "Unobtrusive scripting adapter for jQuery" (jquery-ujs) being loaded by your page.
If you were using the standard rails templates, the 'application.js' manifest file would take care of that for you, but given that you are putting your index.html in the public directory you will have to manually include both jquery and jquery-ujs in your header.
An alternative is to change the route to logout to actually use GET (you will anyway have issues with the PUT and PATCH methods as well), adding this to your devise config (from devise wiki):
# config/initializers/devise.rb
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :get
If you plan to use rails you should find out why you are having issues with the standard rails way of dealing with view templates. I use a lot of javascript-heavy pages, and they work just fine. Plus you get all the benefits of the asset pipeline.

Q about static configuration of javascript/css URL?

I have a single page web application that utilizes DOJO (1.9.x). It normally loads the DOJO library from the Google CDN and my application functions as expected. But, some customers offer limited internet connection that excludes most of the internet for security (!?) reasons. So I have to host DOJO library locally on the server.
For this to work, I should point the URL to the local copy of dojo.js and relevant CSS files. As only the prefix of the URL changes, I am curious if there is a trick to achieve this by some external CSS file so that the URL in the HTML gets its prefix from this small CSS. By simply editing/changing this small CSS file, One site will load DOJO from the Google CDN and Another will load the locally hosted DOJO.
Is this possible with a static CSS file ?
This is not possible with CSS.
A few alternatives, in order of preference:
SAFEST - Distribute two versions of the page/app, with local and remote dojo.
If you have server-side rendering of any sort, configure that to update the dojo URL.
Always distribute the dojo loader with your application. Thereafter, load dojo modules from CDN or locally according to your config. This could get hairy.
More details on option 3:
dojoConfig.js
//var dojoRoot = ".."; // For LOCAL builds - relative to dojo.js
var dojoRoot = "//ajax.googleapis.com/ajax/libs/dojo/1.9.3"; // For CDN builds
var dojoConfig = {
packages: [
// Depending on your project structure, you may need to
// insert entries here for your local packages.
// Here, we override the location for dojo packages
{
name: "dojo",
location: dojoRoot + "/dojo"
},
{
name: "dojox",
location: dojoRoot + "/dojox"
},
{
name: "dijit",
location: dojoRoot + "/dijit"
}
]
};
HTML snippet to use it
<script src="dojoConfig.js"></script>
<script src="dojo/dojo.js"></script>
<script>
require(["dojo/_base/config", "dojo/json"], function(config, JSON) {
console.log(JSON.stringify(config.packages, null, "\t"));
});
</script>

URL of images in JavaScript code using Rails 3.1 asset pipeline?

In CSS files, you can get the proper name of an image asset (with the fingerprint) by using:
background-image: url(image-url("rails.png"))
but how do you do the same from a JavaScript file?
I see you are using the sass helper method.
In standard (non Sass) CSS you do something like this:
.class { background-image: url(<%= asset_path 'image.png' %>) }
The CSS file will need to have erb added to the extensions:
file_name.css.erb
For javascript the same rules apply:
file_name.js.erb
and in the file:
var image_path = '<%= asset_path 'image.png' %>'
The Rails asset pipeline guide is an excellent source of information about how to use these features.
In Rails 4, instead of using a js.erb view I recommend that you stick to the asset pipeline, and pass the URL to it with a variable instead using gon or some other technique discussed at: Ruby on Rails - Send JavaScript variable from controller to external Javascript asset file
With gon:
app/views/layouts/application.html.erb:
<head>
<meta charset="utf-8"/>
<%= include_gon %>
app/controllers/application_controller.rb:
before_filter { gon.path = asset_path 'image.png' }
app/assets/javascripts/file.js.coffee:
alert gon.path
This method is faster because file is precompiled only once at startup, gets served by the server instead of through Rails, and on the same HTTP request as the rest of the Js.

Categories

Resources