JS and Rails site wide announcements - javascript

Tried doing http://davidwparker.com/2008/09/17/site-wide-announcements-in-rails-using-jquery-jgrowl/
Am really bad with JS. Think I am messing up on the last part where it says "This code goes in your application.js file (somewhere in $(function){ //here })"
Am I not suppose to do a link_to_function and create a function with this code that references that link?
Really lost on this one.
Updated -
application.js looks like
$(document).ready(function() {
$.jGrowl.defaults.closer = true;
$("#announcements_box").css("display", "none");
$("#announcements_box .announcement").each(function(){
$jQuery.jGrowl(this.textContent,{ sticky:true, close:function(e,m,o){hide_announcements();} });
});
});
function hide_announcements(){
$.get(
'/hide_announcements'
);
$("#announcements_box").fadeOut();
return false;
}
And my application.html.erb has
<% unless current_announcements.empty? %>
<div id="announcements_box">
<% for announcement in current_announcements %>
<div id="announcement_<%= announcement.id.to_s %>" class="jGrowl">
<%= announcement.message %>
<%= link_to "Hide Annoucements", hide_announcements_path, :id => 'hideAnn'%>
</div>
<% end %>
</div>
<% end %>

I'm not sure what $(function){ //here } notation means, that should give you error in the browser, but I think he just wants to execute code after page is loaded:
$(document).ready(function() {
// here
}

And the culprit was I only entered a div ID when I needed to have a div ID and class.

Related

Rails 5, simple javascript with form submit

I am hoping someone can help me here. Been at this for a few hours, but can't seem to figure out why my Javascript is not working on my simple form. I'm simply trying to display comments using the ajax call. I have gem 'jquery-rails', and required jquery, and jquery_ujs in my application.js file. Here's the code I have so far:
I have a Joy model that has_many comments.
<% #joys.each do |joy| %>
<ul id="comments-<%= joy.id %>">
<% joy.comments.where(void:'f').each do |comment| %>
<li><%= comment.body %></li>
<% end %>
</ul>
<%= form_with(model: [ joy.user, joy, joy.comments.build ], data:{ "js-comments-#{joy.id}" => true}) do |f| %>
<%= f.text_area :body, :class=>'form-control', :required=>'true' %>
<%= f.submit "Post Comment" %>
<% end %>
<script>
$(document).ready(function() {
$('[data-js-comments-<%= joy.id %>]').on("ajax:success", function(event, data, status, xhr){
$('#comments-<%=joy.id%>').append(xhr.responseText);
});
});
</script>
<% end %>
In my Comment controller, in my 'create' action, I have:
if #comment.save
render partial: "comment", locals: {comment: #comment}
end
In my Comment views, I created a partial, called _comment.html.erb:
<li>
<%= comment.body %>
</li>
So, now when I enter a comment, and click 'Post Comment', it correctly saves my Comment, but it does not ajax load the comment into list. Furthermore, the form does not refresh either. The text remains in the text box. It is not only until after I refresh the page when my comment shows up in the list. Anyone with any thoughts on what I'm missing or doing wrong???
Your help is greatly appreciated in advance.
form_with it's a remote form, you dont need that block <script>..</script>.
Just use create.js.erb then use jquery to append new comment.
And if you want to check if your message was created successfully, you can add a #status value in your controller.
//comments_controller.rb
def create
...
if #comment.save
#status = "success"
else
#status = "failed"
end
...
end
//create.js.erb - for example
$("#yourCommentList").append('<%= j( render partial: 'comments/comment', locals: #comment ) %>');
<% if #status == "success" %>
$("body").append(...your notification...)
...
<% else %>
...
<% end %>

Render simple form partial in Rails/Javascript

I want to render my form partial in javascript erb file. When I place it in there it gives me a no method error. Any ideas?
script.js.erb
$(document).ready(function() {
$(".enquiry-button").click(function(e) {
e.preventDefault();
e.stopPropagation();
if ($(this).parents('.cell').find('form').length == 0) {
$(this).closest('.cell').append(
"<div class='enquiry-form'>" +
"<%= escape_javascript( render '/static/form' ) %>" +
"</div>");
$(this).closest('.cell').find(".enquiry-form:last").slideDown("slow");
} else {
$(this).closest('.cell').find(".enquiry-form:last").slideToggle("fast");
}
});
});
_form.html.erb
<%= simple_form_for #user do |f| %>
<%= f.error_messages %>
<%= f.input :email %>
<%= f.button :submit %>
<% end %>
error
NoMethodError in Static#home
Showing /Users/colton/kitchen_ninja/kitchen_ninja/app/views/layouts/application.html.erb where line #6 raised:
undefined method `render' for #<#<Class:0x007f90cc875c80>:0x007f90cd2017e0>
(in /Users/colton/kitchen_ninja/kitchen_ninja/app/assets/javascripts/script.js.erb)
Extracted source (around line #6):
You are mixing two separate things together. Your render needs to run on the server. JavaScript's job is just to make an AJAX request and get a resource.
So, supposed you were to to this:
$.ajax(url: "/test").done(function(html) {
$("#results").append(html);
});
AJAX's only role is to grab a remote resource and parse the results.
In Ruby, you can use render to emit the HTML:
<%= escape_javascript( render '/static/form' ) %>
Just make sure you point the AJAX request to the right resource so Ruby can do the rest of the magic.
Since you are pre-processing the script with .erb, you could use Ruby's string interpolation to return the partial as a string literal in the JavaScript file.
html = "<div class='enquiry-form'>" +
"#{j render partial: 'static/form'}}" +
"</div>"
$(this).closest('.cell').append( html );

Yet another endless page dilemma

I am trying to implement an endless page setup for my page. I've been trying a lot of different methods for two days now but can't seem to get it to work. I liked the proposed setup from this blogpost but I can't seem to get it to work: http://pedromtavares.wordpress.com/2011/05/08/endless-page-scrolling-with-rails-3-and-jquery/
I also tried Ryan Bates screencast but didn't manage to implement it...
I tried the following:
Installed plugin
rails plugin install git://github.com/pedromtavares/endless_scroll_example.git
Modified my controller home:
def index
last = params[:last].blank? ? Time.now + 1.second : Time.parse(params[:last])
#feeds = Feed.input(last)
end
Modified my "Feed-model" with the new method 'input':
def self.input(last)
self.where("created_at < ? ", last).order('created_at desc').limit(5)
end
Modified my index
<% content_for :scripts do %>
<%= javascript_include_tag 'endless' %>
<% end %>
<%unless #feeds.blank?%>
<ul class='list' last="<%=#feeds.to_a.last.created_at%>">
<%= render :partial => 'feeds', :collection => #feeds%>
<div id='infinite-scroll'></div>
</ul>
<%end%>
My partial _feeds.html.erb looks like this (just filling out text :):
<%=feeds.title%>
jfjh
</p>
<p>
jfjh
</p>
<p>
jfjh
</p>
<p>
jfjh
</p>
<p>
jfjh
</p>
<br>
<hr>
Added my new javascript (endless.js) courtesy of pedromtavares
$('ul').endlessScroll({
fireOnce: true,
fireDelay: 500,
ceaseFire: function(){
return $('#infinite-scroll').length ? false : true;
},
callback: function(){
$.ajax({
url: '/home',
data: {
last: $(this).attr('last')
},
dataType: 'script'
});
}
});
My final javascript file looks like this:
<% unless #feeds.blank? %>
$('.endless_scroll_inner_wrap').append("<%=escape_javascript(render :partial => 'feeds', :collection => #feeds)%>");
$('ul').attr('last', '<%=#feeds.to_a.last.created_at%>')
<% else %>
$('#infinite-scroll').detach();
<% end %>
I don't get any errors but no infinite scroll either. I get the first posts from the array but not the rest. Can't figure out what I am doing wrong and it feels like I've tried everything by now... Please help!
Had a similar problem myself. My issue was that my append in my javascript could not find the proper div. Might work for you -
In your javascript file, change:
$('.endless_scroll_inner_wrap').append...
to:
$('#infinite-scroll').append...
and see if that fixes it.

How can I send an automatically generated ID for a form element to a javascript function?

I am trying to call a javascript function from my form page in a Rails 3 project. I need to send the function the ID of a particular element. Unfortunately I can't get the ID easily since it is automatically generated by a plugin.
I tried doing it this way:
<%= t.select :number_type, #id_types, {}, {:onchange => "has_other_field(' + the_value.id.to_s + "');"} %>
<% if (!the_value.nil?) && (!the_value.number_type.nil?) && !#id_types_sm.include? the_value.number_type) %>
<script type="text/javascript">
setup_other_field("<%= the_value.number_type %>", ###ID WOULD GO HERE###);
</script>
<% end %>
.. But since I don't know the ID of the element, I can't call it from the function.
So now I'm trying to do it this way, by calling the function from an "onload" when the input element loads:
<% if (!the_value.nil?) && (!the_value.number_type.nil?) && (!#id_types_sm.include? the_value.number_type) %>
<%# Call the function from the form helper only if the conditions are met %>
<%= t.select :number_type, #id_types, {}, {:onchange => "has_other_field(this.id);", :onload => "setup_other_field('" + the_value.number_type + "', this.id);"} %>
<% else %>
<%# Use the form helper without calling the function %>
<%= t.select :number_type, #id_types, {}, {:onchange => "has_other_field(this.id);"} %>
<% end %>
BUT I realize that onload does not work for this situation. Is there any workaround for this? How can I either
A) get the element ID from the field to the function in the first option, or
B) call this function from this input element whenever it loads?
... or C) an alternative way to do this?
Thanks in advance and let me know if more details would help.
If you have ID saved in the model, get it with <%= model.id %>
Exception to this rule is when you create object, and it is before it is written to database. If you go to edit or anywhere else it will be ok.
If you have it somewhere on the page :/ then you can use jQuery to get it for you.
< div id="id_of_the_element" attr_with_my_id="15" >ABC< /div >
$("#id_of_the_element").attr('attr_with_my_id')
< input id="id_of_the_element ... >< /input >
$("#id_of_the_element").value

Is it right to generate the javascript using C# in ASP.NET MVC view page?

[Sorry for long question but it is necessary to explain the problem]
I am working on a learning website and it is supposed to show a list of messages to user if there are any. Something like this:
When user presses close button, that message must be marked "read" and should not be shown next time. Following code is used to generate those messages:
<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
<p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
<p><%= Html.Encode (m.Text) %></p>
<% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
<input type="submit" value="Close<%= Html.AttributeEncode (m.ID) %>" id="c<%= Html.AttributeEncode (m.ID) %>"/>
<% } %>
</div>
<% } %>
After that, following the guidelines, I added the support of http post method in controller which marks the message as read and then refreshes the view (to handle disabled JavaScript):
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CloseMessage (int id) {
using (var dl = new DL ()) {
dl.MarkAsRead (id);
}
if (Request.IsAjaxRequest ()) {
return new EmptyResult ();
}
else {
return RedirectToAction ("Index");
}
}
Then I wanted to add JavaScript support such that only the message goes away (using jQuery). But the problem is that I am generating the buttons and messages programmatically.
So ended up with a weird looking javascript code in viewpage:
<script type="text/javascript">
$().ready(function() {
<% foreach (var m in Model.UserMessages) { %>
$("#c<%=Html.AttributeEncode (m.ID) %>").click(function(event) {
$.post("Home/CloseMessage/<%=Html.AttributeEncode (m.ID) %>");
$("#m<%=Html.AttributeEncode (m.ID) %>").slideUp("slow");
event.preventDefault();
});
<% } %>
});
</script>
This is basically creating the javascript code in a C# loop which actually works but too much for me to digest. Is there any better way of doing this?
You could just create one javascript function that takes the element IDs as parameters :
function myFunction(ID) {
$.post("Home/CloseMessage/" + ID);
$("#m" + ID).slideUp("slow");
}
And :
<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
<p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
<p><%= Html.Encode (m.Text) %></p>
<% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
<input type="submit" value="Close<%= Html.AttributeEncode (m.ID) %>"
id="c<%= Html.AttributeEncode (m.ID) %>"
onclick="myFunction('<%=Html.AttributeEncode(m.ID)%>')"/>
<% } %>
</div>
<% } %>
YOu could uses a CSS selector in your JS to get all buttons with a particular class assigned to them. Then you can wire up you click event to them. So your HTML would be something like this:
<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
<p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
<p><%= Html.Encode (m.Text) %></p>
<% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
<input type="submit" class="MyCloseButton" value="Close<%= Html.AttributeEncode (m.ID) %>" id="c<%= Html.AttributeEncode (m.ID) %>"/>
<% } %>
</div>
<% } %>
I've only added the class="MyCloseButton" to your input
Then in your JS (I use mootools but JQuery has CSS selectors too but you will need to port it sorry) you can do something like this:
window.addEvent( "domready", function() {
$$("input.MyCloseButton").each( function( button ) {
// Add your code here, you can reference button.id etc for each of your buttons
}
});
This way you only have to write out one little function in plan JS and not worry about doing it server-side, all you need to do it decorate your buttons with a css class so the JS can find them.
I understand its not pretty, but its not that bad either. I think there are easier ways to do this, however.
You can use jquery's positional selectors from the button's click event handler. Then just assign the same handler to every button.
<script type="text/javascript">
$(document).ready(function() {
$("input[type=submit]").click(function(){
$(this).parent().slideup("slow");
$.post("Home/CloseMessage/" + $(this).parent().attr("id"));
event.preventDefault();
});
});
});
</script>

Categories

Resources