In TextField of Ruby Code, I want to check whether the specified class is applied or not, on blur event. Please suggest some technique or way. Sample code is given below used by me.
Ruby Code for TextField::
<%=f.text_field :Username, :size=>4, :tabindex=>2, :class=>class_name,
:autocomplete => "off", :onblur=> $$$$$ %>
Suppose class_name : 'changeView' is applied on above textfield, then I have to detect this particular class & replace by another one like 'changeExtraview'. By using any of the javascript, we can replace that class name but suggest if you have any better option.
Thanks
Just a guessed answer...
So your class_name might be contain a value of changeView, and if in the case, you want to replace the changeView class name to changeExtraview, right?
If it is, then the following should be ok:
<%=f.text_field :Username, :size=>4, :tabindex=>2, :class=>class_name.gsub(/changeView/, "changeExtraview"), :autocomplete => "off", :onblur=> $$$$$ %>
========================
Another try:
<%=
f.text_field :Username, :size=>4, :tabindex=>2, :class=>class_name, :autocomplete => "off",
:onblur => "if($(this).hasClass('changeView')) {$(this).removeClass('changeView'); $(this).addClass('changeExtraview')}"
%>
========================
As #Faisal pointed out, using binding in JS side would be better. Although the answer was long time ago, I decided to update the answer again:
<%= f.text_field :Username, :size => 4, :tabindex => 2, :class => class_name, :autocomplete => "off" %>
And in any ways (I use content_for in this example), add the following js code:
<%= content_for :javascripts do %>
<script type="text/javascript">
jQuery(document).ready(function($) {
$("<%= class_name %>").bind("blur", function() {
var $this = $(this);
if ($this.hasClass('changeView')) {
$this.removeClass('changeView');
$this.addClass('changeExtraView');
}
});
});
</script>
<% end %>
Note that the above code requires you have <%= yield :javascripts %> in your layout file,
Related
I'm having trouble accessing and using the value of a checkbox and then select field for forms dynamically added via the Cocoon Gem for Rails. I've read through many SO posts and the official Cocoon documentation and I just can't seem to get it right.
The idea is that after adding a form via Cocoon, there are hidden fields that only show up if a specific checkbox is :checked, with one of those fields that being a f.select and upon the selection of that value more fields will either show or hide.
_mortgage_fields.html.erb
...
<%= f.form_group :misc_mortgage do %>
<%= f.check_box :misc_mortgage, label: "Miscellaneous Mortgage" %>
<% end %>
<%= f.select :misc_mortgage_context, [["Assignment", "Assignment"], ["Subordination", "Subordination"], ["Modification", "Modification"]],
{ label: "Miscellaneous Mortgage Type" }, wrapper: { class: 'mtgHidden' }%>
<%= f.text_field :reference_mortgage, class: 'form-control', wrapper: { class: 'mtgHidden' } %>
<%= f.text_field :subordinated_mortgage, class: 'form-control', wrapper: { class: 'Subordination' } %>
<%= f.text_field :modification_amount, class: 'form-control', wrapper: { class: 'Modification' } %>
...
The top level form is wrapped with <div id="mtgForm">..</div>
cocoonoptions.js
$(document.ready(function() {
$('#mtgForm').on('cocoon:after-insert', function(e, misc_checkbox) {
alert('getting there');
$(misc_checkbox).find('input[type=checkbox][id*="+misc_mortgage"]').change(function() {
alert('almost there');
if ($(this).is(':checked'))
alert('there!');
$('.mtgHidden').show();
else
$('.mtgHidden').hide();
});
$(misc_checkbox).find("select[name*='misc_mortgage_context']").change(function() {
var mtg = $(this).val();
if (mtg == "Subordination") {
$('.Subordination').show();
$('.Modification').hide();
}
else if (mtg == "Modification") {
$('.Modification').show();
$('.Subordination').hide();
}
else {
$('.Subordination').hide();
$('.Modification').hide();
}
});
});
The wrapper: { ... } fields are set to display: none by CSS and then shown or hidden according to the above values via JS. This same code works (without the cocoon:after-insert part of course) on a static HTML page for adding a single item without the necessity of adding multiple items at once like Cocoon is beautifully made to do.
I've tried the code above many different ways based on different posts or sites I've found online but I can only seem to get the first test alert to fire. Including misc_checkbox.find('...') without the $(...) wrapper.
Am I going about this the wrong way or is my code just incorrect? Thanks in advance for any and all help!
Update
Of course as soon as I post the question I figured it out. The + in [id*="+misc_mortgage"] was throwing it off and I wasn't loading cocoonoptions.js correctly. Going to leave this question up so maybe it will help someone in the future.
So my code was almost correct. Once I changed
$(misc_checkbox).find('input[type=checkbox][id*="+misc_mortgage"]')
to $(misc_checkbox).find('input[type=checkbox][id*="misc_mortgage"]') and loaded the JS via
<% content_for :javascript do %>
<script type="text/javascript">
</script>
<% end %>
function at the bottom of view, everything worked.
I'm following this railscast on nested forms to create a similar application.
In Ryan's application he has a structure like:
Surveys ---> 2. Questions ---> 3. Answers
So a user can create a survey and add/delete questions, with corresponding answers that they can add/delete.
I'm trying to do it a little differently. I have:
Surveys ---> 2. Questions ---> 3. Answers Or Comment
For my application, after a user has created a question, the user can create an answer (just like Ryan's app). But there is a select box next to each answer, with the default being "Answer" and the other being "Comment". I'm trying to get basically the same functionality of Ryan's app, but with two tables: comments table and answers table.
My code mimics the railscast, except for my answer_fields partial looks like:
<fieldset>
<%= f.label :content, "Answer" %>
<%= f.select :switch_answer_table options_for_select(["Answer", "Comment"]), class: "change-type" %>
<%= f.text_field :content %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "remove" %>
</fieldset>
and I have a comment_fields partial that looks like:
<fieldset>
<%= f.label :content, "Comment" %>
<%= f.select :switch_answer_table options_for_select(["Comment", "Answer"]), class: "change-type" %>
<%= f.text_field :comment_content %>
... (leaving out some stuff) ...
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "remove" %>
</fieldset>
My question.rb model looks like:
class Question < ActiveRecord::Base
belongs_to :survey
has_many :answers
has_many :comments
accepts_nested_attributes_for :answers, allow_destroy: true
accepts_nested_attributes_for :comments, allow_destroy: true
end
I've been working on this, and I'm stuck. My jQuery only looks like this so far:
jQuery ->
$('form').on 'click', '.remove_fields', (event) ->
$(this).prev('input[type=hidden]').val('1')
$(this).closest('fieldset').hide()
event.preventDefault()
$('form').on 'click', '.add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
$('form').on 'change', '.change-type', (event) ->
# Confused on how to change partials
Basically, I need a way to onChange, the partial for the selected answer/comment.
alejandro babio is correct. render both partials. give one of them a style of display:none and then toggle the class in your coffescipt onchange handler. In the case that a user starts to type an answer and then switches to a comment you'll also want to clear the fields associated with the newly hidden fields otherwise on submit you could have both comment and answer submitted.
First at all, you must render both partials (answer_fields and comments_fields) with the form.
At the comments_partial replace <fieldset> with <fieldset style="display:none">
Change visibility of partials with coffeescript:
$('form').on 'change', '.change-type', (event) ->
$('.change-type').each ->
$(#).closest('fieldset').each ->
if $(#).is(':visible')
$(#).find('input').val('') # reset all filels to empty values
$(#).toggle()
I thing that do the trick.
I clear only input fields, but there must be all of them to prevent save de hidden element (like says hraynaud)
I haven't tested this, but perhaps you want to use dependent-fields-rails. Depending on the state of the select box you can then show either the comment box or answer box.
The example given on the github page (uses simple form, but you can apply the same to your form_for):
= simple_form_for(#filing) do
= f.input :registration_office, collection: ['habm', 'dpma']
.js-dependent-fields[data-select-id='filing_registration_office' data-option-value='habm']
= f.input :language, collection: ['english', 'german']
Then I guess you use fields_for to satisfy your has_many relationship for example:
f.select :switch_answer_table, collection: ['answer', 'comment']
.js-dependent-fields[data-select-id='question_switch_answer_table' data-option-value='answer']
f.fields_for :answers do |abuilder|
...
.js-dependent-fields[data-select-id='question_switch_answer_table' data-option-value='comment']
f.fields_for :comments do |cbuilder|
...
Again, not tested and a best guess but it hopefully nudges you into the right direction.
The partial fields are generated as a data attribute by the link_to_add_fields helper method. The js then gets the data object and renders it. Consider the following (this is untested but should be a good guide):
The easiest way would be to have seperate 'Add Answer' and 'Add Comment' links with seperate helper methods, or
Allow the user to select Answer or Comment before clicking the link to add and have each different partial as a different data attribute. e.g.
_form.html.erb
<select id="response_type_select_field">
<option value="comment">Comment</option>
<option value="answer">Answer</option>
</select>
<%= link_to_add_reply_fields "Add Reply", f, :answers, :comments %>
surveys_helper.rb
module SurveysHelper
def link_to_add_reply_fields(name, f, association_1, association_2)
object_1 = f.object.send(association_1).klass.new
object_1_id = object_1.object_id
object_1_fields = f.fields_for(association_1, object_1, child_index: object_1_id) do |builder|
render(association_1.to_s.singularize + "_fields", f: builder)
end
object_2 = f.object.send(association_2).klass.new
object_2_id = object_2.object_id
object_2_fields = f.fields_for(association_2, object_2, child_index: object_2_id) do |builder|
render(association_2.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_reply_fields", data: {id_1: object_1_id, id_2: object_2_id, object_1_fields: object_1_fields.gsub("\n", ""), object_2_fields: object_2_fields.gsub("\n", "")})
end
end
Coffee script:
jQuery ->
$('form').on 'click', '.add_reply_fields', (event) ->
time = new Date().getTime()
reply_type = $("#response_type_select_field option:selected").val()
if reply_type is 'answer'
data_attribute = 'object_1_fields'
regexp = new RegExp($(this).data('id_1'), 'g')
else if reply_type is 'comment'
data_attribute = 'object_2_fields'
regexp = new RegExp($(this).data('id_2'), 'g')
$(this).before($(this).data(data_attribute).replace(regexp, time))
event.preventDefault()
Basic Problem: I have a line of text, and on hover, I want that text to change to something else. Basic, right? What's tripping me up is that the text in question is stored in a hash in my controller, and I'm looping through it.
Here's a smaller version of my hash in my PagesController:
def team_list
return [ {
name: "Employee 1",
title: "Founder and CEO",
secret_title: "Something Funny",
image: "about-employee-color.jpg",
alt_image: "about-employee-alt.jpg"
},
{
name: "Employee 2",
title: "Not Founder and CEO",
secret_title: "Something Else Funny",
image: "about-employee2-color.jpg",
alt_image: "about-employee2-alt.jpg"
} ]
end
So then in my view (with #team defined as that hash in my PagesController), I'm looping through to create an About Page entry for each person.
<% #team.each do |member| %>
<div class="about-team">
<%= image_tag member[:image], :mouseover => member[:baby_pic] %>
<%= image_tag member[:baby_pic], :style => "display:none;" %>
<h2><%= member[:name] %></h2>
<h4><%= member[:title] %></h4>
<h4 style="display:none;"><%= member[:secret_title] %></h4>
</div>
<% end %>
And I'm trying to see if there's an easy solution just like my image_tag :mouseover to get my titles to change to secret_titles on hover. I tried CSS first, similar to this. But I can't just put that member variable into the CSS since it doesn't exist outside that loop. I imagine JavaScript would be the same way.
h4:hover { content:<%= member[:secret_title] %>; }
Anyway, what I'm hoping for is something like a text_tag that I haven't come across yet that has a similar :mouseover attribute as image_tag.
You can use a JQuery functionality to swap values that you store directly as attributes in the DOM element, which in this case will be the div with class about-team, without really changing rails controller.
Storing values:
<% #team.each do |member| %>
<div class="about-team" member-title="<%= member[:title] %>" secret-title="<%= member[:secret_title] %>">
<%= image_tag member[:image], :mouseover => member[:baby_pic] %>
<%= image_tag member[:baby_pic], :style => "display:none;" %>
<h2><%= member[:name] %></h2>
<h4><%= member[:title] %></h4>
</div>
<% end %>
Swaping values (JQuery defined once):
$('.about-team h4').hover(
function(){ //mouse enter
$(this).html($(this).parent().attr('secret-title'));
},
function(){ //mouse leave
$(this).html($(this).parent().attr('member-title'));
}
);
JQuery hover event as defined in API docs binds 2 handlers to the matched elements, so you can execute your swap logic when mouse is over and out as done in the code above.
JSFIDDLE: http://jsfiddle.net/VmqB7/4/
I have a form with 3 input fields, strokes, putts, and GIR:
<%= form_for(#played_hole) do |f| %>
<%= f.hidden_field :hole_par, value: #hole.par %>
<%= f.label :strokes, "How many strokes?" %>
<%= f.select(:strokes, options_for_select(generate_strokes_array(#hole.par), selected: #hole.par)) %>
<%= f.label :putts, "How many putts?" %>
<%= f.select :putts, options_for_select(generate_putts_array(5), selected: 1), onclick: calculateGIR() %>
<%= f.label :GIR, "Green in Regulation?" %>
<%= f.select(:GIR, [['Yes', 1], ['No', 0]]) %>
<%= f.submit "Next Hole", class: "btn btn-large btn-success" %>
<% end %>
My goal is to automatically select the 3rd field (:GIR) once the user clicks on the second input, putts. For example, if the hole is a par 4 and they selected 5 in the :strokes field and 2 in the :putts field, then I would know that they didn't get a Green In Regulation. So, I'd like to automatically switch the :GIR select to 'No'.
I'm currently having trouble just getting an onclick() event registered. I've added onclick: calculateGIR() to the :putts select field but I'm getting this error in my PlayedHole#new view: undefined method calculateGIR' for #<#<Class:0xb5a684c4>:0xb591eac8>
I've added this to the javascript/played_holes.js file: function calculateGIR() { alert("calculating GIR"); } but obviously it's not being picked up.
Basically, I could use some help calling javascript (or jQuery) functions within a view. And then once I get that setup I'd like to figure out how to pull the selected value from :strokes and :putts to calculate the GIR.
For those curious, a GIR means you were on the green in 2 (or less) strokes than the par for the hole. i.e. Par 3 - 1 stroke, Par 4 - 2 strokes, Par 5 - 3 (or less) strokes.
And I'm running Rails 3.2, in case you're curious.
Thanks!
You need to put calculateGIR() in quotes:
<%= f.select :putts, options_for_select(generate_putts_array(5), selected: 1), onclick: "calculateGIR()" %>
The onclick HTML attribute should be a a string of JavaScript code that will be executed on click. Instead, you are trying to call a Ruby method, calculateGIR.
Alternative to my comment in your question:
Try: <%= f.select :putts, options_for_select(generate_putts_array(5),
selected: 1), onclick: 'calculateGIR()' %>, put calculateGIR() in
quotes.
It's better not to place javascript into your HTML as you've shown. Unobstrusive way to do this would be to assign an id to the select element and apply calculateGIR logic in the change event.
Something like following is better:
In your view:
<%= f.select :putts, options_for_select(generate_putts_array(5), selected: 1), {}, id: 'putts' %>
In your javascript/played_holes.js
$(document).ready(function() {
$('#putts').on('change', function() {
// Place definition of calculateGIR() here.
});
});
I have a set of dependent dropdown menus on my user/edit page. The user selects the parent dropdown, which then limits the selections available in the child dropdown. The user can add multiple additional sets of parent/child dropdowns. Product is the parent. Variety is the child.
This all works great unless a variety is entered into the database that includes double quotes. When that happens, it breaks the javascript and the trigger to render the partial doesn't work at all.
Single quotes do not cause this problem, nor do any other characters that I've tried. So this problem is specific to double quotes. I thought that escape_javascript was the answer here, but I've tried placing it in many different places in the code and nothing has worked. It's very possible that I just don't know exactly where the helper and it's parenthesis are supposed to go.
The api documentation is terrible. It says escape_javascript(). That's not helpful for me. Similarly, there isn't much clear guidance online. I've searched for hours.
Here are the relevant parts of my code:
Users#edit.html.erb
<%= render :partial => 'season', :collection => #user.seasons %>
Users#_season.html.erb
<% fields_for prefix, season do |season_form| -%>
<%= error_messages_for :season, :object => season %>
Product: <%= season_form.collection_select :product_id, Product.find(:all, :order =>'name'), :id, :name, {:prompt => "Select Product"}, {:onchange => "collectionSelected(this);"} %>
<% varieties = season.product ? season.product.varieties : Variety.all %>
<%= season_form.select :variety_id, options_from_collection_for_select(varieties, :id, :name, season.variety_id), :prompt => "This is optional" %>
Javascripts#dynamic_varieties.js.erb
var varieties = new Array();
<% for variety in #varieties -%>
varieties.push (new Array (<%=h variety.product_id %>, "<%=h variety.name %>", <%=h variety.id %>));
<% end -%>
function collectionSelected(e) {
product_id = e.getValue();
options = e.next(1).options;
options.length = 1;
varieties.each(function(variety) {
if (variety[0] == product_id) {
options[options.length] = new Option(variety[1], variety[2]);
}
});
}
Assuming you're just doing some escaping wrong (and that rails does it correctly), you could try something like:
var varieties = <%= #varieties.map { |v| [v.product_id, h(v.name), v.id] }.to_json %>