Identifying a Specific Button when Submitting AjaxForm(s) - javascript

I'm using Django and AjaxForm to submit a form(s) that adds an item to a user's "cart". I have multiple items listed on the page, each with it's own "add to cart" button. Upon clicking a specific "add to cart" button, I use Ajax to add the item to the user's "cart" and display it in their "cart" at the top of the screen. Users can also delete an item from their cart by clicking on a given item in the cart.
I would now like to change the appearance of the "add to cart" button once it has been clicked, but I am having trouble identifying only the specific button that was clicked (and not all of the 'add to cart' buttons). How can I identify which 'add to cart' button was clicked. I added an 'id' field to my html button and have been trying to use that but have been unsuccessful....??
I have tried many different things but either they are not working or I am putting them in the wrong spot. For example, I have tried:
$('.add-to-cart').on('click',function(){
var id = $(this).attr("id");
console.log("ID: ");
console.log(id);
});
And also:
var addButtonID;
$(this).find('input[type=submit]').click(function() {
addButtonId = this.id;
console.log("ID: ");
console.log(addButtonId)
)};
Any ideas on how I can find the specifc button that was clicked so I can update the button's appearance???
My html:
{% for item in item_list %}
<form class="add-to-cart" action="/item/add/{{ item.id }}/" method="post" enctype="application/x-www-form-urlencoded">
<ul>
<li style="display: block"><button class="addItemButton2" type="submit" id="{{ item.id }}">Add to Cart</button></li>
</ul>
</form>
{% endfor %}
My javascript:
function remove_form_errors() {
$('.errorlist').remove();
}
function show_hide_cart(){
var cart = $('#cart');
var message = $('#message');
if (cart.find('li').length >= 1){
cart.show();
continueButton.show();
message.hide();
}
else {
cart.hide();
continueButton.hide();
message.show();
}
}
function process_form_errors(json, form)
{
remove_form_errors();
var prefix = form.data('prefix'),
errors = json.errors;
if (errors.__all__ !== undefined) {
form.append(errors.__all__);
}
prefix === undefined ? prefix = '' : prefix += '-';
for (field in errors)
{
$('#id_' + prefix + field).after(errors[field])
.parents('.control-group:first').addClass('error');
}
}
function assign_remove_from_cart() {
var cart = $('#cart');
$('.remove-from-cart').on('click', function(e) {
e.preventDefault();
$.get(this.href, function(json) {
remove_form_errors();
cart.find('a[href$="' + json.slug + '/"]').parent('li').remove();
show_hide_cart();
});
});
}
(function($){
$(function() {
var cart = $('#cart'),
message = $('#message');
continueButton = $('#continueButton');
assign_remove_from_cart();
// ajax-enable the "add to cart" form
$('.add-to-cart').ajaxForm({
dataType: 'json',
url: this.action,
success: function(json, status, xhr, form) {
if (json.errors !== undefined) {
// display error message(s)
process_form_errors(json, form);
}
else if(json.id == -1){
// duplicate, do nothing
console.log("json.id:%s:json.slug:%s", json.id, json.slug)
}
else {
// Hide any previously displayed errors
remove_form_errors();
// compile cart item template and append to cart
var t = _.template($('#cart-item-template').html());
$('#cart').append(t(json));
show_hide_cart();
assign_remove_from_cart();
}
}
});
});
})(jQuery);

Based on your comments, you ought to be able to drop your onClick function into a script tag at the end of your HTML page and have it function as intended (though your javascript should actually all be in a separate file that gets referenced via a script tag).
$( document ).ready(function(){
$('.add-to-cart :submit').on('click',function(){
var id = this.id;
console.log("ID: ",id);
//do something with your ID here, such as calling a method to restyle your button
$('#' + id).css("attribute","new value");
//or
$('#' + id).addClass("yourClassName");
});
});

Change the button type to 'button', and then add onClick="addToCartFunction(this);"
then in the addToCarFunction, this.id will be your item id your adding?, or you can use data-attributes to add more item details for the function to get.
if you then need to send information to the server to cache the cart, use a $.ajax jQuery call to the server.

Related

remove object from array when user clicks button

I am trying to store a users selected items into an object so that when the user clicks a "remove button" it will also remove that item from my object. I seem to be running into an error where only the first object in my array will be removed and nothing else. Could I have some assistance?
each li has a data-id value of i, where i is an integer that increments once for every item the user adds to their list for example:
user clicks add
data-id:1
user clicks add
data-id:2
etc etc, currently when the user clicks remove...it will only remove the object with id: 0.. However clicking on any of the other items in the list does not affect the exerciseDataArr
EDIT: Included my html file, this is a Python Flask app and im using Jinja templates, as well as Wtforms to generate the form as I have a dynamic select field that uses my database to pull exercise names from that database for the user to pick from to build a routine.
createRoutine.html
{% extends 'profileSignedInBase.html' %}
{% block content %}
<div>
<div id="media">
<div>
<form action="/workoutroutines">
{{form.hidden_tag()}}
{% for field in form if field.widget.input_type != 'hidden' %}
{{ field(placeholder=field.label.text) }}
{% endfor %}
<button id="createBtn">CREATE</button>
</form>
<div>
<button id="addBtn">Add Exercise To List</button>
</div>
<h1>This is what you have planned for your routine</h1>
<ol id="routineWishlist">
</ol>
</div>
</div>
<script src="/static/addExercise.js"></script>
{% endblock %}
addExercise.JS
let jsonData = {}
let exerciseDataArr = []
let i = 0;
// generate list of items the user has selected for their workout
document.querySelector("#media").addEventListener("click", function (e) {
//Add Item to
if (e.target.id == "addBtn") {
e.preventDefault();
var exerciseValue = $('#exerciseChoices').find(":selected").text();
var workoutName = $('#workoutName').val();
var workoutDescription = $('#description').val();
if (workoutName == "") {
console.log("please fill out all data")
alert("please add a name")
return;
}
if (workoutDescription == "") {
console.log("please fill out all data")
alert("please add a description")
return;
}
console.log("You clicked on the Add button")
var li = document.createElement("li");
var div = document.createElement("div")
var remove = document.createElement("button");
li.setAttribute("data-id", i)
div.setAttribute("id", `exercise${i}`)
remove.setAttribute("id", "removeBtn");
remove.innerText = 'Remove';
try {
jsonData['name'] = workoutName;
jsonData['description'] = workoutDescription;
exerciseDataArr.push({ 'exercise': exerciseValue,
id: i})
} catch (error) {
console.error(error)
}
i++;
console.log(jsonData) //{"name": "workout 1","description": "My favorites"}
console.log(exerciseDataArr) //After adding 2 exercises to the list {"exercise": "2 Handed Kettlebell Swing","id": 0}{"exercise": "2 Handed Kettlebell Swing","id": 1}
var t = document.createTextNode(exerciseValue);
div.append(li)
li.append(remove);
li.appendChild(t);
document.querySelector("#routineWishlist").appendChild(div);
}
if (e.target.id === "removeBtn") {
e.preventDefault();
exerciseName = $(e.target).closest('div').attr('id');
exerciseOrder = parseInt($(e.target).closest('li').attr('data-id'));
console.log("remove " + typeof(exerciseOrder) + " " + exerciseOrder + " at " + exerciseName )
console.log("inside " + typeof(exerciseDataArr)) //object
//remove from displayed list of exercises
$(e.target).closest('div').remove()
// remove from object
for(let val in exerciseDataArr){
val = parseInt(val)
console.log(`id: ${val}`)
// if the exerciseDataArr contains id: exerciseOrder delete from exerciseDataArr
if(exerciseDataArr.hasOwnProperty("id") == exerciseOrder ){// <---does not activate unless the first 'li' is clicked.
console.log("the object has been found, now delete it")
delete exerciseDataArr[exerciseOrder]
val = undefined;
}
}
console.log(exerciseDataArr)
}
Can You post some more code ? If Possible post the HTML as well and what is the exerciseDataArr in your code it is not clearly explained

Javascript $(var).html(data); not working

I'm currently using javascript to try and update a page with ajax. however, using .html to update the page with the parameter i pass in ends with no resulting changes. The html page is a grid of buttons and i'm trying to update the button being right clicked with the 'flaggedcell' img. I can sucessfully log the data that i'm trying to replace, however, in the line right below that, the .html function isnt doing anything.
Javascript:
$(function() {
console.log("Page is ready");
$(document).bind("contextmenu", function(e) {
e.preventDefault();
console.log("Right click. Prevent context menu from showing.")
});
$(document).on("mousedown", ".game-button", function(event) {
switch (event.which) {
case 1:
var buttonNumber = $(this).val();
console.log("Button number " + buttonNumber + " was left clicked");
break;
case 2:
alert('Middle mouse button is pressed');
break;
case 3:
event.preventDefault();
var buttonNumber = $(this).val();
console.log("Button Number " + buttonNumber + " was right clicked");
doFlag(buttonNumber);
break;
default:
alert('Nothing');
}
});
});
function doFlag(buttonNumber) {
$.ajax({
datatype: "json",
method: 'POST',
url: '/grid/flag',
data: {
"cellNumber": buttonNumber
},
success: function(data) {
// this data logs succesfully
console.log(data);
//this changes nothing
$("#" + buttonNumber).html(data);
}
})
}
data html:
#model MinesweeperASP.NET.Models.Cell
#{
//store image names in an array for more efficient code.
string[] imageNames = { "UnoenedCell.png", "green.png", "bomb.png", "FlaggedCell.png" };
int i = 0;
}
#if (!Model.isVisited && Model.isFlagged)
{
i = 3;
}
<button class="game-button" type="submit" value="#Model.rowNumber,#Model.colNumber" name="cellNumber" asp-controller="Grid" asp-action="HandleLeftClick">
<img class="game-button-image" src="~/img/#imageNames[i]" />
<div class="button-label">
#Model.rowNumber
,
#Model.colNumber
</div>
</button>
Developer tools output:
Page is ready
site.js?v=yEzTfLHBcae6F8YYH3SeJjYAxKx_gxgY8BqS9gC2o5c:24 Button Number 0,1 was right clicked
site.js?v=yEzTfLHBcae6F8YYH3SeJjYAxKx_gxgY8BqS9gC2o5c:42
<button class="game-button" type="submit" value="0,1" name="cellNumber" formaction="/Grid/HandleLeftClick">
<img class="game-button-image" src="/img/FlaggedCell.png" />
<div class="button-label">
0
,
1
</div>
</button>
site.js?v=yEzTfLHBcae6F8YYH3SeJjYAxKx_gxgY8BqS9gC2o5c:5 Right click. Prevent context menu from showing.
Your button is not having id attribute. Add the id attribute and check it.

button change jquery javascript

Is there a way to change my button to "remove" if i clicked the "add to stay button"
Like when i click the add button it will load the data then it will be changed to remove button because it is already added.
and if i press the remove button how can it go back to "add to your stay" button? Here is my js code and My button code
$(document).ready(function() {
$(".addons").on("click", function(event) {
event.preventDefault();
var id = $(this).data('addon-id');
console.log(id);
if (id != '') {
$.ajax({
type: "POST",
url: "Pages/addonajax",
data: {
id: id
},
success: function(data) {
console.dir(data);
if (data) {
result = JSON.parse(data);
$("#test4>span").html(result[0]['name']);
$("#test5>span").html(result[0]['price']);
$("#test2>span").append(result[0]['price']);
} else {
$('#test1').append('no records found');
}
}
});
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3 class="bookingroom">Total: PHP 2,750.00</h3>
<h5 class="addon-taxes2">Including Taxes & Fees</h5>
<button class="addons addon-btn trans_200">ADD TO MY STAY</button>
here's the example fiddle
https://jsfiddle.net/j501fwb8/1/
It's much harder to maintain a single element that has to do multiple things based on some criteria. Instead I highly suggest using multiple elements with a Single Responsibility.
I'd also HIGHLY recommend reading Decoupling Your HTML, CSS, and JavaScript - Philip Walton (Engineer # Google)
My example would be something like:
$(document).ready(function() {
$('.js-btn-addon').on('click', function() {
var $this = $(this);
/// do whatever
var addonId = $this.data('addon-id');
$this.addClass('is-hidden');
$('.js-btn-remove[data-addon-id="' + addonId + '"]').removeClass('is-hidden');
});
$('.js-btn-remove').on('click', function() {
var $this = $(this);
/// do whatever
var addonId = $this.data('addon-id');
$this.addClass('is-hidden');
$('.js-btn-addon[data-addon-id="' + addonId + '"]').removeClass('is-hidden');
});
});
.is-hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="addons addon-btn js-btn-addon trans_200" data-addon-id = "1">ADD TO MY STAY</button>
<button class="addons addon-btn js-btn-remove is-hidden trans_200" data-addon-id = "1">Remove</button>
<br/>
<button class="addons addon-btn js-btn-addon trans_200" data-addon-id = "2">ADD TO MY STAY</button>
<button class="addons addon-btn js-btn-remove is-hidden trans_200" data-addon-id = "2">Remove</button>
<br/>
<button class="addons addon-btn js-btn-addon trans_200" data-addon-id = "3">ADD TO MY STAY</button>
<button class="addons addon-btn js-btn-remove is-hidden trans_200" data-addon-id = "3">Remove</button>
<br/>
You can change the HTML of the element to say Remove by using:
$(".addons").html('Remove');
You will have to handle the onClick method functionality accordingly though. Or you can remove the button altogether and show a different one.
You can change text after ajax call and load data, also you can add class for remove process etc.
Note: here i remove your ajax call, just put .text() on ajax success when load data
$(document).ready(function(){
$(".addons").on("click", function(event) {
var _t = $(this);
if(_t.hasClass('remove')){
_t.removeClass('remove').text('ADD TO MY STAY');
} else {
_t.addClass('remove').text('Remove');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3 class = "bookingroom">Total: PHP 2,750.00</h3>
<h5 class = "addon-taxes2">Including Taxes & Fees</h5>
<button class="addons addon-btn trans_200">ADD TO MY STAY</button>
You can use a class to mark the button once it has been used to add the item. Wrapping the execution code inside an if/else block lets you check whether the class exists so you can act accordingly.
See the comments in this suggested code:
$(document).ready(function() {
$(".addons").on("click", function(event) {
event.preventDefault();
var id = $(this).data('addon-id');
console.log(id);
if (id != ''){
// Tests which type of button this is (see below)
if(!this.classList.contains("isRemoveButton")){
/* Your ajax call for adding goes here */
// Changes the button text
$(this).text("REMOVE");
// Adds a class indicating which type of button this is
this.classList.add("isRemoveButton");
} else {
/* Different ajax call for removing goes here */
// Restores original button text
$(this).text("ADD TO MY STAY");
// Restores original classList state
this.classList.remove("isRemoveButton");
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3 class="bookingroom">Total: PHP 2,750.00</h3>
<h5 class="addon-taxes2">Including Taxes & Fees</h5>
<button class="addons addon-btn trans_200" data-addon-id="1">ADD TO MY STAY</button>
$(document).ready(function(){
$(".addons").on("click", function(event) {
event.preventDefault();
var id = $(this).data('addon-id');
console.log(id);
if(id != '')
{
$.ajax(
{
type:"POST",
url : "Pages/addonajax",
data:{id:id},
success:function(data)
{
console.dir(data);
if (data) {
result = JSON.parse(data);
$("#test4>span").html(result[0]['name']);
$("#test5>span").html(result[0]['price']);
$("#test2>span").append(result[0]['price']);
}
else {
$('#test1').append('no records found');
}
}
});
}
$(this).hide();
$('.remove').show();
//and write a remove property which you want.
});
$('.remove').on("click", function(){
//write your property here for remove once.
$(".addons").show();
$(this).hide();
})
});

How can I use an autosave partial view on a page with multiple forms?

Extending the example found at Autosave in MVC (ASP.NET), I wanted to create a partial to reuse in my application. I have one view with a tabbed layout, and each tab has its own form, and this is causing problems, namely that every form tries to submit every time, and only the first timestamp in the document updates. I understand why this is happening, but I don't know how I can fix it.
Partial's cshtml:
<div class="form-group">
<label class="control-label col-lg-2" for=""> </label>
<div class="col-lg-10">
<span class="help-block" id="autosaveTime">Not Autosaved</span>
</div>
</div>
#{
var autosaveString = "'" + #ViewData["autosaveController"] + "'";
if (ViewData["autosaveAction"] != null && ViewData["autosaveAction"] != "")
autosaveString += ", '" + ViewData["autosaveAction"] + "'";
}
<script type="text/javascript">
$(document).ready(function () {
autosave(#Html.Raw(autosaveString));
});
</script>
Javascript:
//methodName is optional-- will default to 'autosave'
function autosave(controllerName, methodName)
{
methodName = typeof methodName !== 'undefined' ? methodName : 'autosave'
var dirty = false;
$('input, textarea, select').keypress(function () {
dirty = true;
});
$('input, textarea, select').change(function () {
dirty = true;
});
window.setInterval(function () {
if (dirty == true) {
var form = $('form');
var data = form.serialize();
$.post('/' + controllerName + '/' + methodName, data, function () {
$('#autosaveTime').text("Autosaved at " + new Date);
})
.fail(function () {
$('#autosaveTime').text("There was a problem autosaving, check your internet connection and login status.");
});
dirty = false;
}
}, 30000); // 30 seconds
}
I have 2 ideas on how to fix it, but not sure which is more maintainable/workable:
Give each form an id, and pass that to the partial/autosave function. Add the name to the autosavetime text block for updates, and to determine which form to serialize/submit.
Somehow use jquery's closest function to find the form where the autosave block was placed, and use that to do what I was doing explicitly with #1.
First, make the URL using your Razor helper's Html extension (dynamically piecing URLs like this in JavaScript is unnecessarily risky). Take that, and stuff it in a data attribute on the tab control like so:
<div class="tab autosave" data-action-url='#Html.Action("Action", "Controller")'>
<form>
<!-- Insert content here -->
</form>
</div>
Then, you'll want something like this ONCE -- do not include it everywhere, and remove the javascript from your partial completely:
$(function() {
// Execute this only once, or you'll end up with multiple handlers... not good
$('.autosave').each(function() {
var $this = $(this),
$form = $this.find('form'),
dirty = false;
// Attach event handler to the tab, NOT the elements--more efficient, and it's always properly scoped
$this.on('change', 'input select textarea', function() {
dirty = true;
});
setInterval(function() {
if(dirty) {
// If your form is unobtrusive, you might be able to do something like: $form.trigger('submit'); instead of this ajax
$.ajax({
url : $this.data('action-url'),
data : $form.serialize()
}).success(function() {
alert("I'm awesome");
dirty = false;
});
}
}, 30 * 1000);
});
});

How can I delete the selected messages (with checkboxes) in jQuery?

I'm making a messaging system and it has a lot of AJAX. I'm trying to add a bulk actions feature with check boxes. I've added the checkboxes, but my problem is that I don't know how to make something happen to the selected messages.
Here's my function that happens whenever a checkbox is clicked:
function checkIt(id) {
if ($('#checkbox_' + id).is(':checked')) {
$('#' + id).addClass("selected");
}
else {
$('#' + id).removeClass("selected");
}
}
But, I don't know where to go from there.
Here is some example markup for one of the lines [generated by PHP] of the list of messages:
<div class="line" id="33" >
<span class="inbox_check_holder">
<input type="checkbox" name="checkbox_33" onclick="checkIt(33)" id="checkbox_33" class="inbox_check" />
<span class="star_clicker" id="star_33" onclick="addStar(33)" title="Not starred">
<img id="starimg_33" class="not_starred" src="images/blank.gif">
</span>
</span>
<div class="line_inner" style="display: inline-block;" onclick="readMessage(33, 'Test')">
<span class="inbox_from">Nathan</span>
<span class="inbox_subject" id="subject_33">Test</span>
<span class="inbox_time" id="time_33" title="">[Time sent]</span>
</div>
</div>
As you can see, each line has the id attribute set to the actual message ID.
In my function above you can see how I check it. But, now what I need to do is when the "Delete" button is clicked, send an AJAX request to delete all of the selected messages.
Here is what I currently have for the delete button:
$('#delete').click(function() {
if($('.inbox_check').is(':checked')) {
}
else {
alertBox('No messages selected.'); //this is a custom function
}
});
I will also be making bulk Mark as Read, Mark as Unread, Remove Star, and Add Star buttons so once I know how to make this bulk Delete work, I can use that same method to do these other things.
And for the PHP part, how would I delete all them that get sent in the AJAX request with a mysql_query? I know it would have to have something to do with an array, but I just don't know the code to do this.
Thanks in advance!
How about this
$('#delete').click(function() {
var checked = $('.inbox_check:checked');
var ids = checked.map(function() {
return this.value; // why not store the message id in the value?
}).get().join(",");
if (ids) {
$.post(deleteUrl, {idsToDelete:ids}, function() {
checked.closest(".line").remove();
});
}
else {
alertBox('No messages selected.'); // this is a custom function
}
});
Edit: Just as a side comment, you don't need to be generating those incremental ids. You can eliminate a lot of that string parsing and leverage jQuery instead. First, store the message id in the value of the checkbox. Then, in any click handler for a given line:
var line = $(this).closest(".line"); // the current line
var isSelected = line.has(":checked"); // true if the checkbox is checked
var msgId = line.find(":checkbox").val(); // the message id
var starImg = line.find(".star_clicker img"); // the star image
Assuming each checkbox has a parent div or td:
function removeDatabaseEntry(reference_id)
{
var result = null;
var scriptUrl = './databaseDelete.php';
$.ajax({
url: scriptUrl,
type: 'post',
async: false,
data: {id: reference_id},
success: function(response)
{
result = response;
}
)};
return result;
}
$('.inbox_check').each(function(){
if ($(this).is(':checked')){
var row = $(this).parent().parent();
var id = row.attr('id');
if (id == null)
{
alert('My selector needs updating');
return false;
}
var debug = 'Deleting ' + id + ' now...';
if (console) console.log(debug);
else alert(debug);
row.remove();
var response = removeDatabaseEntry(id);
// Tell the user something happened
$('#response_div').html(response);
}
});

Categories

Resources