Change the content of 3 divs using javascript and ajax - javascript

i'm using rails 4 and javascript and here's my question:
i need to change the values of 3 divs using a button. The values of the divs are generated by a ruby function that came from the controller of that page.
Code:
<% $number= randNumbers %>
<div id="1"><%= $number[0] %></div>
<div id="2"><%= $number[1] %></div>
<div id="3"><%= $number[2] %></div>
<button id="btn1" >Click me!</button>
Here's the ruby method
def randNumbers
n1=rand(1..10)
n2=rand(1..10)
n3=rand(1..10)
return array=[n1,n2,n3]
end
So i need to recall the ruby function to generate new random numbers everytime i click on the button "btn1" without reloading the page.
I know that i have to use ajax or jquery, but i do not really know how to use it with ruby methods.
Thanks for helping :D

You can try the following:
HTML code in View:
Remove the code <% $number= randNumbers %>
Change the code to:
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
<button id="btn1" >Click me!</button>
Javascript Code in View:
$( document ).ready(function() {
call_ajax();
});
$("#btn1").click(function(){
call_ajax();
});
function call_ajax(){
$.ajax({ type:'POST', url:'/controller/get_random', data: {},
success:function(data)
{
$("#1").text(data.arr[0])
$("#2").text(data.arr[1])
$("#3").text(data.arr[2])
},
error:function()
{
// Handle error if Ajax fails
}
});
}
Method in Controller:
def get_random
n1=rand(1..10)
n2=rand(1..10)
n3=rand(1..10)
array=[n1,n2,n3]
render json: {arr: array}
end
Also add routes in routes.rb: post '/controller/get_random'

Related

Add a css class using to "this" item in a forEach within EJS/node.js

I've been trying this for hours but I am stumped.
I have a kind of "shopping list" node.js app where you can tick off items as bought. I want the bought items to be styled green or smth. It is passing a mongoose obj to the client side along a route.
Server side:
router.get("/:id", function(req, res){
//find the list with provided ID
List.findById(req.params.id).populate("listItems").exec(function(err, foundList){
if(err){
console.log(err);
} else {
//render show template with that list
res.render("lists/show", {list: foundList});
The foundList obj basically has a structure of (not valid code, just so u can get an idea):
List {
name: String,
listItems: [{
text: String,
bought: Boolean
}]
On the client side I am using a forEach in ejs to loop through the listItems and display a html element for each item:
<% list.listItems.forEach(function(listItem){ %>
<div class="card">
<div class="card list">
..listItem name here
</div>
</div>
<% }) %>
I want to basically make it so that when an element is checked off and listItem.bought == true, the card list element is green, and when lisItem.bought == false, it's just white.
I've got it working with following code, however if one occurrence of the forEach is bought = true, all .card elements turn green. I want it so that only the element in question is effected.
<% list.listItems.forEach(function(listItem){ %>
<% if(listItem.bought === true){ %>
<script>
$(document).ready(function(){
(".card").css("background-color","green");
});
</script>
<% } else { %>
<script>
$(document).ready(function(){
(".card").css("background-color","white");
});
</script>
<% } %>
<div class="card">
<div class="card list">
....
Question: How do I target 1 occurrence of a forEach from server side data in ejs, and add a class/style to it. E.g. if there is 2 items on the list, 1 is bought and one not, one should be green and one white. Currently they both go green.
Thanks!
I don't think you need jQuery for this. You can just add the background color like this:
<% list.listItems.forEach(function (listItem) { %>
<div class="card" style="background-color: <%= listItem.bought ? 'green' : 'white' %>">
<div class="card list">
...
</div>
</div>
<% }); %>
If you want to use jQuery you probably need do add ids to the cards and use them to change the backgrounds.

Passing CSS Values Through JavaScript to Partial View

I am working with an MVC Entity Framework Webapp. I have a view that displays other partial views that are updated every 30 seconds. The issue is the dynamic progress bar I am using does not fill up at all and I have tried everything I know. The problem I think is the css that gets passed to the partial view ("width", current_progress + "%"). Here is a pic and the bar is supposed to be over half full...
Controller methods:
public ActionResult Dashboard()
{
ViewBag.SumofDon = db.tblDonors.Sum(s => s.DonationAmount);
return View(db.tblDonors.ToList());
}
public ActionResult Progress()
{
return PartialView("_Progress", db.tblDonors.ToList());
}
Dashboard.cshtml:
#model IEnumerable<bssp.Models.tblDonor>
#{
ViewBag.Title = "Dashboard";
}
#section Scripts{
<script>
function loadProgressPV() {
$.ajax({
url: "#Url.Action("Progress")",
type: 'GET', // <-- make a async request by GET
dataType: 'html', // <-- to expect an html response
success: function(result) {
$('#progress').html(result);
}
});
}
$(function() {
loadProgressPV(); // first time
// re-call the functions each 10 seconds
window.setInterval("loadProgressPV()", 10000);
});
</script>
<script>
$(function () {
var SumofDon = #ViewBag.SumofDon;
var current_progress = (SumofDon / 20000) * 100; // 20000 is the goal that can be changed
$("#dynamic")
.css("width", current_progress + "%") //This causes the problem?
});
</script>
}
<div class="container-fluid">
<div class="row" id="progress">
#Html.Partial("_Progress")
</div>
</div>
Partial view:
#model IEnumerable<bssp.Models.tblDonor>
<div class="row">
<br /><br /><br />
<div class="col-md-12">
<div class="well bs-component">
<h4>#String.Format("{0:C}", #ViewBag.SumofDon) out of $20,000<br /></h4>
<div class="progress progress-striped active">
<div class="progress-bar" id="dynamic" style="width: 0%"></div> #*The width is what gets updated because it found the id of dynamic*#
</div>
</div>
</div>
</div>
Any help would be awesome and thanks in advance!
I think your issue is that you pull in the html from the partial with a style="width: 0%" but then jQuery that adjusts the css, $("#dynamic").css("width", current_progress + "%"), is only run on page load, not after the partial reloads. You have two options to fix this,
Run the jQuery function after the razor loads in from the partial, in the success method of the ajax.
Since you are using razor to create the partial, why not just do the calculation right there? That way the partial comes in already set up with the width set. This is the easier and faster option of the two.

CKEditor and iframes

I'm experiencing stuff with CKEditor. I read the doc, but I can't find a way to do what I'm trying to do.(I'm in Java, in a jsp page)
I have a path
String path = request.getContextPath();
And I need to call this path
<%=path%>/docX/Controller
What I have is very basic:
<div id="editor">
<h1>Hello world!</h1>
</div>
<script>
initSample();
</script>
That works very well, but I want to add content when the page load.
I tried to manually add an iframe in the code with my path, such as
<iframe src="<%=path%>/docX/Controller"></iframe>
But it shows something like this : http://docs.cksource.com/images/9/93/CKEditor_iframe_example1.png
Which is normal if I understood well. If I click on "preview" I'll see what I'm suppose to see. But I want to see it at first and I want to be able to edit it.
The file it will return will be a .html file. So I must get the 'innerHTML' from that file and put it somehow in the editor. It doesn't have to be an iframe if there's an easier way to get the data.
Now I'm trying to get the html from the iframe and put it into a <p>. What I got so far looks like this :
<%
String path = request.getContextPath();
%>
<div class="main">
<div class="grid-container">
<div class="grid-width-100">
<div id="editor">
<h1>Hello world!</h1>
<iframe id="frame" src="<%=path%>/docX/Controller"></iframe>
</div>
</div>
</div>
</div>
<script>
initSample();
var iframe = document.getElementById("frame");
var iframe_contents = iframe.contentDocument.body.innerHTML;
alert(iframe_contents);
</script>
My alert() shows an empty string, but if I click on preview, I can see the text.
Any kind of help is always appreciated.
EDIT: My html file only have "test" inside it. Nothing like <html> <head> and stuff. I tried
$(document).ready(function () {
var test = $("#frame").contents().find("html").html();
alert(test);
})
But it returns <html></html><body></body>
EDIT 2:
I changed it for
$(document).ready(function () {
var mydocument = document.getElementById("frame").contentDocument;
var serializer = new XMLSerializer();
var content = serializer.serializeToString(mydocument);
alert(content);
})
My result is : <html xmlns="http://www.w3.org/1999/xhtml"><head><style type="text/css"></style></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"></pre></body></html>
If I open my .html file, all I see is test
I'll answer my question so if someone has the same issue, he could try this solution.
So I removed the <iframe> from my CKEditor and I added an empty <p>. I simply took the returned data of my URL and put it in that <p>.
<%
String path = request.getContextPath();
%>
<div class="main">
<div class="grid-container">
<div class="grid-width-100">
<div id="editor">
<p id="content"></p>
</div>
</div>
</div>
</div>
<script>
initSample();
$(document).ready(function () {
$.get('<%=path%>/docX/Controller').then(function(responseData) {
$("#content").append(responseData);
});
})
</script>
In my case, responseData returns "test". It will also take properties, if your text is bold for exemple.
This will work in IE. But to make it work in chrome, in my case, it will return object XMLDocument. I had to do something like this:
$.ajax({
url: '<%=path%>/docX/Controller',
type: 'GET',
dataType: 'text',
success: function(data){
alert(data);
}
});

Ruby Rails - optional form input shown conditional on checkbox

I am working on a dynamic form input display where if the users clicks something to show "advanced options" in the form, the input vectors will be displayed, but otherwise (the default) they will not be shown. I have the following pieces in my form partial:
UPDATED 1x:
<div class="form-inputs">
<%= f.input :message, label: 'Write message'%>
</div>
<div class="form-inputs">
<%= f.check_box :advanced, {}, :id => "advancedbox" %>
</div>
<div class="form-inputs" id="advancedopts" style="display:none;">
<%= f.input :startdatetime, label: 'Specify', :as => :datetime_picker %>
<%= f.input :expirationdatetime, label: 'Specify', :as => :datetime_picker %>
</div>
And the JS in the head of the form partial:
UPDATED 1x:
<head><script type="text/javascript">
var checkbox = document.getElementById('advancedbox');
checkbox.onchange = function() {
if (checkbox.checked) {
document.getElementById("advancedopts").style.display = "block;";
} else {
document.getElementById("advancedopts").style.display = "none;";
}
}
</script></head>
I took the inspiration for this from the following post: show rest of a form if a checkbox is ckecked in ruby on rails
But I cannot get it to work: the checkbox shows, but clicking it on or off does not show my advanced form inputs. Can anyone help me debug?
Thanks!!
Your problem is that there is no event being listened for. In the example you linked, checkbox.onchange is an event that triggers a function (action) that displays the div. As yours is all namespaced within a function with no event to fire it, nothing happens as it is not evaluated when the state of your checkbox changes.
So if you move the line
var checkbox = document.getElementById('advancedbox');
outside your show function and then key the onchange event to that variable as in the example you linked, it should work.
EDIT: jQuery solution...
$(document).ready(function(){
$("#advancedbox").change(function(){
if( $(this).is(':checked') ){
$('#advancedopts').show(); // you could instead animate using .fadeIn() or .slideDown() if that was preferable
} else {
$('#advancedopts').hide(); // ditto above, using .fadeOut(), .slideUp() etc.
}
});
});
Your problem is here:
<div class="form-inputs" name="advancedopts" style="display:none;">
Changing the name attribute to id should do the trick:
<div class="form-inputs" id="advancedopts" style="display:none;">
Because I do not need to save the user selection, I use the following which works well for my purposes (inspired by changing DIV visibility with JavaScript):
in form partial:
<input type="button" value="Show advanced" onClick="show()">
<div class="form-inputs" id="advancedopts">
... </div>
in application.js:
function show(){
document.getElementById("advancedopts").style.visibility= 'visible' ;
}
in scaffolds.css:
#advancedopts{
visibility:hidden;
}
And works sufficiently for me without the use of a listener. Just in case anyone has a similar simple need and starts off on a track-more-complicated-than-necessary like me.

Rails 3.2.1 - Getting Javascript variables/data to Rails Controller

I'm working on a Rails 3.2.1 app and would like to pass some Javascript variables to the Rails controller. Here are some more details:
my js fiddle: http://jsfiddle.net/PauWy/475/
and what fiddle doesn't show, a jQuery UI sortable: $("#menu-items").sortable();
I would like to work with the following information in my Rails 'execute' method in the ThingsController for each item:
Whether or not the item is visible (I think I should do something like $('#item_1).is(':visible')
Which one of the following is displayed - "Add", "Reduce", or neither
the id of the item
the order/position of the item in the sortable list
My take would be to send an AJAX with the above data to the 'things/execute' action, and somehow route it and respond_to the incoming AJAX.
I know vaguely how some bits and pieces should look like, but I'm having a hard time putting everything together. Would really appreciate some help!
So, you need to parse you HTML to get information from it
Example
HTML :
<div id="my_content">
<div id="div1" class="reduce" style="visibility: visible;"></div>
<div id="div2" class="add" style="visibility: visible;"></div>
<div id="div3" class="add" style="visibility: visible;"></div>
<div id="div4" class="reduce" style="visibility: visible;"></div>
<div id="div5" class="reduce" style="visibility: hidden;"></div>
<div id="div6" class="add" style="visibility: hidden;"></div>
<div id="div7" class="add" style="visibility: hidden;"></div>
<div id="div8" class="reduce" style="visibility: hidden;"></div>
</div>
Then you can parse it to JSON (using jQuery) :
Javascript :
var parsed_data = {}
var order = 1
$('#my_content > div').each(function() {
// Some if else
var element_class = $(this).hasClass('reduce') ? 'reduce' :
( $(this).hasClass('add') ? 'add' : 'unkown')
parsed_data['data'+ order] = {
element_id: $(this).attr('id'),
display_class: element_class,
visibility: $(this).css('visibility'),
}
order++
})
Then you call your controller with AJAX :
$.ajax({
url: "<CONTROLLER_URL>",
type: "POST",
dataType: 'json', // data returned, not data sent
data: parsed_data
}).done(function(data) {
console.log('Done')
})
Ruby Controller :
def your_controller_function
params.each do |key, div|
print "DIV N°#{key}"
print " Id #{element_id}"
print " Displayed class #{display_class}"
print " Visibility #{visibility}"
end
end
I hope it's not too messy and it helped.

Categories