Using infinite scroll in a Rails application - javascript

I want my application to have an endless scroll. For that I'm using this javascript https://github.com/jney/jquery.pageless/blob/master/lib/jquery.pageless.js
Then as he suggested in the usage I wrote added the pageless function in my script tag. But the application is failing to work. Am I doing this correctly?
<div id = "container1"></div>
<script>
$(document).ready(function() {
$.ajax({
url : "shirts/first",
type : "GET"
});
$("#name").autocomplete({
source : "shirts/autocomplete",
autoFocus : false,
minLength : 1,
select : function(event, ui) {
document.getElementById("name").value = ui.item.value;
$.ajax({
url : "shirts/show?name=" + ui.item.value,
type : "GET"
});
}
});
$('#container1').pageless({
totalPages: 4,
url: 'shirts/first',
loaderMsg: 'Loading more results'
});
});
</script>
Controller code:
def first
#init = Sunspot.search(Clothes) do
paginate :page => params[:page], :per_page => 16
order_by :maxprice
end
#first = #init.results
if request.xhr?
sleep(1)
render :partial => 'shirts/first', :collection => #first
end
end

first error i see is that you have defined the div with id #container1 but your jquery calls #container
also make sure you have the proper urls loading in that js. if this doesn't work, please provide more info

Related

Render rails fields_for through ajax call

I have an AJAX call:
$('#enrollment_members').change(function(){
var memberNumber = $(this);
$.ajax({type: 'GET',
url: $(this).href,
type: "get",
data: { members: memberNumber.val() },
error: function(){ alert("There was a problem, please try again.") }
});
return false;
console.log(data);
});
through which I send params[:members] into a new method.
I wanna do something like this:
def new
#enrollment = Enrollment.new
params[:members] ? params[:members].to_i.times { #enrollment.atendees.build } : #enrollment.atendees.build
respond_to do |format|
format.js
end
end
I need this value in order to know how many fields_for to build.
But this being in the new action, how can I update the content of the new view after inputting a value in the members input field?
From that ternary, #enrollment.atendees contains 4 objects.
My new.js.erb :
$("#contact-wrap").html("<%= j render(:partial => 'enrollments/form') %>");
The xhr response contains 4 fields_for forms.
Is the object #enrollment_members the input value you are trying to pass to the controller?
if so, try this:
$('#enrollment_members').change(function(){
var memberNumber = $(this);
$.ajax({type: 'GET',
url: $(this).href,
type: "get",
data: { members: memberNumber.serialize() }, //CHANGE
error: function(){
alert("There was a problem, please try again.")
}
});
return false;
Hmm are you really sure you need a custom made solution for this ? The behavior of dynamically adding/removing children in fields_for is already adressed by several gems like nested_form (no longer maintained) or cocoon (more promising)
I'd suggest to actually reuse their library even if you need to tweak it your way. Because doing an AJAX request is completely pointless. Your AJAX is a GET request that will always do the same thing, unless you have a custom atendees.build which will do weird things for successive calls (like incrementing a global counter somewhere).
Those gems I mentionned above will actually save the HTML fields to generate in a "template" (stored locally in HTML or JS), and just call this template when you want to add a new field.
I got it working by modifying the ajax call:
$('#enrollment_members').change(function(){
var memberNumber = $(this);
$.ajax({type: 'GET',
url: $(this).href,
type: "get",
dataType : "html",
data: { members: memberNumber.val() },
success: function( data ) {
var result = $('<div />').append(data).find('#contact-wrap').html();
$('#contact-wrap').html(result);
$('#atendees-wrap').show();
},
error: function( xhr, status ) {
alert( "Sorry, there was a problem!" );
}
});
return false;
});

Rendering an object passed through Pusher in Rails

I am trying to implement a realtime chat application.
I'm using pusher to notify server about the button click, and then pass the message object as message to a subscriber. What I need to do is, render that message in other user's chat screen(show.html.erb) dynamically. Here is my cycle:
// MessagesController.rb
def create
conversation = Conversation.find(params[:conversation_id])
message = Message.create(content: params[:content], user_id: params[:user_id])
conversation.messages << message
Pusher['test_channel'].trigger('my_event', {
message: message
})
end
And my subscriber is
// show.html.erb
// some html code
<ul class="chats">
<%= render #messages %>
</ul>
// some html code
<script>
// some js code
var channel = pusher.subscribe('some_channel');
channel.bind('some_event', function(data) {
// What to do here?
});
</script>
This assumes you are using jquery. It's also untested so may have a few bugs/syntax errors.
Ajax method:
JS
channel.bind('some_event', function(data) {
$.ajax({
url:'/messages/'+data.message.id,
success:function(html){ $('.chats').append(html)}
});
});
routes:
match '/messages/:id' => "messages#show_no_layout"
controller:
def show_no_layout
#message = Message.find(params[:id])
render "show", layout: false
end
view(show.html.erb):
<%= *whatever you want in here* %>
ICH(read more) method:
This will of course require adding an extra js file which is why its not my first suggestion.
Template:
<script id = "messageTemplate" type = "text/html">
{{ message.content }}
// plus whatever else you want.
</script>
channel.bind('some_event', function(data) {
messageHtml = ich.messageTemplate(data.message);
$('.chats').append(messageHtml);
});
If you are using JQuery,
channel.bind('some_event', function(data) {
$('.message').text(data.message);
});
See this tutorial.

Dropzonejs with Rails Delete files from the page

I am using a carrierwave and dropzonejs. Everything seems fine however, when I try to press to remove picture button, even though it removes from the database, picture stays on the container.
Here how it looks like;
When I click to remove file link all of them, it becomes;
So I clicked all the remove file buttons, they are removed from the database however, stays on the page. I think it is because of the js code (end part) below,
<script type="text/javascript">
$(document).ready(function(){
// disable auto discover
Dropzone.autoDiscover = false;
// grap our upload form by its id
$("#picture-dropzone").dropzone({
// restrict image size to a maximum 5MB
maxFilesize: 5,
// changed the passed param to one accepted by
// our rails app
paramName: "picture[image]",
acceptedFiles: "image/*",
// show remove links on each image upload
addRemoveLinks: true,
// if the upload was successful
success: function(file, response){
// find the remove button link of the uploaded file and give it an id
// based of the fileID response from the server
$(file.previewTemplate).find('.dz-remove').attr('id', response.fileID);
$(file.previewTemplate).find('.dz-remove').attr('boat_id', response.boatID);
// add the dz-success class (the green tick sign)
$(file.previewElement).addClass("dz-success");
},
//when the remove button is clicked
removedfile: function(file){
//location.reload();
//removeFile(file); *******THIS DOES NOT WORK*******
// grap the id of the uploaded file we set earlier
var id = $(file.previewTemplate).find('.dz-remove').attr('id');
var boat_id = $(file.previewTemplate).find('.dz-remove').attr('boat_id');
// // make a DELETE ajax request to delete the file
$.ajax({
type: 'DELETE',
url: '/boats/' + boat_id + '/pictures/' + id,
success: function(file){
}
});
}
});
});
</script>
pictures controller if anyone wonders,
class PicturesController < ApplicationController
before_action :logged_in_user
before_filter :load_parent
def new
#picture = #boat.pictures.new
#pictures = #boat.pictures.all
end
def show
#picture = #boat.pictures.find(params[:id])
end
def create
#picture = #boat.pictures.new(picture_params)
if #picture.save
render json: { message: "success", fileID: #picture.id, boatID: #boat.id }, :status => 200
else
render json: { error: #picture.errors.full_messages.join(',')}, :status => 400
end
end
def edit
#picture = Picture.find(params[:id])
end
def update
#picture = #boat.pictures.find(params[:id])
if #picture.update_attributes(picture_params)
flash[:notice] = "Successfully updated picture."
render 'index'
else
render 'edit'
end
end
def destroy
#picture = #boat.pictures.find(params[:id])
if #picture.destroy
render json: { message: "File deleted from server" }
#redirect_to new_boat_picture_path(#boat, #picture)
flash[:notice] = "Successfully destroyed picture."
else
render json: { message: #picture.errors.full_messages.join(',') }
end
#flash[:notice] = "Successfully destroyed picture."
#redirect_to new_boat_picture_path(#boat, #picture)
#redirect_to boat_pictures_path(#boat)
#redirect_to boat_path(#boat)
end
private
def picture_params
params.require(:picture).permit(:name, :image)
end
def load_parent
#boat = Boat.find(params[:boat_id])
end
end
write below line in your delete ajax call success method
$(file.previewTemplate).fadeOut()

How to refresh Yii widget without refreshing/changing page

I'm having an issue with submitting a TbActiveForm and the renderPartial wiping my page out and displaying only the partial view. I want to reload only the widget after my action triggers and finishes. I'm also using a modal to display and make changes.
view:
$form = $this->beginWidget(
'booster.widgets.TbActiveForm',
array(
'id' => 'horizontalForm',
'type' => 'horizontal',
'action' => Yii::app()->createUrl('orderControl/order/returns.save'),
)
);
echo $form->hiddenField(
$editReturnFormModel,
'orderId',
array(
'value' => $editReturnFormModel->orderId
)
);
$this->widget(
'bootstrap.widgets.TbButton',
array('buttonType' => 'submit', 'type' => 'primary', 'label' => 'Save')
);
$this->endWidget();
Action:
$this->controller->renderPartial('ScModules.orderControl.widgets.ReturnsWidget.views._returnItems', array('returnsDataProvider'=>$returnsDataProvider, 'editReturnFormModel'=>$editReturnFormModel));
One other point is that the Yii::app()->createUrl('orderControl/order/returns.save') is change the page url all together. On this page page I'm directed to, the view is created fine. I need the widget to rebuild/refresh on the current page and not send me somewhere else. Any ideas on solution would be appreciated.
Here's what I would do:
Wrap your form widget inside a div or whatever block tag you like.<div id="myFormWrapper"> (your widget goes here) </div>
Add a custom ID in your form (id="formId") and submit button (id="submitButtonId")
Add some jQuery in order to submit your form and replace the old widget with the new
$(document).on('click', '#submitButtonId' , function() {
$.ajax({
type: 'POST',
url: $('#formId').attr('action'),
data : $('#formId').serialize(),
beforeSend : function(){
//do anything you want before sending the form
},
success : function(data){
//We'll replace the old form with the new form widget
$('#myFormWrapper').html(data);
},
error : function(data){
console.log('ops');
},
});
return false;
});
Do whatever you want to do in your Controller action and use renderPartial.
//The action below should be the same that you used in the action attribute of the form
public function actionProcessForm(){
$model = new MyFormModelName();
if(isset($_POST['MyFormModelName'])){
$model->attributes = $_POST['MyFormModelName'];
if($model->save()){
//Do whatever you want here
$returnsDataProvider = new CActiveDataProvider('YourModel');
$this->renderPartial('//folder/to/your/view', array('returnsDataProvider'=> $returnsDataProvider, 'editReturnFormModel'=>$editReturnFormModel));
}else{
//You might want to render something else here
$this->renderPartial('errorViewPage');
}
}
}

How to change dom element in ajax way but not replace the dom content using javascript way

By default the page will show up vote button
After user click up button, the page will reload again then show down vote button
Now I want to do it in Ajax way without loading the page,
But how could I change the button without reloading the page ?
- if not comment.has_evaluation?(:votes, current_user)
= link_to vote_comment_path(comment, type: "up"), method: :post do
%button.btn.btn-xs.btn-success
Like this
- else
= link_to vote_comment_path(comment, type: "down"), method: :post do
%button.btn.btn-xs.btn-danger
Unlike this
I assume you use background image to control the up vote and down vote buttons. Try this:
var $btn = $('#btn-id');
$.ajax({
url: '/rate',
data: {key: value},
type: 'post'
}).done(function(res) {
if (res.success) {
if (res.myRate.up) {
$btn.removeClass('down-vote-bg');
$btn.addClass('up-vote-bg');
} else {
$btn.removeClass('up-vote-bg');
$btn.addClass('down-vote-bg');
}
}
}).fail(function() {
alert('Action failed');
});
Check jQuery Ajax API for more information.

Categories

Resources