Ruby on Rails Simple_Form Textfield with javascript - ruby-on-rails

I have an application with a large Text field:
<%= simple_form_for(#language) do |f| %>
<div class="form-inputs">
<%= f.input :text_message, :input_html => { :class => "span8", rows: "12" } %>
</div>
And I'm trying to add this HTML and Javascript which allows me to click a button to add a predetermined value into the textfield. Right now it works but I can't figure out how to link it to the RoR textfield.
<form name="virtual">
<input type="text" name="text"/>
<input type="button" onclick="last_name()" value="Last Name" style="border:none;"/>
<input type="button" onclick="first_name()" value="First Name" style="border:none;"/>
</form>
<script type="text/javascript">
function last_name(){
document.forms["virtual"]["text"].value += "{last_name}";
}
function first_name(){
document.forms["virtual"]["text"].value += "{first_name}";
}
</script>
So my question is, how can I combine these two so that selecting the buttons will add "{last name}" or {first name} to the text_message field in the Language model, and not the plain html form.
Edit: To provide more context - later on these variables like {last_name} will be parsed out and replaced with their associated fields - but for now that's not relevant as all I'm trying to do is create buttons that input the actual string "{last_name}" or "{first_name}" into the textfield. This JS was the only way I could figure out to do this
Thanks!

Related

How to use label.radio-inline instead of span.radio-inline > label with bootstrap 3 and simple_form 3.1.0?

I use bootstrap v3.3.1 and simple_form 3.1.0.
I wrote f.input :some_column, as: :radio_buttons, item_wrapper_class: 'radio-inline' in a horizontal form.
And simple_form 3.0.2 generates label.radio-inline > input, but simple_form 3.1.0 generates span.radio-inline > label > input.
It seems bootstrap's Inline checkboxes and radios assumes label without span. (http://getbootstrap.com/css/#forms-controls )
How to remove span and set radio-inline class to inline labels?
I tried item_wrapper_tag: false and I can remove span, but I cannot set radio-inline class to inline labels.
I tried label_html: { class: 'radio-inline' }, and it sets class to label of left column instead of inline labels.
Here is simple radio button inline solution
CSS
.radio-buttons-inline{
.make-md-column(12);
}
.radio-buttons-inline {
.margin-right(10px);
}
HTML
<div class="radio-buttons-inline">
<label class="radio-inline">
<input type="radio" name="inlineRadioOptions" value="option1">1
</label>
<label class="radio-inline">
<input type="radio" name="inlineRadioOptions" value="option1">2
</label>
<label class="radio-inline">
<input type="radio" name="inlineRadioOptions" value="option1">3
</label>
<hr>
</div>
http://jsfiddle.net/52VtD/9291/
I know it's too late but for anyone out there looking for an answer and found this thread I think you might be looking for something like this:
f.input :some_column, as: :radio_buttons, item_wrapper_class: 'radio-inline', item_wrapper_tag: 'label'

Dynamic changes in rails form (simpleform)

I'm trying to make a simple form with this general structure:
o accept o decline
[submit]
when the radio button accept is checked and submit pressed, I want it to change the state of my model (called Offer here).
BUT when the button decline is checked, the form needs to change to something like this:
o accept x decline
Please enter reason here: [text box]
[submit]
Having entered a (mandatory) reason for declining and pressing submit, will change the state of the model Offer too, but differently.
I'm currently having problems getting the form to display the way I want. I'm using SimpleForm and tried something like this:
<%= simple_form_for #offer do |f| %>
<%= f.input accepts, as: :radio_buttons %>
<%= f.input :r_comment, as: :text, :label => 'Please enter reason here:' , :input_html => { :rows => 2, } %>
<%= f.button :submit %>
<% end %>
This of course doesn't work, because there is no "accepts" method or variable defined for offers (and it shouldn't be!). As for dynamically showing the input text box, I don't even have the slightest clue.
I'd be glad for any help you might offer,
Lordylike
UPDATE: HTML generated by simple_form
<div class="control-group radio_buttons optional">
<label class="radio_buttons optional control-label">Accept?</label>
<div class="controls">
<label class="radio">
<input class="radio_buttons optional" id="offer_accepts_decline" name="offer[accepts]" type="radio" value="Decline" />
Decline
</label>
<label class="radio">
<input class="radio_buttons optional" id="offer_accepts_accept" name="offer[accepts]" type="radio" value="Accept" />
Accept
</label>
</div>
UPDATE: HTML generated for comment box
<div class="control-group text optional">
<label class="text optional control-label" for="offer_r_comment">Reason for rejection:</label>
<div class="controls">
<textarea class="text optional" cols="40" id="offer_r_comment" name="offer[r_comment]" rows="2">
</textarea>
</div>
</div>
i'm not a fan of formtastic or simple_form but looking at the documentation, you should be able to do the following
# offer.rb
attr_accessor :accepts
# view
<%= f.input :accepts, as: :radio_buttons, collection: ['Decline', 'Accept'] %>
# js which can be placed inline or in the assets. let's use coffee
# you should also limit the selector below to include the class or the id of the
# radio buttons. I'm also not familiar with the html generated by simple form so
# the selectors to show and hide should also be changed.
$ ->
$(':radio').change ->
if $(this).prop('checked')
if $(this).val() == 'Accept'
$('#offer_r_comment').show()
else
$('#offer_r_comment').hide()
UPDATE: non coffee version. you can place this inside a script tag and just throw in the view.
$(document).ready(function() {
$(':radio').change(function() {
if ($(this).prop('checked'))
if ($(this).val() == 'Accept')
$('#offer_r_comment').show();
else
$('#offer_r_comment').hide();
});
});

Styling file upload button for simple_form_for with Bootstrap in Rails 3

Using simple_form_for, Bootstrap and Rails 3. In a form:
<%= f.input :upload, label: 'PDF file:' , input_html: {accept: ('application/pdf') } %>
I don't know how I'd style this so that the "choose file" button can have a different class ('btn btn-primary').
Additionally, when using with Bootstrap at least, its severely misaligned by default. See attached image.
Finally, how do I redefine the text from "No file chosen" to "Chose file" when there isn't one added yet, and show the file name when there is one.
This is how I do it:
In the view add your form file field and hide it
Add a styled additional field just to display the file name
Add a button to trigger the file browse dialog
<div class="control-group">
<div class="attach-set">
<%= f.input :real_file, input_html: { hidden: true }, label: 'Upload Attachment' %>
<div class="input-append">
<input id="file-display" class="input-large uneditable-input" type="text">
<a id="upload-btn" class="btn"><i class="icon-upload-alt"></i> Browse</a>
</div>
</div> <!-- /attach-set -->
</div> <!-- /control-group -->
In your JS (Coffee w/ jQuery shown), pass the click from the display button onto the real file input and when they select a file drop the file name in the display text field (I drop the path so that I don't see C:\FakePath....)
$(document).ready ->
# ------------------------------------------------------
# pretty-fy the upload field
# ------------------------------------------------------
$realInputField = $('#real_file')
# drop just the filename in the display field
$realInputField.change ->
$('#file-display').val $(#).val().replace(/^.*[\\\/]/, '')
# trigger the real input field click to bring up the file selection dialog
$('#upload-btn').click ->
$realInputField.click()
This worked great for me and only requires HTML
<label class="btn btn-primary">
Add a file!
<span style="display:none;">
<%= f.file_field :image, required: true, multiple: true, name: 'picture' %>
</span>
</label>
I ran across and am using Jasny's extension to Bootstrap 3. It seems to work well so far.
No JS required, just plain css
scss
.fileinput-button {
position: relative;
overflow: hidden;
float: left;
margin-right: 4px;
width: 110px;
height: 32px;
input{
opacity: 0;
filter: alpha(opacity=0);
transform: translate(-300px, 0) scale(4);
direction: ltr;
cursor: pointer;
}
}
html / slim
span class="btn btn-success fileinput-button"
i.fa.fa-pencil
span
| Select File
= f.file_field :cover_ar
I recommend using compass for cross browser compatibility
As #rafaelfranca said you can't style file input but you can add your own button which will be clicking your hidden original button. See example here http://jsfiddle.net/rUdf2/6/
Every Browser has a different type of file input field button and this makes it a pain. You can play a little with css. This has given me a basic styling with JS without the annoying "No file chosen" text in chrome and Safary:
$(document).ready(function() {
$(".your_button").css("width", "80px");
});
Otherwise the best solution is to hide it and show a fake one that intercepts the click:
http://duckranger.com/2012/06/pretty-file-input-field-in-bootstrap/
With respect to the question of how to show that a file has been uploaded, a basic solution with jquery file upload is to detect the upload complete event and replace some of your text with a success message (The exact file name I believe it is not possible to obtain with modern browsers):
$(".your_button").fileupload({
dataType: "json",
done: function(e, data) {
$(".place_for_your_text").text("File uploaded.");
}
});
In summary, a basic solution is to use javascript in your assets to:
Hide the annoying "No file chosen text" with css.
Place your "Chose file" text next to the button and give it a class you can reference.
Replace the text with "File uploaded"
No fancy shiz required:
HTML:
<form method="post" action="/api/admin/image" enctype="multipart/form-data">
<input type="hidden" name="url" value="<%= boxes[i].url %>" />
<input class="image-file-chosen" type="text" />
<br />
<input class="btn image-file-button" value="Choose Image" />
<input class="image-file hide" type="file" name="image"/> <!-- Hidden -->
<br />
<br />
<input class="btn" type="submit" name="image" value="Upload" />
<br />
</form>
JS:
$('.image-file-button').each(function() {
$(this).off('click').on('click', function() {
$(this).siblings('.image-file').trigger('click');
});
});
$('.image-file').each(function() {
$(this).change(function () {
$(this).siblings('.image-file-chosen').val(this.files[0].name);
});
});
CAUTION: The three form elements in question MUST be siblings of each other (.image-file-chosen, .image-file-button, .image-file)
If you are using Bootstrap, Simple Forms, Jasny, and ReFile, this post may be of interest to you refile simple_form undefined method attachment_field
<label class="btn btn-primary"
<%= f.input :upload, label: 'PDF file:',
class:"hidden", input_html: {accept: ('application/pdf') } %>
</label>
Works for me
Using class="hidden"
PS: I'm using Tailwind CSS

Twitter bootstrap "lead" not working with simple_form

I'm using Twitter Bootstrap along with simple_form in Rails. For some reason I cannot get the Bootstrap class="lead" to function. I see in the rendered HTML some additional classes which I assume come from simple_form. How can I get the two to play together?
This is my code:
<p class="lead">
<%= sentence.input :dialog, :input_html => { :class => "span8" },
:placeholder => "Enter your sentence here", :label => false %>
</p>
And this is the rendered HTML:
<p class="lead">
<div class="control-group string optional">
<div class="controls"><input class="string optional span8" id="dialog_catagory_dialogs_attributes_0_dialog" name="dialog_catagory[dialogs_attributes][0][dialog]" placeholder="Enter your sentence here" size="50" type="text" />
</div>
</div>
</p>
EDIT
I've tried various options, including using the rendered HTML, like this and removing the divs. Still not working.
<p class="lead">
<input class="string optional span8" id="dialog_catagory_dialogs_attributes_0_dialog" name="dialog_catagory[dialogs_attributes][0][dialog]" placeholder="Enter your sentence here 2" size="50" type="text" />
</p>
output
<p class="lead">
<input id="dialog_catagory_dialogs_attributes_0_dialog" name="dialog_catagory[dialogs_attributes][0][dialog]" size="30" type="text" />
</p>
Here's the problem: Placing a div inside of a p element implicitly closes the p tag in standards-confirming browsers. ( Reference )
You can see (and modify locally, if you wish) the behavior of Simple Form's Bootstrap generators in this file on Github.

Setting up error message html view in this way?

I'm using Twitter-Bootstrap and want to generate the correct html to display the error view how it does it on the main site, which is:
The html for the above field is:
<div class="control-group error">
<label for="inputError" class="control-label">Input with error</label>
<div class="controls">
<input type="text" id="inputError">
</div>
</div>
Note: I deleted Please correct the error, <span>, I just want the input field and label.
And if I was to use my sign up page as an example, the email field, it would be:
<div class="control-group">
<label for="user_email" class="control-label">Email*</label>
<div class="controls">
<input type="email" value="" name="user[email]" id="user_email" class="span3">
</div>
</div>
What do I have to do to get it to function like the former?
Don't re-invent the wheel. Use simple_form. The current version of the gem allows you to do the following:
rails generate simple_form:install --bootstrap
With that, you can use the simple_form helpers. They will generate the right things for you.
I've just encountered this issue, and have fixed it with a simple modification to the Bootstrap CSS.
My usual field code is:
<div class="control-group">
<%= f.label :fieldname, t('models.model.fieldname'), :class => "control-label" %>
<div class="controls">
<%= f.text_field :fieldname, :class => 'input-large' %>
</div>
</div>
Since I'm using f.label and f.text_field the label and input are both encapsulated with divs with the field_with_errors class (as Nicholas mentions), making the resulting HTML:
<div class="control-group">
<div class="field_with_errors"><label class="control-label" for="model_fieldname">Field name</label></div>
<div class="controls">
<div class="field_with_errors"><input class="input-large" id="model_fieldname" name="model[fieldname]" size="30" type="text" value=""></div>
</div>
</div>
To make these have the same look appearance as Bootstrap's <div class="control-group error"> style I add some extra selectors into bootstrap.css. I find all references to .control-group.error ... and add duplicate lines with .control-group .field_with_errors .... So I end up with this kind of thing:
.control-group.error > label,
.control-group.error .help-block,
.control-group.error .help-inline,
.control-group .field_with_errors > label,
.control-group .field_with_errors .help-block,
.control-group .field_with_errors .help-inline {
color: #b94a48;
}
It might not be the most elegant way of doing it for Rails, but to me it seemed a lot easier than more dependant gems or overriding the error processing. Yes, you'll have to make the same changes each time you update Bootstrap, but they're fairly simple changes, and you could probably make a patch file to do it automatically.
Rails automatically generates a div with the class field_with_errors when an error message appears. That div wraps the element with error. In order to customize it, you can add this line to application.rb:
config.action_view.field_error_proc = Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe }
This is the default, so in order to get the same structure as Twitter Bootstrap, you could play with it.
html_tag is a placeholder for the field with errors, e.g. <input name="model[attribute]" size="30" type="text" value="">
You could wrap this within another div, and also add a span saying "Please correct the error".
More info: http://guides.rubyonrails.org/configuring.html - item 3.9

Resources