I need to write some jquery which will read what the current value in a drop down list is and then hides a particular link on the page.
The dropdown list is a locale selector. So when I select "english" I want the link to be hidden but when select French the link has to remain.
Can you show how i can do this? I want learn this. Thanks
How about this:
function handleLang() {
if ($('#select').val() == 'en') {
$('#link').hide();
} else {
$('#link').show();
}
}
$(function() {
// hide/show on load
handleLang();
// hide/show when the language is changed (useful if the page doesn't reload)
$('#select').change(handleLang);
});
Based on the first answer provided for this question and more hints provided by the author of the first answer in the comments, here is the final (and compact) full version of the code that worked for me (I also removed and styling since was no longer required). This is a main page provided in the index.html.erb for this test application.
<h2 id='main_header'>Showing/hiding link based on dropdown selection</h2>
<table>
<thead>
<th>Action</th>
<th>Skip assessment</th>
<th>Reason for skipping</th>
</thead>
<tbody>
<tr>
<td>
<%= link_to 'Start asseement', url_for(controller: :home, action: :start_assessment), id: 'start_assessment' %>
</td>
<td>
<%= select_tag "skip_option", options_for_select([ "Yes", "No" ], "No"), id: "skip_option", onchange: "reason_picker()" %>
</td>
<td>
<%= text_field_tag "reason_for_skipping", nil, size: 50, placeholder: 'Enter reason here...' %>
</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
$(document).ready (
window.reason_picker = function () {
var selected = document.getElementById("skip_option").selectedIndex;
if (selected == 0) {
$("#reason_for_skipping").show();
$("#start_assessment").hide();
}
else {
$("#reason_for_skipping").hide();
$("#start_assessment").show();
}
}
);
</script>
The start assessment page is very basic, just a title and back link to the main page contained in the start_assessment.html.erb file:
<h1>Assessment</h1>
<%= link_to 'Back', :back %>
I this is of any help, here are the controller home_controller.rb file:
class HomeController < ApplicationController
def index
end
def start_assessment
end
end
And the route route.rb file is:
Rails.application.routes.draw do
root controller: 'home', action: :index
get 'start_assessment' => 'home#start_assessment'
end
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 trying to display all the topics that are being discussed on my application, so I created a dropdown menu (btw if there is a better way of doing this please feel free to share it):
<div class="form-group">
<label for="topic_category">Category</label>
<select id="topic_category" name="topic[category]" class="form-control">
<option>Art</option>
<option>Business</option>
<option>Books</option>
<option>Charity</option>
<option>Coding</option>
<option>Cooking</option>
<option>Dance</option>
<option>Design</option>
<option>DIY</option>
<option>Engineering</option>
<option>Fashion</option> etc...
</select>
</div>
What I'm trying to do is to create links to each single category and also display how many topics are active through something like
----- Edit 1 -----
what I'm trying to achieve is something like this:
<div class="row">
<div class="col-md-6" style ="padding-top: 10px; border-right: 1px solid #ccc;">
<h4 style="text-align: center;">Topics</h4>
<link_to project.category(Art)> (project.category(art).count)
</div>
I know that is wrong but is the closest I get to explaining what I'm trying to achieve
---- Edit 2 -----
So I'm still trying to get it right, this is probably because I'm a newbie. So following your answers I implemented the code which looks something like this.
static_pages controller.
def home
if logged_in?
#user = current_user
#topics_count = Topic.group(:category).count
end
end
def categoryselection
category = params[:category]
topics = Topic.where(category: category)
render json: { success: true, Topics: topics }
end
def help
end
def about
end
def contact
end
end
home view
.......
<% if logged_in? %>
<div class="row">
<%= render 'shared/sidebar_right' %>
<div class="col-md-8" style = "align-content: right">
<%= render 'shared/feed' %>
</div>
</div>
<% else %>
.....
Sidebar_right view
......
<div id='topics'>
<% #topics_count.each do |topic, count| %>
<a class ='project-link' href='topic_path?category=<%= topic %>'> <%= topic %> (<%= count %>)</a>
<% end %>
......
<script type>
$('#topics').on('change', '.topic-link' function (e) {
e.preventDefault();
var category = $(e.currentTarget).val();
var queryUrl = $(e).href + '?category=' + category;
$.get(queryUrl, function(resp) {
if (resp.success) {redirect_to topic_path
// select the div or whatever node on the DOM you are displaying the result, and change it.
}
});
});
</script>
Topics Controller
class TopicsController < ApplicationController
.....
def index
end
def show
#user = current_user
#topic = Topic.find(params[:id])
end
.....
The error I'm getting is no routes match [GET] topic_path, and I've checked on my routes and it does exit it actually refers to "show", is this happening because the page I'm using is home rather than the topics page?
Thanks!
Based on your new edit
In the controller:
def index
#topics_count = Topic.group(:category).count
# this will give you something like this { 'Art' => 10, 'Business' => 15' }
end
on the html page:
<div id='topics'>
<% #topics_count.each do |topic, count| %>
<a class='topic-link' href='topic_show_url?category=<%= topic %>'> <%= topic %> (<%= count %>)</a>
<% end %>
</div>
You don't need to (and shouldn't) load all the topics because you are just showing the count, and at large scale, loading the entire table will likely crash your site.
This will take care of your second request, showing the topic the user picks when the link is clicked.
on the page, send ajax request when user select one of those options.
$('#topics').on('click', '.topic-link', function (e) {
e.preventDefault();
var category = $(e.currentTarget).val();
var queryUrl = $(e).href + '?category=' + category;
$.get(queryUrl, function(resp) {
if (resp.success) {
// select the div or whatever node on the DOM you are displaying the result, and change it.
}
});
});
in the controller
def you_define_this_method
category = params[:category]
topics = Topic.where(category: category)
render json: { success: true, topics: topics }
end
You can add a link inside your <option> tag... ie.
<option>Art</option>
I have a form with nested attributes, where you can dynamically add and remove attributes (the form lets you click "add hobby" and "remove hobby" links...a user has hobbies, and when entering his profile he can add one, two, five, or fifty hobbies).
With the help of the nested form gem this works completely fine. However, I also provide the ability to UPDATE a user's profile.
When doing this, a user can click the dynamic "remove" link to take off a hobby. However, this doesn't delete the "hobby" from the database, like I want it to. So I'm trying to write Jquery or Javascript or something that deletes the object from the database, if it exists.
This is what the code looks like:
...
...
<%= f.fields_for :hobbys, :wrapper => false do |hobby| %>
<tr class="fields">
<td> <%= user.text_field :hobby %> </td>
<td> <%= user.link_to_remove "Remove" %> </td>
</tr>
<% end %>
</table>
<p><%= f.link_to_add "Add hobby", :hobbys, :data => { :target => "#hobbys" } %></p>
<script>
$(document).on('nested:fieldRemoved', function(event){
var field = event.field;
/* ??? Delete field somehow ??? */
})
</script>
Is there any way to do this? I really don't know how to go about it....it doesn't seem like Jquery can delete off a database...
UPDATE
here's my best attempt so far...
...
...
<%= f.fields_for :hobbys, :wrapper => false do |hobby| %>
<tr class="fields">
<td> <%= user.text_field :hobby %> </td>
<td> <%= user.link_to_remove "Remove" %> </td>
</tr>
<% end %>
</table>
<p><%= f.link_to_add "Add hobby", :hobbys, :data => { :target => "#hobbys" } %></p>
<script>
$(document).on('nested:fieldRemoved', function(event){
$.get("delete", { id: 2 })
alert( "Deleted: ");
})
</script>
I'm just trying to get this damn thing to work, by hardcoding an id as the argument (since I can't yet easily extract it). But it keeps using the string "delete" as the id of the user.....huh??
Here's the log output:
Started GET "/users/delete?id=2" for 127.0.0.1 at 2016-10-05 08:35:15 -0400
Processing by UsersController#show as */*
Parameters: {"id"=>"delete"}
Current user: anonymous
Completed 404 Not Found in 19.5ms
ActiveRecord::RecordNotFound (Couldn't find User with id=delete):
You could use Jquery to call a function in Ruby to do it for you:
Javascript:
$.get( "delete", { id: id_to_delete } )
.done(function( deleted ) {
alert( "Deleted: " + deleted.id );
});
Route (route.rb):
get 'delete', to: 'application_controller#delete'
Application Controller (application_controller.rb):
def delete
id = params[:id].to_i
to_delete = Hobby.find(id).destroy
render json: {id: id}
end
Add a listener on click of the remove button for each activity and make an ajax request to your backend api which handles it. It will look something like below:
$('.activities').each(function(activity) {
$(activity).click(function(event) {
$.ajax
url: 'activity/:id',
method: delete,
success: function(data) { REMOVE ELEMENT IN HERE }
error: alert('this didnt work');
})
})
I have this view:
<!-- Loads custom Stylesheet -->
<%= stylesheet_link_tag 'simulation' %>
<!-- Loads polling calls to update -->
<script type="text/javascript">
<%= render 'show.js.erb' %>
</script>
<!-- Render simulation -->
<%= render 'simulation' %>
<%= link_to 'Back', simulations_path %>
It contains these two partials:
_show.js.erb:
callUpdate = function(id) {
if (id) {
console.log("tic")
$.ajax({
type: "PUT",
url: "/simulations/" + id
});
} else {
console.log("Update error, no id passed.")
}
$('#sim_div').html("<%= j (render #simulation) %>");
setTimeout( function() {
callUpdate(id)
}, 5000);
};
setTimeout( function() {
callUpdate("<%= #simulation.id %>")
}, 5000);
_simulation.html.erb:
<div id="sim_div">
<h1><%= #simulation.identifier %></h1>
<h4 class="offset-col-sm-1">Dimensions: <%= #simulation.x_size %>x<%= #simulation.y_size %></h4>
<h4 class="offset-col-sm-1">Verdict: <%= #simulation.verdict %></h4>
<!-- REMOVE -->
<h1> <%= #simulation.dirty? %></h1>
<table class="table table-bordered">
<thead>
<tr>
</tr>
</thead>
<tbody>
<% #simulation.state.each_with_index do |row, y_index| %>
<tr>
<% row.each_with_index do |current, x_index| %>
<td class="text-center <%= 'dirty' if #simulation.dirty_points.include?([x_index,y_index]) %>"><%= current %></td>
<% end%>
</tr>
<% end %>
</tbody>
</table>
<br>
</div>
The javascript is calling my controllers update function, which sets dirty records on the update function.
simulation_controller#show:
def update
#simulation = Simulation.find(params[:id])
#simulation.next # <= THIS SETS DIRTY RECORDS ON THE OBJECT
#simulation.save
respond_to do |format|
format.js
format.html { redirect_to simulations_url }
end
end
My javascript code never gets the new updated record from after the update call, and I want it so that when their are no longer update calls to stop calling update and stop the polling. However it only can ever see the initial record which is not dirty. Only the _simulation partial seems to receive the new record (Even though it's getting re rendered by the javascript code so I'm not sure why the javascript can't see the updated record.)
How can I access properties of the updated record, not just the original in the javascript code? Thanks!
Your callUpdate javascript function likely is in fact being executed every 5 seconds, but it is rendering the same #simulation (the initial one) over and over without change. Your javascript partial is only being rendered once (initial view), and it is making endless ajax requests and endlessly replacing the html of some element with the same contents over and over.
Instead you should be updating the inner html of some element on every response of these ajax calls.
Take this line from your initial view:
$('#sim_div').html("<%= j (render #simulation) %>");
and move it to the response template of your update action (likely to be: update.js.erb)
I'm running Rails 3.2.11. I'm working on a simple wiki project as I learn Rails and Javascript. What I want to do is store a two-column table in my database whose contents and number of rows can be edited by users, and use jQuery to add forms for a new table row on a button click. The table is stored as a hash containing hashes for each row's columns. i.e. {"row1" => {"head" => "first column/header content", "tail" => "second column/data content"}, "row2" => {"head" => "first column/header content", "tail" => "second column/data content"}} The part of my _form.html.erb for editing the table looks like this:
<div id="node_table_row_0">
<%= f.fields_for :table do |table_rows| %>
<%= table_rows.fields_for :row do |table_cols| %>
<%= table_cols.text_field :head, :id => 'node_table_row_head_0' %>
<%= table_cols.text_field :tail, :id => 'node_table_row_tail_0' %>
<% end %>
<% end %>
<button id="add_table_row" type="button" class="btn btn-small">Add Row</button>
</div>
I'm displaying the table on my page like so:
<table class="table">
<% #node.table.each do |row| %>
<tr>
<th><%= row[1]['head'] %></th> <td><%= row[1]['tail'] %></td>
</tr>
<% end %>
</table>
And my node.js file contains the following:
$(document).ready(function(){
$('#header').append('Script loaded')
var newIndex = 0
$('#add_table_row').click(function(){
$('.sidebar_img').append('onclick event activated')
var prevIndex = newIndex
var prevRow = $('#node_table_row')
newIndex = newIndex + 1
var newRow = prevRow.clone(true).attr('id', 'node_table_row_'+newIndex)
newRow.find('#node_table_row_head').attr({ id: 'node_table_row_head_'+newIndex, name: 'node[table][row'+newIndex+'][head]'})
newRow.find('#node_table_row_tail').attr({ id: 'node_table_row_tail_'+newIndex, name: 'node[table][row'+newIndex+'][tail]'})
newRow.after(prevRow)
});
});
When I click the "add row" button, I get my confirmation that the onclick event has been recognized, but the forms are not appended. Am I approaching this entirely the wrong way? It seems like there would be a simpler way to go about this.
Have you tried using the jQuery insertAfter() method? use jQuery to select the table then use .children().insertAfter(newRow);