Rails link_to and audio_tag - ruby-on-rails-3

I'm trying to figure out the best way to play a wav file in the background (HTML5-like) when I use a link_to tag in Rails.
Here's a sample link_to from one of my views:
<%= link_to 'At Station', at_station_mdt_index_path, :class => 'btn btn-success btn-medium', :method => :put, :remote => true %>
I'd like to figure out how to use the audio_tag to trigger a sound when the button is pressed. I've tried combining the audio_tag in the link_to ERB but get all sort of syntax errors.
Any examples would be greatly appreciated.
Updated 01/04/14-10:18am CT: The sounds fire once and properly. However since adding the :id to the link_to the links no longer trigger the rails path to change the object, only plays the sound
View code:
<%= link_to 'En Route', en_route_mdt_index_path(:call_id => call.id), :class => 'btn btn-warning btn-medium', :method => :put, :remote => true, :id => "er" %>
<%= link_to 'On Scene', on_scene_mdt_index_path(:call_id => call.id), :id => 'to', :class => 'btn btn-primary btn-medium', :method => :put, :remote => true, :id => "os" %>
<%= link_to 'To Hospital', to_hospital_mdt_index_path(:call_id => call.id), :class => 'btn btn-warning btn-medium', :method => :put, :remote => true, :id => "to" %>
<audio id="en-route" class="audio_player" preload="true">
<source src="audios/en-route.wav" type="audio/wav">
</audio>
<audio id="on-scene" class="audio_player" preload="true">
<source src="audios/on-scene.wav" type="audio/wav">
</audio>
<audio id="to-hospital" class="audio_player" preload="true">
<source src="audios/to-hospital.wav" type="audio/wav">
</audio>
<script>
$('#er').click(function (e) {
e.preventDefault();
$('#en-route')[0].currentTime = 0;
$('#en-route')[0].play();
return true;
});
$('#os').click(function (e) {
e.preventDefault();
$('#on-scene')[0].currentTime = 0;
$('#on-scene')[0].play();
return true;
});
$('#to').click(function (e) {
e.preventDefault();
$('#to-hospital')[0].currentTime = 0;
$('#to-hospital')[0].play();
return true;
});
</script>

Here's a simple example for playing a wav file:
http://jsfiddle.net/84pav/
HTML:
At Station
<audio id="sound_effect" class="audio_player" preload="auto">
<source src="http://www.villagegeek.com/downloads/webwavs/alrighty.wav" type="audio/wav">
</audio>
JavaScript:
$('#playsound').click(function (e) {
$('#sound_effect')[0].currentTime = 0;
$('#sound_effect')[0].play();
return false;
});
I set currentTime = 0 before playing to make it always plays from the beginning.
It does not work on IE because IE does not support wav file.

I'm making a few assumptions in this answer:
You're using HTML5 markup
You want a styled link "button" to trigger a sound
You don't want to display the default HTML5 audio player
The sound files are stored in public/audios
The sound file is pre-loaded on the page
Unfortunately, the Rails 3.2 implementation of audio_tag is broken (https://github.com/rails/rails/issues/9373). So unless you're using Rails 4, you're better off using the actual HTML markup.
In this example, we're loading an mp3 file in the the default HTML5 audio player. The following snippet should be in your view file.
<audio id="sound_effect" class="audio_player" controls="false" preload="true">
<source src="/audios/TrainWhistle.mp3" type="audio/mpeg">
</audio>
Since the HTML5 audio player comes with "built-in" display chrome, you may want to position it off the page with css. In this example, you would add the following to your css file:
.audio_player {
position: absolute;
top: -999em;
{
Your link_to markup would look something like:
<%= link_to 'At Station', '#', class: 'btn btn-success btn-medium', id: 'playsound' %>
The javascript to actually play the sound will look similar to this jQuery example:
$('#playsound').on('click', function (e) {
e.preventDefault();
$('#sound_effect').currentTime = 0;
$('#sound_effect').play();
return false;
});
This example can easily be extended to support multiple files by small changes to the link_to tag and javascript.

How about something like this...
function playSound(soundfile) {
document.getElementById("playsound").innerHTML=
"<embed src=\""+soundfile+"\" hidden=\"true\" autostart=\"true\" loop=\"false\" />";
}
$('#playsound').observe('click', function (event) {
playSound('URL to soundfile');
event.stop(); // Prevent link from following through to its given href
});
Then add the playsound id to your link.

Related

Passing JQuery Datepicker Data to Rails Controller

I'm new to Rails and JQuery so I'll try to explain this as best I can. I'm trying to pass my JQuery datepicker values to my rails controller. The page has data on it that I want the user to be able to filter based on a date range. There are a number of different posts on this subject:
Passing the variables from from jquery to rails controller
How to pass variables from AJAX form into controller?
I have tried to follow the guidance of these posts, but I'm still having trouble.
Here is my partial _dateFilter.html.erb =>
<%= form_tag({:controller => 'events', :action => 'dateFilter', :class => 'date_form'}, :remote => true) do %>
<%= datepicker_input "event", :start_date, :class => 'dateFilter', :dateFormat => 'mm/dd/y' %>
<%= datepicker_input "event", :end_date, :class => 'dateFilter', :dateFormat => 'mm/dd/y' %>
<%= submit_tag "Submit" %>
<% end %>
Here is the generated HTML =>
<form accept-charset="UTF-8" action="/events/dateFilter?class=date_form" data-remote="true" method="post">
<input class="dateFilter" id="event_start_date" name="event[start_date]" size="30" type="text" /><script type="text/javascript">
//<![CDATA[
jQuery(document).ready(function(){jQuery('#event_start_date').datepicker({"dateFormat":"mm/dd/y"})});
//]]>
</script>
<input class="dateFilter" id="event_end_date" name="event[end_date]" size="30" type="text" /><script type="text/javascript">
//<![CDATA[
jQuery(document).ready(function(){jQuery('#event_end_date').datepicker({"dateFormat":"mm/dd/y"})});
//]]>
</script>
<input name="commit" type="submit" value="Submit" />
</form>
Here is the dateFilter.js.erb =>
$('.dateFilter').append('<%= escape_javascript(render(#events)) %>');
Here is the events_controller =>
def dateFilter
#events = Event.find(:all, :conditions => ["EVENT_DATE_TIME_LOCAL BETWEEN ? AND ?", params[:start_date], params[:end_date]])
respond_to do |format|
format.html
format.json { render json: #events }
format.js
end
end
Finally here is the application.js =>
$(document).ready(function() {
$('#date_form').submit(function (){
$.ajax({
type: 'POST',
url: "/events/dateFilter",
beforeSend: function (xhr) {xhr.setRequestHeader("Accept", "text/javascript");},
data: { 'start_date' : $("input[name='event[start_date]']").datepicker(), 'end_date' : $("input[name='event[end_date]']").datepicker()}
success: function(data) { <%= render "events/dateFilter" %>}
});
});
This is log data from the server =>
Started POST "/events/dateFilter?class=date_form" for 127.0.0.1 at 2012-12-12 15:09:39 -0500
Processing by EventsController#dateFilter as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"J/HU+DxNmIwEhu3keN071k6MGCCD/n/1UhXUD0MkH1Q=", "event"=>{"start_date"=>"12/06/12", "end_date"=>"12/13/12"}, "commit"=>"Submit", "class"=>"date_form"}
Event Load (1.7ms) SELECT "TBLEVENT".* FROM "TBLEVENT" WHERE (EVENT_DATE_TIME_LOCAL BETWEEN NULL AND NULL)
Rendered collection (0.0ms)
Rendered events/dateFilter.js.erb (0.3ms)
Completed 200 OK in 8ms (Views: 3.4ms | ActiveRecord: 1.7ms)
One of the problems is that I keep getting "NULL" for the values of data I am trying to pass. I'm not even sure that I am going about this correctly, any help/feedback on this would be greatly appreciated. Thanks.
From your log data, this is in the Parameters:
"event"=>{"start_date"=>"12/06/12", "end_date"=>"12/13/12"}
which means start_date and end_date are in a Hash called event, so your controller should look like this:
def dateFilter
eventIn = params[:event]
#events = Event.find(:all, :conditions => ["EVENT_DATE_TIME_LOCAL BETWEEN ? AND ?", eventIn[:start_date], eventIn[:end_date]])
respond_to do |format|
format.html
format.json { render json: #events }
format.js
end
end
One other small thing - the form_tag class should be set like so:
<%= form_tag({:controller => 'events', :action => 'dateFilter'}, :class => 'date_form', :remote => true) do %>

Rails flash messages with HAML

i started learn HAML: and i can't translate flash block to HAML:
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong><%= value %></strong>
</div>
<% end %>
Here you go:
= flash.each do |key, value|
.alert{ :class => "alert-#{key}" }
%button.close{ :data => { :dismiss => "alert" } } x
%strong
= value
Just FYI you can add attributes to any element by attaching them as a hash after the declaration. If you don't specify an element, just a class or ID, HAML makes that element a div with the given class or id. But you could do this many ways. For instance, these are all the same:
%div{:class => 'foo bar', :id => 'test' }
.foo{:class => 'bar', :id => 'test'}
#test.bar{:class => 'foo'}
#test.foo.bar
All output: <div class="foo bar" id="test"></div>
You need to put computed attributes in the hash though, i.e.:
- klass = "bar"
%div{ :class => klass }
Outputs: <div class="bar"></div>
Also, note that in all the examples above, the :attribute => 'value' can be expressed as attribute: 'value', e.g.:
%button.close{ data: { dismiss: 'alert' } } x
Hope that helps.

jquery ui dialog appears bottom of page

quite random behavior, I'm calling on a modal dialog to show a partial inside.
I'm working with simple_form + bootstrap and jquery-ui.
the button that calls the function has this code in the view:
<p><%= link_to 'New Boots', new_boot_path, :class => 'btn btn-primary pull-right', :remote => true, :id => 'new_boot_link' %></p>
in my views/boots/new the code is this:
<div id="content">
<%= render :partial => 'form' %>
</div>
and in views/boots/_form the following
<%= simple_form_for(#boot, :html => { :class => 'form-vertical' }, :remote => true) do |f| %>
<fieldset>
<%= f.input :number %>
<%= f.input :size, :collection => boot_size_options %>
<%= f.input :condition, :collection => boot_condition_options %>
<%= f.input :brand , :collection => boot_brand_options %>
</fieldset>
<div class="form-actions">
<%= f.button :submit, :class => 'btn btn-primary' %>
<%= submit_tag 'Reset', :type => :reset, :class => "btn btn-danger" %>
</div>
<% end %>
In application.js i have the following:
$(document).ready(function() {
$('#new_boot_link').click(function(e) {
var url = $(this).attr('href');
$('#modal').dialog({
title: "New Boots",
draggable: true,
resizable: false,
modal: true,
width:'auto',
open: function() {
return $(this).load(url + ' #content');}
});
});
});
So the modal works as it should, but it appears at the bottom of the screen, however if i close it and click on the button again, it shows right in the middle as it should have done in the first place.
Is it css? I think maybe not, as otherwise it would continue showing up constantly in the same place... so i dont know if is the way I'm calling the function?
Suggestions are welcome, this is quite an annoying glitch!
Sorry about previous mistakes.
Unfortunately I can't reproduce your problem in person. I suspect that this would help because it will convert the DIV and on call fill and display.
$(document).ready(function(){
var modal=$('#modal');
$('#new_boot_link').click(function(e) {
var url = $(this).attr('href');
modal.load(url + ' #content',function(){
modal.dialog("open");
});
});
modal.dialog({ autoOpen: false, title: "New Boots", draggable: true,
resizable: false, modal: true, width:'auto'});
});
Include: jQuery Center
Change to:
$(document).ready(function() {
$('#new_boot_link').click(function(e) {
var url = $(this).attr('href');
$('#modal').dialog({
title: "New Boots",
draggable: true,
resizable: false,
modal: true,
width:'auto',
open: function() {
return $(this).load(url + ' #content');}
});
}).center(false);
});
This set your dialog on middle-center of page.
If you have specific place you want show dialog force:
..}).css({position:"relative"}).css("left",null).css("top",null);
// Last too remove value of left and top. Trick with {left:null,top:null} does not work!

Is there a way to render an action's js template from a js.erb file?

I have tried <%= render :template =>'resources/new', :format => "js" %>, but nothing happens.
Edit: Also I don't know how to send parameters to a .js template.
Solved by doing this:
render :template => 'resources/new.js', :locals => {:link_id => "register_similar"}
In the recieving js.erb file:
var link_id = '<%= link_id %>'

What is the Rails 3 Way to do a form field validation prior to submission?

I basically want to prevent searches that are less than 3 characters long.
In Rails 2.x, I would just do this in an onClick event. I understand how to handle AJAX requests and responses in Rails 3 now, but wouldn't using the onClick event be considered obtrusive in Rails 3?
Yup, onclick would indeed be considered obtrusive.
You might want to use a third-party validation library in javascript.
It could work something like this:
<form ... class="validated">
<input type="text" name="name" data-validation="presence=true,format=/[a-zA-Z0-9\s]+/" />
<input type="submit" value="Send" />
</form>
<script language="javascript">
$('form.validated').live('submit', function() {
var data = $(this).serializeArray();
var errors = [];
$(this).find('input').each(function() {
var input = $(this);
$.each($(this).attr('data-validation').split(','), function(validation) {
var type, param = validation.split("=");
if(type == "presence") {
if(input.val() == "") errors += input.attr('name') + " is empty";
} else if(type == "format") {
...
}
});
return (errors.length == 0);
});
</script>
(Just some rough code out of my head. Lots of caveats there.)
But instead of writing all that, perhaps you just want to use: http://github.com/jzaefferer/jquery-validation
Got it!
I put this code in application.js:
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
$(function() {
$("#search_submit").click(function() {
if ($("#search_value").val().length < 3) {
alert("You must supply 3 or more characters in your search.");
return false;
}
})
})
My form is:
<%= form_for(#search, { :remote => true, :html => { :id => 'left', :class => "custom-border" } }) do |f| %>
<h2><%= f.label :value, "Search By Part or Interchange #" %></h2>
<p><%= f.text_field :value %></p>
<p class="button"><%= f.submit "Search" %></p>
<% end %>
Voilá!