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

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.

Related

Receive Carrierwave URL through javascript

Is there a way to grab the Model.image_url through sql or javascript?
I have a select that when changed, I want the <img src=> to change dynamically.
With other situations I have done the following to change the background color of a div container:
<%= f.grouped_collection_select :color_id, #other_model, :colors, :title, :id, :title, include_blank: "Select Color" %>
<div id="div" style="background-color:<%= "#{model.color.hex}" %>;">
...
</div>
**javascript**
var colors = <%= Color.pluck(:id, :hex).to_h.to_json.html_safe %>;
document.getElementById("model_color_id").addEventListener("change", function(){
document.getElementById("div" %>").style.backgroundColor = colors[this.value];
}, false);
For getting the carrierwave imgae, I tried a similar approach:
var product_mock = <%= Item.pluck(:id, :image).to_h.to_json.html_safe %>;
document.getElementById("model_item_id").addEventListener("change", function(){
document.getElementById("item").src = product_mock[this.value];
}, false);
but this isn't grabbing the *.url' or *_url
Tried a way like this for onchange:
$('#shop_product_item_id').on('change', function(){
let item_id = $(this).val(); #tried with and without these 2 lines and with var
console.log(item_id); #tried with and without these 2 lines
var image = <%= Item.find(1).image_url %>;
document.getElementById("id").src = image;
});
There is an id:1
nothing prints to console but the following error:
Uncaught TypeError: e.unique is not a function
Is there a way to grab this from carrierwave thorugh sql or even ruby within the javascript?
You can change your code Item.pluck(:id, :image).to_h.to_json.html_safe to Item.all.map{|item| [item.id, item.image_url]}.to_h.to_json.html_safe . But as others said in comments better to get items through Ajax request not just store them in html.

Rails - Javascript - Add param to params before form submit

I have a form for multiple pupils, with checkboxes next to each pupil to collect their IDs. I'm trying to have two buttons that each lead to different forms, and I've tried submitted params with the button click but to no avail:
simple_form_for - multiple submit buttons with different params
Is there any way to write some JS that adds a parameter to the params before submitting the form? My form is as follows:
<%= simple_form_for :pupils, url: edit_multiple_school_group_pupils_path(school, group) do |f| %>
...
...
<%= f.button :submit, 'Change Levels', name: 'editing', value: 'levels' %>
<%= f.button :submit, 'Move to A Class', name: 'editing', value: 'classes' %>
<% end %>
Each of the buttons have their own ID in the raw HTML so I'm hoping theres a way to pluck that before the form gets submitted and add it to the params.
I'm extremely green with JS so wouldn't even know where to start. Thanks in advance.
I'm not 100% sure what is needed for the rails portion, but it sounds like you want to serialize your form.
This is fairly easily accomplished. Here is an example of what a serialize to JSON function might look like
function toJSONString( form ) {
var obj = {};
var elements = form.querySelectorAll( selectors );
for( var i = 0; i < elements.length; ++i ) {
var element = elements[i];
var name = element.name;
var value = element.value;
if( name ) {
obj[ name ] = value;
}
}
return JSON.stringify( obj );
}
The selectors can be pretty much whatever you want within your form. Inputs, textareas, buttons etc.
Hope this helps!

Rails: Why can't my object created by ajax be used to trigger javascript?

I'm trying to implement an ajax voting system for a model "Things", where if a user votes on Thing then a new Thing appears in the old one's place, which he can then vote on, and so on. This takes place on the Thing view itself.
I'm pretty sure this exact code was working a week ago, but now it mysteriously broke. Now, the Thing is replaced upon the first vote, but after that, voting no longer brings forth a new Thing:
views/things/show.html.erb
<div id="randajax">
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), upvoterandom_thing_path(#rand.id), remote: true, method: :get %>
<script type="text/javascript">
function reload_script() {
$(".rand_up_vote").click(function () {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
$('#randajax').html(data);
reload_script();
});
});
}
reload_script();
</script>
</div>
controllers/things_controller.rb
def upvoterandom
#thing = Thing.find(params[:id])
UpVote.create!
#rand = Thing.all.first
render text: "<a data-method=\'get\' data-remote=\'true\' href=\'" + upvoterandom_thing_path(#rand.id) + "\'><img alt=\'Upvote\' class=\'rand_upp_vote\' src=\'/assets/UpArrowGray.jpg\' /></a>".html_safe
end
Apparently the issue is that an item created with ajax can't execute javascript. The web console shows that the upvoterandom_thing_path is getting executed, but nothing happens to the randajax div. I tried giving the Thing created from the original javascript a differenc class with different javascript and that didn't work either, although a seperate item ("THIS_WORKS") with the same class executed the same javascript normally:
views/things/show.html.erb
<%= link_to "THIS_WORKS", "#", class: "TEST_TEST", remote: true %>
<div id="randajax">
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), upvoterandom_thing_path(#rand.id), remote: true, method: :get %>
<script type="text/javascript">
function reload_script() {
$(".rand_up_vote").click(function () {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
$('#randajax').html(data);
reload_script();
});
});
}
reload_script();
</script>
<script type="text/javascript">
$(".TEST_TEST").click(function () {
$('#randajax').html("TEST");
});
</script>
</div>
controllers/things_controller.rb
def upvoterandom
#thing = Thing.find(params[:id])
UpVote.create!
#rand = Thing.all.first
render text: "<a data-method=\'get\' data-remote=\'true\' href=\'" + upvoterandom_thing_path(#rand.id) + "\'><img alt=\'Upvote\' class=\'rand_up_vote\' src=\'/assets/UpArrowGray.jpg\' /></a>".html_safe
end
Can anyone explain why this is happening or how I can fix this?
When you set it up, you do this in your javascript:
$(".rand_up_vote").click(function () {
...
This sets up the click event on the elements. When one of the elements is replaced, or a new one is added, it hasn't had this event added to it, so it won't work like the others.
To fix this, you need to add this same event to the new element, OR remove the event from all elements and then add it to all elements (if you don't remove it first you risk firing the same event twice on a click or whatever).
EDIT with a proposed solution.
The simplest way is to add an onclick attribute to your elements, to run the reload_script() function. Change this so that it doesn't add an onclick to the events. I was about to start editing your code and i noticed that the reload_script function calls itself at the end of the anonymous function you're adding as the onclick event: this means that when you click on a .rand_up_vote element, it will do the AJAX get, replace the html, and then add another onclick to all the elements. This is definitely not right - was this an earlier attempt to fix this problem?
You probably just need something like this:
<div id="randajax">
<%= link_to image_tag("UpArrowGray.jpg", class: "rand_up_vote"), upvoterandom_thing_path(#rand.id), remote: true, method: :get %>
<script type="text/javascript">
function reload_script() {
$.get( "<%= upvoterandom_thing_path(:id => #rand.id) %>", function( data ) {
$('#randajax').html(data);
});
}
</script>
</div>
now edit the html so that each .rand_up_vote element has an onclick="reload_script()" attribute.

Preview form button in another view

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

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