I have an Ajax request in my Rails 4 app, but once the button is clicked it reloads the entire page. How can I keep that from happening? The page is cached so I cannot simply add a link_to or button_to. Thanks in advance.
listing_collection.js
$(document).ready(function(){
$(".listcollect").on("click", function(){
var listID = this.id;
$.ajax({
method: "GET",
url: "/listing_collections/:id/listcollect",
success: function(result) {
var arrLen = result.length
var $ul = $("<ul></ul>")
for (var i = 0; i<arrLen; i++){
var $li = $("<li></li>");
var $a = $("<a></a>");
$a.attr("href", "/listings/" + listID + "/add_to_collection?listing="+listID+"$amp;listing_collection_id="+result[i]["id"]+"&listing_id="+listID)
$a.text(result[i]["name"])
$li.append($a)
$(this).next().append($li)
}
}.bind(this)
})
});
});
This is the button:
<div class="btn-group listcollect-wrapper">
<button class="listcollect button btn-blue-white btn-2x dropdown-toggle" data-toggle='dropdown' type="button" id=<%= listing.id %>>Add to Listing Collection <span class="caret"></span></button>
<ul class='dropdown-menu'>
</ul>
</div>
My two cents
The dom with this class .listcollect is a button of type submit i.e button type="submit"
You can either use button type = "button" or use
event.preventDefault()
$(".listcollect").on("click", function(){
event.preventDefault()
// Rest of code
})
It's because this is the default behaviour of the anchor tag. As suggested you can either change the control type to something like button or override the default behaviour like so:
$(".listcollect").on("click", function(e){
e.preventDefault();
});
Try this:
$(document).ready(function(){
$(".listcollect").on("click", function(e){
e.preventDefault();
e.stopPropagation();
var listID = this.id;
$.ajax({
method: "GET",
url: "/listing_collections/:id/listcollect",
success: function(result) {
var arrLen = result.length
var $ul = $("<ul></ul>")
for (var i = 0; i<arrLen; i++){
var $li = $("<li></li>");
var $a = $("<a></a>");
$a.attr("href", "/listings/" + listID + "/add_to_collection?listing="+listID+"$amp;listing_collection_id="+result[i]["id"]+"&listing_id="+listID)
$a.text(result[i]["name"])
$li.append($a)
$(this).next().append($li)
}
}.bind(this)
})
});
});
I have added e.preventDefault() that prevents the browser to handle the the click by default and e.stopPropagation() that disable the propagation of the click event to the containers of your control, in case they have listener too.
Related
I have two complementary functions, one that publishes a post, and one that unpublishes a post when the user clicks the same button (the button is acting as a toggle). If the post is not published and the user goes to publish it everything works as it is supposed to, however if the user decides to unpublish it again the function to publish is erroneously called again. I am using class selectors to accomplish this. So publish does its business and then sets the class to unpublish so that when the user clicks the button unpublish gets called (which doesn't happen).
I have verified that publish gets the class unpublish after being called, and vise versa but the complementary function never gets called despite having its class changed in the final lines. Console.log shows that publish keeps getting called.
What am I doing wrong?
$('a.publish').on('click', function(e) {
console.log('publish item');
var id = $(this).attr('data-id');
var table = $(this).attr('rel');
var parent = $(this).closest('.btn-group');
var current = $(this).closest('a');
$.ajax({
type: 'POST',
url: '',
data: 'publish=' + id + '&table=' + table,
success: function(data) {
$('#published_' + id).hide().html(data).fadeIn();
count(table);
var buttons = parent.find(".btn-danger");
buttons.each(function() {
$(this).removeClass("btn-danger").addClass("btn-primary");
});
current.find('span').text('Unpublish');
current.removeClass("publish").addClass("unpublish");
}
});
e.preventDefault();
});
$('a.unpublish').on('click', function(e) {
console.log('unpublish item');
var id = $(this).attr('data-id');
var table = $(this).attr('rel');
var parent = $(this).closest('.btn-group');
var current = $(this).closest('a');
$.ajax({
type: 'POST',
url: '',
data: 'unpublish=' + id + '&table=' + table,
success: function(data) {
$('#published_' + id).hide().html(data).fadeIn();
count(table);
var buttons = parent.find(".btn-primary");
buttons.each(function() {
$(this).removeClass("btn-primary").addClass("btn-danger");
});
current.find('span').text('Publish');
current.removeClass("unpublish").addClass("publish");
}
});
e.preventDefault();
});
If this has to do with DOM or something, how can I subvert it?
HTML:
<a class="btn btn-sm btn-primary unpublish" href="javascript:void(0);" data-id="213114246" rel="projects">
<i class="glyphicon glyphicon-plus"></i>
<span class="actions">Unpublish</span>
</a>
$('.btn-container').on('click', '.btn', function(e) {
if ($(this).hasClass('publish')) {
console.log('publish item');
$(this).removeClass("publish").addClass("unpublish").text('unpublish');
} else {
console.log('unpublish item');
$(this).removeClass("unpublish").addClass("publish").text('publish');
}
e.preventDefault();
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn-container">
<a class="btn btn-sm btn-primary unpublish">unpublish</a>
</div>
There are several buttons (they creates dynamically)
<button class="common" id="1.1" status="sale" oncontextmenu="rightButton('1.1'); return false" onclick="addOptions('1.1')" number="1">1</button>
I need to get attributes (class, id, status, number) and insert them into object array. Then input to database.
function saveScheme()
{
var table = document.getElementById('schemeTable');
var elements = table.getElementsByTagName('button');
var arrayIdButtons = {};
for(var i = 0; i<elements.length; i++)
{
arrayIdButtons[i] = {};
for(var j = 0; j<4; j++)
{
arrayIdButtons[i]["coord"] = elements.item([i]).id;
arrayIdButtons[i]["status"] = elements.item([i]).status;
arrayIdButtons[i]["type"] = elements.item([i]).class;
arrayIdButtons[i]["number"] = elements.item([i]).number;
}
}
console.log(arrayIdButtons);
var data='data=' + JSON.stringify(arrayIdButtons,"", 2);
$.ajax({
type: 'POST',
url: "handler.php",
data: data,
cache: false,
data: data,
success: function(data) {
alert(data)
}
});
}
result of this code(console.log(arrayIdButtons);):
Since you're already using jQuery, you can access the attributes of an element using .attr(). For example:
$('.common').attr('number');
Or, without jQuery,
elements[i].getAttribute('number');
Use HTML5 API data
<button class="common" id="1.1" data-status="sale" oncontextmenu="rightButton('1.1'); .....</button>
So,
elements.item([i]).data('status'); //if jquery enabled
You can try this html. then,
<button class="common" data-id="1.1" data-status="sale" data-number="1">1</button>
If DOM is not loaded, then you can get this by
$(document).ready(function(){
$(".common").on("click",function(){
var data_id = $(this).attr('data-id');
var data_status = $(this).attr('data-status');
var data_number = $(this).attr('data-number');
console.log(data_id);
console.log(data_id);
console.log(data_id);
});
});
And if DOM is already loaded you can get them by
$(document).on("click",".common",function(){
var data_id = $(this).attr('data-id');
var data_status = $(this).attr('data-status');
var data_number = $(this).attr('data-number');
console.log(data_id);
console.log(data_id);
console.log(data_id);
});
Then you can push this is an array. Note - this will give you the attributes of only the button was clicked
I'm working at a comment system for a website.
I am using jquery to update the view after comment under post is posted.
The element I am pushing the comment after post is like this:
<p class="card-text new_comment_{{$i->id}}" style="display:none"></p>
So what I do is
//Manages post in view
jQuery(function ($) {
$(document).ready(function () {
$("body").on("submit", ".dynamic-form", function (e) {
var form_id = '#' + $(this).attr('id');
//removes the 'post_' part from id
var id = this.id.replace('post_', '');
var new_comment_class = '.new_comment_' + id;
var new_comment_class_removal = 'new_comment_' + id;
var comments_id = '#comments_' + id;
var form = $(this);
$.ajax({
url: form.prop('action'),
type: 'post',
dataType: 'json',
data: $(this).serialize(),
success: function (data) {
var resultStr = "";
resultStr = resultStr + "<a href=\"#\">" + data.user_name + " <\/a>" + data.body ;
$(comments_id).find(new_comment_class).html(resultStr).slideToggle(150).promise().done(function () {
$(new_comment_class).fadeIn("fast").toggleClass(new_comment_class_removal);
});
$(form_id).slideToggle(150).promise().done(function () {
$(form_id).fadeOut("fast");
});
}
});
e.preventDefault();
});
});
});
so after the javascript gets executed the element loses the class that permits me to find it in the view so that if the user posts again the body of the post doesn't get appended to that element. But now how do I put a new target element as the original one just above the newly creatded one? like this:
<p class="card-text new_comment_{{$i->id}}" style="display:none"></p>
<p class="card-text">This is the body of the comment</p>
solved using http://api.jquery.com/before/ and some temp variables
I have multiple buttons to toggle status of different projects:
<div class="btn-group btn-toggle project_status" data-project-id="1" data-form="project_status" data-value="1">
<button class="btn btn-default active">ACTIVE</button>
<button class="btn btn-primary">CLOSED</button>
</div>
<div class="btn-group btn-toggle project_status" data-project-id="2" data-form="project_status" data-value="1">
<button class="btn btn-default active">ACTIVE</button>
<button class="btn btn-primary">CLOSED</button>
</div>
I need to toggle the data-value between 1 and 2 when ajax post success.
I have tried this so far but without any luck:
$('.project_status').click(function(){
var project_id = $(this).attr('data-project-id');
var project_status_val = $(this).attr('data-value');
var toggle_status = function(){
$(this).find('.btn').toggleClass('active').toggleClass('btn-primary');
if (project_status_val == '1'){
alert(project_status_val);
$(this).attr('data-value','2');
} else {
alert(project_status_val);
$(this).attr('data-value','1');
}
return false;
};
var dataString = 'project_id=' + project_id + '&project_status=' + project_status_val;
$.ajax({
type: "POST",
url: "post.php",
data: dataString,
success: toggle_status
});
$('#sidebar-wrapper').load('sidebar.php');
return false;
});
I have got the alert data value correct. I have got the sidebar reload with updated value (only the first click). But I am not able to change the attribute value so that the next click will send the toggled value.
Please help! Thx
$(this) inside the toggle_status method is not your btn. Inside the method the this keyword refers to the object the method belongs to. In this case Window. As a workaround, I have made a self property before the method to store a reference to the selected $('.project_status') object. I have updated the code so it will work.
https://jsfiddle.net/05akxvx3/1/
$('.project_status').click(function(){
var self = $(this);
var project_id = self.attr('data-project-id');
var project_status_val = self.attr('data-value');
var toggle_status = function(){
self.find('.btn').toggleClass('active').toggleClass('btn-primary');
if (project_status_val == '1'){
self.attr('data-value','2');
} else {
self.attr('data-value','1');
}
alert(self.attr('data-value'));
return false;
};
var dataString = 'project_id=' + project_id + '&project_status=' + project_status_val;
$.ajax({
type: "POST",
url: "post.php",
data: dataString,
success: toggle_status
});
$('#sidebar-wrapper').load('sidebar.php');
return false;
});
You have an extra dash in your $(this).attr() statement.
$(this).attr('data--value','2'); ought to be:
$(this).attr('data-value','2');
i have a button with the folowing code
<button type="button" class="btn btn-success btn-xs vote up" id="76" name="up"><span class="glyphicon glyphicon-thumbs-up"></span> Bueno</button>
the button does not work unless i reload the page, and i dont know why. any ideas?
jquery code is at the beginning of the body
jquery
<script type="text/javascript">
$(function() {
$(".vote").click(function()
{
var id = $(this).attr("id");
var name = $(this).attr("name");
var dataString = 'id='+ id ;
var parent = $(this);
var _this = this;
if(name=='up')
{
$(this).fadeIn(600).html('<span class="glyphicon glyphicon-ok"></span>');
$.ajax({
type: "POST",
url: "up_vote.php",
data: dataString,
cache: false,
success: function(html)
{
parent.html(html);
$( _this ).remove();
$( ".escondido" ).css( "display", "block" );
} });
return false;
});
});
</script>
If the jQuery code is at the beginning of the code (before the HTML) as you state, the DOM would not have been created yet. Try moving the jQuery code to the bottom of the body (after the HTML).
I would assume you're getting an error in the button click event. Have you tried using the live('click') instead? Can you demonstrate the issue using JSFIDDLE?
In the jsFiddle I created, I'm seeing syntax errors - Original Code
If I change the code to Edited jsFiddle:
$(function () {
$(".vote").click(function () {
var id = $(this).attr("id");
var name = $(this).attr("name");
var dataString = 'id=' + id;
var parent = $(this);
var _this = this;
if (name == 'up') {
$(this).fadeIn(600).html('<span class="glyphicon glyphicon-ok"></span>');
$.ajax({
type: "POST",
url: "up_vote.php",
data: dataString,
cache: false,
success: function (html) {
parent.html(html);
$(_this).remove();
$(".escondido").css("display", "block");
}
});
return false;
}; // Removed ) from this line
});
}); // Added this whole line