Rails Simple Form Bootstrap - Javascript if statement to reveal input - javascript

I have a rails 4 app with simple form and bootstrap.
I want to ask a question in my form which asks whether users need survey responses. If the answer to that is true, then I want to ask a follow up question. My two survey questions are:
<%= f.input :survey, :as => :boolean, :label => false, inline_label: 'Do you need survey responses?' %>
<br><br>
<%= f.input :survey_link, label: 'Where is your survey?', :label_html => { :class => 'question-data' }, placeholder: 'Include a link to your survey', :input_html => {:style=> 'width: 650px; margin-top: 20px', class: 'response-project'} %>
Is JS if statement the best way to approach this task? I want to hide the second question until the user answers true to the first question.
If so, I'm having trouble understanding how to make this JS work.
I have tried:
if (:survey is :true) {
:survey_link;
}
I can't find any resources to help explain how to do this. Help would be very much appreciated. Thank you.

Obviously the code below depends on what the name of your survey and survey_link inputs look like in actual HTML. So if in this example it is for #user:
<% simple_form_for #user do |f| %>
<%= f.input :survey, :as => :boolean, :label => false, inline_label: 'Do you need survey responses?' %>
<%= f.input :survey_link, label: 'Where is your survey?', :label_html => { :class => 'question-data' }, placeholder: 'Include a link to your survey', :input_html => {:style=> 'width: 650px; margin-top: 20px', class: 'response-project'} %>
<% end %>
Then the JQuery should look like (note the user part - you may have to change this):
<script>
$(function() {
// Hide the survey_link input
$('input[name="user[survey_link]"]').hide();
$('input[name="user[survey_link]"]').closest("label").hide();
// When the survey checkbox changes
$('input[name="user[survey]"]').change(function() {
$('input[name="user[survey_link]"]').closest("label").toggle(this.checked);
$('input[name="user[survey_link]"]').toggle(this.checked);
});
});
</script>

Related

How to add Label inside correct "form group" in Ruby on Rails form?

I'm using Rails 5.2 and have this simple rails form and a field for the IP address that looks like this:
<%= bootstrap_form_for(#asset,
:url => asset_path(#asset.id),
:as => :asset,
:method => :patch,
:layout => :horizontal,
:label_col => "col-md-3",
:control_col => "col-md-4") do |f| %>
<%= f.label :ip_address_locator, 'My NEW label', data: { "toggle"=> "tooltip", "placement"=>"bottom", :title => "This is a tooltip text" } %>
<%= f.text_field :ip_address_locator %>
<% end %>
I want to update the default label for:
My NEW label
but for some reason the default and new labels show up at the same time.
and when I inspect the labels they seem to be in different divs.
How to only show 'My NEW label' and not both labels?
I still want to have my tooltip as show on the picture.
By the way I was also able to update my label like this:
<%= f.text_field :ip_address_locator, :label => {:text => 'My NEW label'} %>
But then I don't have access to my tooltip any more.
I want to be able to update my label text and be able to see my tooltip when hovering on the label just like I have it on my picture.
Because you're using bootstrap_form_for builder, f.text_field outputs a label by default. You can remove it with skip_label option. And use your custom label instead.
<%= f.label :ip_address_locator, 'My NEW label', data: { "toggle"=> "tooltip", "placement"=>"bottom", :title => "This is a tooltip text" } %>
<%= f.text_field :ip_address_locator, :skip_label => true %>
However the custom label is now outside of the form group wrapper. If you want to keep the layout unchanged you should explicitly wrap the label and the input:
<% f.form_group do %>
<%= f.label :ip_address_locator, 'My NEW label', data: { "toggle"=> "tooltip", "placement"=>"bottom", :title => "This is a tooltip text" } %>
<%= f.text_field :ip_address_locator, :skip_label => true, wrapper: false %>
<% end %>
As a side note, in an effort to spare you extra work. I'd prefer to have a hint that's always visible if a field requires extra context. Label already has text in it and a tooltip seems redundant. If used in one or two places, I think it's fine. But you would be missing all the benefits of the form builder as well; skipping wrapper and label. You would only get a .form-control class on your input from the form builder by doing this.
Update for bottstrap_form < 4.1.0. No wrapper: false option.
<style>
.form-group .form-group { margin-bottom: 0; }
</style>
<div class="form-group">
<%= f.label :ip_address_locator, 'My NEW label', class: "control-label col-md-3", data: { "toggle"=> "tooltip", "placement"=>"bottom", :title => "This is a tooltip text" } %>
<div class="col-md-4"
<%= f.text_field :ip_address_locator, layout: :none, :skip_label => true %>
</div>
</div>
Fastest way would be to add jQuery, that will initialize the tooltip.
$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip();
});
This way tooltip will appear on hover.
jQueryUI documenation
Of course in order to use it you need jQuery gem or script tag inside of <head> </head>. But it's best to use the gem, you will need it a lot.

Making tinyMCE and Garlic.js work together

I'm trying to make Garlic.js and tinyMCE work together in my Rails app without success. I've integrated Garlic in my asset pipeline and for tinyMCE I'm using tinymce-rails gem.
Both work great separately but when I put them together Garlic stops working.
I've recently tried micschk's potential solution posted in Garlic's github repository https://github.com/guillaumepotier/Garlic.js/issues/87 which involves initialising tinymce with the following code:
views/layouts/application.html (following script inside head tag)
<script>
tinyMCE.init({
selector: 'textarea.tinymce',
setup : function(editor) {
editor.on("change keyup", function(e){
console.log('saving');
tinyMCE.triggerSave(); // updates all instances
// editor.save(); // updates this instance's textarea
$(editor.getElement()).trigger('change'); // for garlic to detect change
});
}
});
</script>
the code does initialise tinymce and runs the code after 'setup' but it does not seem to make Garlic work.
Here's my view code for reference
<%= simple_form_for(#open_ender, remote: true, html: {"data-persist" => 'garlic', id:'open_ender_form' }) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :answer_id, :required => true, :as => :hidden, :autofocus => true, input_html: {value: #answer.id } %>
<%= f.input :content, :input_html => { :class => 'tinymce' }, :label => false, :required => true, :autofocus => true %>
<%= button_tag(type: 'submit', id: "save-btn", style:'background:transparent' ) do %>
<i class="fa fa-floppy-o" aria-hidden="true" title="save"; data-toggle="tooltip"; data-placement="right"></i>
<% end %>
</div>
<% end %>
I would really appreciate if someone could point me to the right solution.
I've finally decided to use the tinyMCE autosave plug-in instead of using Garlic.js although the functionality is not exactly the same it serves the purpose of protecting users from losing their data.
https://www.tinymce.com/docs/plugins/autosave/

Rails reCAPTCHA with callback

I am trying to integrate a recaptcha into my website and I wanted to add some client side validation.
I chose to use a gem to include the recaptcha tags, but I wanted to trigger a function once the recaptcha is checked.
Looked through some google sites and found that a data-callback attribute with its value set to function name is all I need.
I used recaptcha_tags helper from the gem to set it up and then a jquery method to add this data-callback attribute as I have not seed an option to do this inside the gem.
$('.g-recaptcha').attr("data-callback", "myFunctionName");
After clicking the recaptcha the function is not called. Why?
I asume you have a form like this
app/views/contacts/contact.html.erb
<%= form_for #contact do |f| %>
<%= f.text_field :nombre, :placeholder => I18n.t("contacto_formulario_nombre"),:required => true %>
<%= f.text_field :apellido :placeholder => I18n.t("contacto_formulario_apellidos"), :required => true %>
<%= f.text_field :email, :placeholder => I18n.t("contacto_formulario_email"), :required => true %>
/** (....other tags ....) **/
<%= recaptcha_tags :display => 'clean' %>
<%= f.button I18n.t("contacto_formulario_continuar"), type: "submit" %>
<% end %>
app/assets/javascripts/contact.js
$(function() {
$('.g-recaptcha').attr("data-callback", "recaptcha");
})
function recaptcha()
{
console.log("captcha pulsado!");
/** the actions you want, i.e. activate submit button **/
}
The magic ocurrs in the attribute "data-callback"
Hope it helps.
Marino

Search and display multiple columns when using jquery autocomplete in Rails?

I have successfully integrated Jquery-Autocomplete into my rails app, currently users can search more than 5000+ airports and so far the integration works exactly as desired, however...
Any Airport has multiple columns, currently i am returning the airport name but would like to instead show
**
airport_name - airport_city - airport_iata - airport_icao
**
I have so far used Ryan Bates Railscast to get me started
Episode #102
But amended and tweaked thanks to other resources since his video. Sorry i can't reference them right now but will update my question once i've found links to their instructions.
Either way Autocomplete does work as designed and i have managed to populate a hidden field but i would really like to display more than just the Airport name when searching. I will continue to only save the airport ID.
Any help is appreciated, here is my code.
_form.html.erb
<div class="field">
<%= f.label :departure_airport %><br>
<%= text_field_tag nil, nil, :id => 'claim_departure_airport_name', data: {autocomplete_source: Airport.order(:name).map { |t| { :label => t.name, :value => t.id } } }, class: "form-control" %>
</div>
<%= f.hidden_field :d_airport_id, id: 'd_airport_id' %>
<%= f.hidden_field :a_airport_id, id: 'a_airport_id' %>
claims.coffee
jQuery ->
$('#claim_departure_airport_name').autocomplete
source: $('#claim_departure_airport_name').data('autocomplete-source')
select: (event, ui) ->
# necessary to prevent autocomplete from filling in
# with the value instead of the label
event.preventDefault()
$(this).val ui.item.label
$('#d_airport_id').val ui.item.value
$('#claim_arrival_airport_name').autocomplete
source: $('#claim_arrival_airport_name').data('autocomplete-source')
select: (event, ui) ->
# necessary to prevent autocomplete from filling in
# with the value instead of the label
event.preventDefault()
$(this).val ui.item.label
$('#a_airport_id').val ui.item.value
As you can see i am directly reaching the model data without the need for a dedicated controller although i realise this would be much more intelligent than my current solution as i wish to roll this out in other areas of the platform.
I don't fully understand everything that is happening in the jquery code in my coffee file this was obtained from another source although i forget who to give credit. As far as i know it's taking the ID of the airport and populating the hidden field?
If you can spot how to show other airport database columns to the user that would be great.
Thanks
edit
Also wish to restrict autocomplete from loading the data source into html due to seriously long page load times. A screen shot of what i mean is below.
screenshot of data loading
You can modify the autocomplete source to
<%= text_field_tag nil, nil, id: 'claim_departure_airport_name', data: { autocomplete_source: Airport.select(:id, :name, :city, :iata, :icao).order(:name).map { |t| { label: "#{t.name}-#{t.city}-#{t.iata}-#{t.icao}", value: t.id } } }, class: "form-control" %>
To refactor this a bit, you can move the active record query into a helper
def airport_autocomplete_data
Airport.select(:id, :name, :city, :iata, :icao).order(:name).map { |t| { label: "#{t.name}-#{t.city}-#{t.iata}-#{t.icao}", value: t.id } }
end
and your text field becomes
<%= text_field_tag nil, nil, id: 'claim_departure_airport_name', data: { autocomplete_source: airport_autocomplete_data }, class: "form-control" %>
The main point is here data: {autocomplete_source: Airport.order(:name).map { |t| { :label => t.name, :value => t.id } } }
It builds an array of objects, like [{'label': 'BKK', value: 1}, {'label': 'HAM', value: 2}]
So you either need to add something to the label key, or maybe add a different key and use it later in the select callback.
If you are using rails4-autocomlete Gem. You can easily override from controller.
def autocomplete_profile
term = params[:term]
profiles = Profile.where(
'LOWER(profiles.first_name) LIKE ? OR LOWER(profiles.last_name) LIKE ?',
"%#{term}%", "%#{term}%"
).order(:id).all
render :json => profiles.map { |profile| {:id => profile.id, :label => profile.id, :value => profile.id} }
end

Unresponsive javascript when using collection_select?

I have just started learning rails, html and javascript. I am using a collection_select to allow a user to select other users in the database:
<%= f.collection_select :id, Customer.where(business_id: current_customer.business_id), :id, :full_name, :prompt => 'Select', :html => { :id => "colleageselect", :onChange => "renderColCal(this)"} %>
<div id = colleaguecal> </div>
I have just been trying to test whether onChange works, by using the javascript:
<script type = "text/javascript">
function renderColCal(select){
alert('this is a test' + select.valueOf() );
document.getElementById("colleaguecal").innerHTML = "foo"
}
</script>
But changing the collection_select value when running the page doesn't do anything? Am I missing something here?
check the generated html if it is what you are expecting. I don't see any issues with the js although it would be better if it was unobstrusive. The only thing that may have caused your issue is that you didn't just passed a hash to the html options. Try
f.collection_select :id,
Customer.where(business_id: current_customer.business_id),
:id,
:full_name,
{ prompt: 'Select' },
{ id: "colleageselect", onChange: "renderColCal(this)" }

Categories