Preview form button in another view - javascript

I have a form where user enters some information (text boxes, select box). Inside the form I have a link_to "Preview" where users can preview what they did without saving it. They can preview it in the view of another controller I already have. Any advice on how to do this would be highly appreciated. I tried with js and ajax but it didn't work. I think that the biggest problem is how to pass form params to link_to. I am using Ruby on Rails 3.2, jQuery, JavaScript. Thanks.
Here is some code. In the second controller which checks if it is a preview or not after user clicks Preview:
def index
if !params[:access_token].nil?
#p = "something"
#m.access_token = params[:access_token]
#m.title = params[:title]
#m.body = params[:body]
else
#p = "something else"
end
respond_to do |format|
format.html
format.js
end
end
View (the first one where the form is and preview button) in haml + js, index.html.haml:
= form_for [:controller, #m], action: action, html: { multipart: true, id: "some_id" }, method: :post, remote: true do |f|
- #access_token = generate_access_token
= hidden_field_tag :access_token, #access_token
.input-prepend
%span.add-on Title
= f.text_field :title, id: "title"
.input-prepend
%span.add-on Body
= f.text_area :body, id: "body"
= f.submit t("save"), class: "btn btn-primary"
= link_to "Preview", " ", id: "preview", target: "_blank", class: "btn"
:javascript
$("#preview").click(function(e) {
var title = $("#title").val();
var body = $("#body").val();
var access_token = $("#access_token").val();
$.get('/' + "?access_token=" + access_token + "&title=" + title + "&body=" + body);
});
This .get probably doesn't make sense since it has to open in a new tab and new view.

If you really want to open the preview in a new tab/window, you can just change your last line to:
var url = '/' + "?access_token=" + access_token + "&title=" + title + "&body=" + body;
window.open(url, '_blank');
In your click event you'll want to e.preventDefault(): http://api.jquery.com/event.preventDefault/.
However, as others have noted, you don't really need to hit the server by requesting a new preview page. You might look into using something like Bootstrap's Modal or jQuery UI's Dialog to create a "popup" on the same page. The modal content would be very similar to the preview page you have set up, but with the title and body provided by e.g. var title = $("#title").val();.

var preview= window.open('/',title,'height=500,width=500');
preview.document.write(body); //you can write html code in it, your script vars in it
reference

Related

I want to see the textarea in Rails JUST as javascript does

I have a form that allows a user to submit HTML, and I just want to make a few changes to the text (e.g. replace a company name with one in Active Record), and then replace the HTML inside of a textarea. However, it's not playing too well. For whatever reason, trying to replace the textarea with the contents that were submitted in its POST request does not work. Nothing happens.
Here's my view form:
<div class="modal-body">
<div class="form-group row">
<div class="col-sm-12">
<%= form_tag(convert_email_template_path(format: :js), method: :post, :authenticity_token => true, id: 'importEmailForm', remote: true) do %>
<%= text_area_tag 'import_email', nil, rows: 10, placeholder: "Paste the headers of your email here.", class: "form-control" %>
<% end %>
</div>
</div>
</div>
<div class="modal-footer">
<%= link_to '<i class="fa fa-download"></i> Import'.html_safe, '#', onclick: "importEmail();", class: "btn btn-success btn-sm" %>
</div>
So basically, importEmail() looks like this:
function importEmail() {
setTimeout(function () {
$.ajax({
type: 'POST',
url: $("#importEmailForm").attr("action"),
data: $("#importEmailForm").serialize(),
});
}, 100)
};
which basically submits the form in the view. I need to capture this POST data, make a change or two, and then proceed with replacing textarea with the modified contents.
Now if I do this in plain javascript, this works fine:
#views/templates/convert_email.js.erb
var sourceBody = $('#import_email').val();
var start_position = sourceBody.indexOf("<html>");
var stop_position = sourceBody.indexOf("</html>");
var html = sourceBody.substring(start_position, stop_position);
var fixed_html = html.replace(/(=\n)/g, '');
// Grab body.
var iframe = document.getElementsByClassName("fr-iframe")[0]
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
// get the element in question
const input = innerDoc.getElementsByTagName("body")[0];
// Before pasting data, let's make sure the code view is turned OFF.
if ($('textarea').froalaEditor('codeView.isActive') == true) {
$('textarea').froalaEditor('codeView.toggle');
}
// dispatch keyboard events
input.innerHTML = fixed_html;
// Close modal.
$('#Modal').modal('toggle')
But if capture this POST data with params[:import_email], and do something like this:
#controllers/templates.rb
body = params[:import_email]
#body = body.gsub("=\n", "")
and pass that to the javascript view.
#views/templates/convert_email.js.erb
// Grab body.
var iframe = document.getElementsByClassName("fr-iframe")[0]
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
// get the element in question
const input = innerDoc.getElementsByTagName("body")[0];
// log codeview status
var codeView = 0
// Before pasting data, let's make sure the code view is turned OFF.
if ($('textarea').froalaEditor('codeView.isActive') == false) {
codeView = 0;
$('textarea').froalaEditor('codeView.toggle');
} else {
codeView = 1;
}
function
// dispatch keyboard events
input.innerHTML = "<%= #body %>";
resizeFroala();
// Close modal.
$('#Modal').modal('toggle')
Nothing happens. Perhaps there's a way to treat a textarea as source code or something?
Using the first method (javascript only), this is what fixed_html looks like in the console:
I want to get #body to look like this, but in order for me to do that, I have to do this in the controller:
body = params[:import_email]
#body = body.gsub("=\r", "\r").gsub("\n", "").gsub("\r", "").gsub("\t", "")
but trying to write this to the console looks like this:
Sorry for any confusion. Hope this makes sense. I just basically want to do what works flawlessly in Javascript, but in Rails.
Think I finally figured it out. Didn't realize rails used <%== %> in addition to <%= %>
Changed my code to:
input.innerHTML = "<%== j #body %>";
and this did the trick. Wow.

how to make collection_select value as link_to variable

I have the ff:
app/views/reports/index.html.erb
<h1>Reports</h1>
<br>
<legend>Categories</legend>
<div class="row">
<div class="span5">
<ol>
<li><%= link_to 'COMMENDATION', commendations_path(format: 'pdf'), { id: 'commendations_click' } %></li>
<%= collection_select(nil,
:employee_id,
#employees,
:id,
:last_name,
{:prompt => "Select an Employee"},
{:id => 'employees_select'}) %>
<br>
<%= collection_select(nil,
:employee_movement_id,
#employeemovements,
:id,
:position,
{:prompt => "-"},
{:id => 'employee_movements_select'}) %>
<li><%= link_to 'REPORT2', '#' %></li>
<li><%= link_to 'REPORT3', '#' %></li>
</ol>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
$('#employees_select').change(function() {
$.ajax({
url: "<%= update_employee_movements_path %>",
data: { employee_id : $('#employees_select').val() },
dataType: "script"
});
});
$('#commendations_click').click(function() {
$.ajax({
url: "<%= commendations_path %>",
data: {
employee_id : $('#employees_select').val(),
employee_movement_id : $('#employee_movements_select').val()
},
dataType: "script"
});
});
});
</script>
app/controllers/reports_controller
class ReportsController < ApplicationController
before_filter :authenticate_user!
# GET /reports
def index
#employees = Employee.all
#employeemovements = EmployeeMovement.distinct_positions
end
def update_employee_movements
if params[:employee_id]
#employeemovements = [].insert(0, "Select Employee Movement")
else
employee = Employee.find(params[:employee_id])
#employeemovements = employee.employee_movements.map{ |a| [a.position, a.id] }.insert(0, "Select Employee Movement")
end
end
def commendations
emdates = EmployeeMovement.last_2_dates_obtained(params[:employee_movement_id])
date_from = emdates[0].date_obtained
date_to = emdates.length == 1 ? nil : emdates[1].date_obtained
emp = Employee.find(params[:employee_id])
#commendations = case date_to.nil?
when true then emp.commendations.this_day_onwards(date_from)
else emp.commendations.within(date_from, date_to)
end
end
end
What I'm trying to do here is, I'm creating a page filled with links and drop down lists that will serve as a Reports center. The idea is, each link will be catered by a controller. Each controller will be responsible in showing my PDF in the browser (through ThinReports, if you're curious).
The #employees_select change event is used for changing the value of the #employee_movements_select collection_select.
Now my problem is, how can i capture the value of both #employees_select and #employee_movements_select and pass them to my commendations action?
I tested link_to by hardcoding values, and it works (code below)
<%= link_to 'COMMENDATION', commendations_path(employee_id: 1, employee_movement_id: 12, format: 'pdf') %>
However, If I use javascript to push the values to my commendations action through the 'click' event, my commendations action will be called twice, thus an error occurs because the params[:employee_id] in the action is now blank.
By the way, I need those values because my commendations action needs it so I can populate my PDF report template.
Please help. Thanks a lot in advance!
UPDATE 1
-> Updated link_to:
<%= link_to 'COMMENDATION', '#', { id: 'commendations_click' } %>
-> Removed dataType: "script" in #commendations_click event handler
-> Updated url: in #commendations_click event handler
url: <%= commendations_path(format: 'pdf') %>
UPDATE 2 (RESOLUTION)
I tweaked my javascript to look something like this:
$('#commendations_click').click(function() {
event.preventdefault();
window.location = "<%=j commendations_path(format: 'pdf') %>" + "?employee_id=" + $('#employees_select').val() + "&employee_movement_id=" + $('#employee_movements_select').val();
});
Works perfect now.
Two things come to mind. You can wrap the two select lists within a form element and just do a submit. Everything inside the form will be submitted to your server and you can process the request and handle the redirect on the server side. The other thing you can do is to handle the commendations click event on the client side using jquery or something. Just bind to the click event of that link, grab the values of the two select lists and do whatever you want with it. Remember, link_to just gets rendered as plain old html links on the view. For e.g.
link_to "Profile", profile_path(#profile) gets rendered as Profile

pass selected drop down value as params in rails link_to

I have a select tag which populates list of department names, When I select a value from drop down, I need to display an edit link below (link_to) and append the selected value of dropdown as id params.(I am not using form for this single select tag since I dont need to save value in my databse). How this could be possible. Please help. I am using rails2.3
I tried like the below but it didn't work.
Select A Dept
<%=select :select_dept, :dept, #dept.map{|dept| [dept.full_name, dept.id]},{:prompt => "#{t('select_a_batch')}"} %>
<%= link_to "Display", {:controller => "user", :action => "display_value", :id => $('#select_dept').val() } ,:class => "button" %>
Gopal is on the right track.
Give the link an id so you can pick it out
<%= link_to 'Display", {:controller ...}, :class => 'button', :id => 'display_link' %>
Hide it with CSS by default
#display_link { display:none; }
#display_link.showing { display:block; }
Then in javascript, do something like
$('#select_dept').on('change', function(ev) {
var deptId = $(this).find(':selected').val();
var newPath = '/users/' + deptId + '/display_value';
$('#display_link').attr('href', newPath);
$('#display_link').addClass('showing');
});
This will not set things up on page load, but you could run the same function you've passed as the change callback on page load to set things up (assuming one of the items might be selected on load).

rails: form on submit should go to a custom url containing values of two dropdown menus

i have a little problem with making a custom url from two value got from dropdown menus.
i am trying to use jquery to that. these two values have their ids as
#convertor_from_currency
#convertor_to_currency
jquery:
<script>
$(document).ready(function(){
$("#currency_form").submit(function(e){
e.preventDefault();
var from = $('#convertor_from_currency').val();
var to = $('#convertor_to_currency').val();
var url_end = from + "-" + to;
var url = $('#currency_form').attr('action') + '/' + url_end;
$('#currency_form').attr('action', url);
$('#currency_form').submit();
//alert(url);
});
</script>
and this is a markup of the form:
<%= form_for :convertor , :html => {:id => "currency_form"}, :url => {:controller => "converter", :action => "show" } do |f| %>
<%= f.label :from_currency %>
<%= f.select :from_currency, options_for_select(currencies, #from_cur) %>
<%= f.label :to_currency %>
<%= f.select :to_currency, options_for_select(currencies, #to_cur), :required => true %>
<%= f.submit "Calculate", class: "btn btn-large btn-primary", id: "submitButton" %>
<% end %>
routes
root 'converter#index'
# get "converter/show"
match '/currencies/', to: 'converter#show', via: [:post]
on submitting i want the url to be:
'/currencies/url_end
where "url_end" is a concatenation of the values submitted in the form:
#convertor_from_currency
#convertor_to_currency
updated, this is my controller.
class ConverterController < ApplicationController
def index
end
def show
#amount = params[:convertor][:amount]
#from_cur = params[:convertor][:from_currency]
#to_cur = params[:convertor][:to_currency]
#result = ConverterHelper.show(#from_cur, #to_cur, #amount)
end
end
how do i do this?
any ideas will be appreciated even if it is using another way other than jquery/javascript
Can you try rewriting this route:
match '/currencies/', to: 'converter#show', via: [:post]
to:
match '/currencies/:from-:to', to: 'converter#show', via: [:post]
In this case requests to (for example) /currencies/usd-eur will be routed to converter#show and you will be able to access the currencies in the controller action using params[from] and params[:to].
UPDATE:
There was an error in javascript code:
This code should work as you expected:
<script>
$(document).ready(function(){
$("#currency_form").submit(function(e){
var from = $('#convertor_from_currency').val();
var to = $('#convertor_to_currency').val();
var url_end = from + "-" + to;
var url = $('#currency_form').attr('action') + '/' + url_end;
$.post(url, $('#currency_form').serialize(), function(data){alert('success');});
alert(url);
e.preventDefault();
return false;
});
});
</script>
You should not call submit on form as long as you are inside submit handler. Instead, you should use $.post(...) to submit the form data. Form data can be serialized as in my example to be sent with the $.post(). You should have added "});" before closing tag.
One of routing configurations that should work for you:
match '/currencies/' => 'converter#index', as: :converter
match '/currencies/:from-:to' => 'converter#show', via: [:post]
your form should use converter_path helper as the action url. And the JS code should submit the form to /currencies/:from-:to.
You need to update the form in the view to:
{:id => "currency_form"}, :url => converter_path do |f| %>
You can use this sample code in your controller to ensure that the form is submitted correctly:
def show
#amount = params[:convertor][:amount]
#from_cur = params[:convertor][:from_currency]
#to_cur = params[:convertor][:to_currency]
##result = ConverterHelper.show(#from_cur, #to_cur, #amount)
render text: "text"
end
You can uncomment the line and remove render once you see that the form is correctly processed on the server.
this can help (it worked for me)
<script>
$(document).ready(function(e){
$("#currency_form").submit(function(){
var from = $('#convertor_from_currency').val();
var to = $('#convertor_to_currency').val();
var url_end = from + "-" + to;
var url = $('#currency_form').attr('action') + '/' + url_end;
$('form#currency_form').attr('action', url);
// window.location.href = url
e.preventDefault();
alert(url);
return false;
});
});
</script>
you can (un)comment to make it work according to your question
don't forget your routes
root 'converter#index'
match '/currencies/', to: 'converter#show', via: [:post]
post '/currencies/:url' => 'converter#show'
then upvote!!!!

Rails and jQuery: How to select input from a specific form

I have a rails app with a job model, and on the index page, each job has a form. I need to be able to access the specific form everytime the submit button is selected, so I can take the input for the form and perform some jQuery validation with it.
Here is some of my index.html page.
<ul>
<% #unassigned.each do |job| %>
<li>
<div class="row new-message">
<div class="small-12 columns">
<%= form_for #message do |f| %>
<%= f.text_area :body, {placeholder: 'enter a new message...'} %>
<%= f.hidden_field :job_id, value: job.id %>
<%= f.submit 'send message', class: 'button small radius secondary message-button', "data-job-id" => job.id %>
<div id="message<%= i %>-validation-errors"> </div>
<% end %>
</div>
</div>
<li>
<% end %>
<ul>
And here is the javascript/jQuery where I try to select the input from a specific form
var messages;
messages = function() {
$('.message-button').click(function(e) {
var id = $(this).data('job-id');
messageValidation(e, id);
});
function messageValidation(e, id) {
var body = $('#message_body').val();
var div = '#message' + id + '-validation-errors';
if(body == "") {
$(div).html('');
e.preventDefault();
$(div).html('<small style="color:red"> Message body empty </small>');
}
};
};
$(document).ready(messages);
The index page will have a form for each job, and I want there to be front end validation that checks when the button is submitted, that the body field is not empty. It works fine the first time, but after going back to the index page, and trying to validate a second time var body = $('#message_body').val(); always seems to be empty, whether I put anything in the body or not. I believe it has something to do with the fact that since there is the same form for each job, there are multiple #message_body id's on the same page, and it is selecting the incorrect one. I am new to jQuery and javascript can someone please help me
You cannot have multiple elements with same id on a page. What you can do is add a class identifier to those elements.
In your case, simple set class="message_body" to your elements and select them as shown below:
$('.message-button').click(function(e) {
var id = $(this).data('job-id');
var body = $(this).parent().find('.message_body').val();
messageValidation(e, body, id);
});
To solve this problem I needed to select the child of the form and find the message_body through that.
messages = function() {
$('.new_message').submit(function(e) {
//var id = $(this).data('job-id');
var $this = $(this);
var body = $this.children('#message_body').val();
var id = $this.children('#message_job_id').val();
messageValidation(e, body, id);
});
function messageValidation(e, body, id) {
var div = '#message' + id + '-validation-errors';
if(body == "") {
$(div).html('');
e.preventDefault();
$(div).html('<small style="color:red"> Message body empty </small>');
}
};
};

Categories

Resources