Why does this function console.log 20 times instead of once? - javascript

In application.js, I have all the 'topics' compiling on the page from an ajax call, and then when one is clicked, all the information appears on the screen. Everything works great in development, but in production I get a 500 server error.
In trying to debug this, I noticed that the console is logging 20 times with the .onclick call. Why is this happening, and does it have any reason why it is returning a 500 error in production (heroku)?
I put ** ** around the 3 console.logs where this is happening.
if(window.location.pathname === "/topics") {
$('.actions').click(function(e) {
console.log("submit");
})
$.ajax({
url: '/topics',
dataType: 'json',
type: 'GET',
success: function(result) {
console.log(result);
for(var i = 0; i < result.length; i++) {
var title = result[i].title;
var level = result[i].level;
var id = result[i].id;
var favlink = '/topics/' + id + '/favorite';
var link = '/topics/' + id;
var topicInfo = {title: title, link: link};
var template = compiledTopics(topicInfo);
$('.topic-wrapper').append(template);
$('.listing-topics, .favorite-topic-title').click(function(e){
e.preventDefault();
if( $(this).hasClass("favorite-topic-title")) {
var heartClass = "favorited_heart_icon"
}
else if( $(this).hasClass("listing-topics")) {
var heartClass = "unfavorited_heart_icon";
$('html, body').animate({ scrollTop: 0 }, 'fast');
}
**console.log(this);**
$.ajax({
url: this,
dataType: "json",
type: 'GET',
success: function(result) {
var id = result.id;
var title = result.title;
var body = result.body;
var level = result.level
**console.log(level);**
//SHOW TOPIC and FAVTOPIC AS POPUP WHEN CLICKED
//Add proper favorite icon.
var favlink = '/topics/' + id + '/favorite';
**console.log(heartClass);**
var topicInfo = {title: title, body: body, heartClass: heartClass};
var template = compiled(topicInfo);
$('.topic-wrapper').append(template);
//CLOSE TOPIC WHEN CLICKING THE GREY SURROUNDING BOX - topicClose
$('.topicClose').click(function(e) {
$('.topicClose').css("display", "none");
$('.show_topic').css("display", "none");
})
//FAVORITE TOPIC
//ADD TO FAV TOPICS LIST
$(".unfavorited_heart_icon, .favorited_heart_icon").click(function(e) {
e.preventDefault();
//onclick - change colors of heart
if ( $(this).hasClass("favorited_heart_icon")) {
$(this).removeClass("favorited_heart_icon");
$(this).addClass("unfavorited_heart_icon");
urlEnd = '/unfavorite';
}
else if ( $(this). hasClass("unfavorited_heart_icon")) {
$(this).removeClass("unfavorited_heart_icon");
$(this).addClass("favorited_heart_icon");
urlEnd = '/favorite';
}
// console.log('/topics/favorite/' + id);
$.ajax({
url: '/topics/' + id + urlEnd,
type: 'POST',
success: function(result) {
location.reload();
}
})
});
},
error: function(err) {
console.log(err);
}
})
});
};
},
error: function(err) {
}
});
at the bottom of same js file:
var listingSource = $("#listingTopics").html();
var compiledTopics = Handlebars.compile(listingSource);
topics handlebar template:
<script id="listingTopics">
<div>
{{title}}
</div>
</script>
Thanks in advance!
EDIT**
I've also tried:
$.ajax({
url: '/topics',
dataType: 'json',
type: 'GET',
success: function(result) {
for(var i = 0; i < result.length; i++) {
var title = result[i].title;
var level = result[i].level;
var id = result[i].id;
var favlink = '/topics/' + id + '/favorite';
var link = '/topics/' + id;
var topicInfo = {title: title, link: link};
var template = compiledTopics(topicInfo);
$('.topic-wrapper').append(template).click(function(e) {
e.preventDefault();
console.log($(this))
});
};
},

I think a lot of the problems you are having with the assignment of multiple event listeners can be solved by taking those listeners out of the loops and defining them using the delegate strategy.
I would try something conceptually something similar to:
function getTopicJSON_Success(result){
console.log(result);
for(var i = 0; i < result.length; i++) {
var title = result[i].title;
var level = result[i].level;
var id = result[i].id;
var favlink = '/topics/' + id + '/favorite';
var link = '/topics/' + id;
var topicInfo = { title: title, link: link };
var template = compiledTopics(topicInfo);
$('.topic-wrapper').append(template);
}
}
function getJSON_Error(err){
console.log(err);
}
if(window.location.pathname === "/topics") {
$('.actions').click(function(e) {
console.log("submit");
});
$('.topic-wrapper').on("click", '.listing-topics, .favorite-topic-title', function(e){
e.preventDefault();
// =========================
// Note at this point "this" is the element that was clicked.
// in the ajax requrest below we will want to use $this.attr("href").
// =========================
console.log(this);
// =========================
var $this = $(this);
var heartClass;
if( $this.hasClass("favorite-topic-title") ) {
heartClass = "favorited_heart_icon"
} else if( $this.hasClass("listing-topics") ) {
heartClass = "unfavorited_heart_icon";
$("body").animate({ scrollTop: 0 }, 'fast');
}
// =========================
// Note: could be "null".
// Did you want one or the other specifically and not the posibility of null?
// =========================
console.log(heartClass);
// =========================
var getListJSON_Success = function(result){
var id = result.id;
var title = result.title;
var body = result.body;
var level = result.level
console.log(level);
//SHOW TOPIC and FAVTOPIC AS POPUP WHEN CLICKED
//Add proper favorite icon.
var favlink = '/topics/' + id + '/favorite';
var topicInfo = {title: title, body: body, heartClass: heartClass};
var template = compiled(topicInfo);
$('.topic-wrapper').append(template);
//CLOSE TOPIC WHEN CLICKING THE GREY SURROUNDING BOX - topicClose
$('.topicClose').click(function(e) {
$('.topicClose').css("display", "none");
$('.show_topic').css("display", "none");
});
//FAVORITE TOPIC
//ADD TO FAV TOPICS LIST
};
$.ajax({
url: $this.attr("href"),
dataType: "json",
type: 'GET',
success: getListJSON_Success,
error: getJSON_Error
})
});
$('.topic-wrapper').on("click", ".unfavorited_heart_icon, .favorited_heart_icon", function(e) {
e.preventDefault();
var $this = $(this);
var urlEnd;
if ( $this.hasClass("favorited_heart_icon") ) {
$this.removeClass("favorited_heart_icon");
$this.addClass("unfavorited_heart_icon");
urlEnd = '/unfavorite';
} else if ( $this. hasClass("unfavorited_heart_icon") ) {
$this.removeClass("unfavorited_heart_icon");
$this.addClass("favorited_heart_icon");
urlEnd = '/favorite';
}
$.ajax({
url: '/topics/' + $this.attr("id") + urlEnd,
type: 'POST',
success: function(result) { location.reload(); },
error: getJSON_Error
});
});
$.ajax({
url: '/topics',
dataType: 'json',
type: 'GET',
success: getTopicJSON_Success,
error: getJSON_Error
});
}

I'm guessing that results is roughly 20 items. When you're creating your click event handler within your for loop, your binding it to a classes .listing-topics, .favorite-topic-title. When you click on the element it goes ahead and fires the click events (20 times since you have 20 items in you results array). I suspect this is what is happening but need to see it to verify. Do you have a JSFiddle?
To fix this, change up the way you're binding your event handler. You need to scope it to a specific instance of a class or element in order for the events to fire individually instead of all at once.
SAMPLE SCENARIO
var results = ["1", "2", "3"];
//How you're currently doing it
for (var i = 0; i < results.length; i++) {
$('#container').append($('<div />', {text: results[i], class:'test-class'}));
$('.test-class').click(function () {
console.log($(this).text());
});
}
//Solution
for (var i = 0; i < results.length; i++) {
$('#container').append($('<div />', {text: results[i], class:'test-class'}).click(function () {
console.log($(this).text());
}));
}
I have created a simple reproduction of this scenario (aligning with yours) to help better explain what's happening. Basically, instaed of binding all your events within one go (by class), bind it to the element as you're creating it.
JSFIDDLE: https://jsfiddle.net/ncrxekmq/
UPDATED CODE
if(window.location.pathname === "/topics") {
$('.actions').click(function(e) {
console.log("submit");
})
$.ajax({
url: '/topics',
dataType: 'json',
type: 'GET',
success: function(result) {
console.log(result);
for(var i = 0; i < result.length; i++) {
var title = result[i].title;
var level = result[i].level;
var id = result[i].id;
var favlink = '/topics/' + id + '/favorite';
var link = '/topics/' + id;
var topicInfo = {title: title, link: link};
var template = compiledTopics(topicInfo);
$('.topic-wrapper').append(template);
//use $.each(index, item) to loop through all of your elements and bind the click event individually instead of in one go.
$('.listing-topics, .favorite-topic-title').each(function (index, item) {
$(item).click(function(e){
e.preventDefault();
if( $(this).hasClass("favorite-topic-title")) {
var heartClass = "favorited_heart_icon"
}
else if( $(this).hasClass("listing-topics")) {
var heartClass = "unfavorited_heart_icon";
$('html, body').animate({ scrollTop: 0 }, 'fast');
}
**console.log(this);**
$.ajax({
url: this,
dataType: "json",
type: 'GET',
success: function(result) {
var id = result.id;
var title = result.title;
var body = result.body;
var level = result.level
**console.log(level);**
//SHOW TOPIC and FAVTOPIC AS POPUP WHEN CLICKED
//Add proper favorite icon.
var favlink = '/topics/' + id + '/favorite';
**console.log(heartClass);**
var topicInfo = {title: title, body: body, heartClass: heartClass};
var template = compiled(topicInfo);
$('.topic-wrapper').append(template);
//CLOSE TOPIC WHEN CLICKING THE GREY SURROUNDING BOX - topicClose
$('.topicClose').click(function(e) {
$('.topicClose').css("display", "none");
$('.show_topic').css("display", "none");
})
//FAVORITE TOPIC
//ADD TO FAV TOPICS LIST
$(".unfavorited_heart_icon, .favorited_heart_icon").click(function(e) {
e.preventDefault();
//onclick - change colors of heart
if ( $(this).hasClass("favorited_heart_icon")) {
$(this).removeClass("favorited_heart_icon");
$(this).addClass("unfavorited_heart_icon");
urlEnd = '/unfavorite';
}
else if ( $(this). hasClass("unfavorited_heart_icon")) {
$(this).removeClass("unfavorited_heart_icon");
$(this).addClass("favorited_heart_icon");
urlEnd = '/favorite';
}
// console.log('/topics/favorite/' + id);
$.ajax({
url: '/topics/' + id + urlEnd,
type: 'POST',
success: function(result) {
location.reload();
}
})
});
},
error: function(err) {
console.log(err);
}
})
});
});
};
},
error: function(err) {
}
});

Related

ajax url directs me to .php?userid=undefined

When I click on the button, it redirects me to removeadmin.php?userid=undefined . My intended result was eg removeadmin.php?userid=0001 depending on which button the person has pressed. I have tried to change to window.location = "removeadmin.php?userid=" + arr[i].userid However, nothing seems to work.
(function () {
$(document).ready(function () {
showadmin();
});
function showadmin() {
var url = serverURL() + "/showadmin.php";
var userid = "userid";
var employeename = "employeename";
var role ="role";
var JSONObject = {
"userid": userid,
"employeename": employeename,
"role": role
};
var myJSON = JSON.stringify(JSONObject);
$.ajax({
url: url,
type: 'POST',
data: JSONObject,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (arr) {
_getAdminResult(arr);
},
error: function () {
alert("fail");
}
});
}
function _getAdminResult(arr) {
var gridcontainers = [];
for (var i = 0; i < arr.length; i++) {
var gridcontainer = $("<div />").addClass("grid-container");
gridcontainer.append($("<div />").text(arr[i].userid));
gridcontainer.append($("<div />").text(arr[i].employeename));
gridcontainer.append($("<div />").text(arr[i].role));
gridcontainer.append($("<div />").append(
$("<button />")
.on("click", BtnRemoveAdmin)
.text("Remove")
));
gridcontainers.push(gridcontainer);
}
$("#name").append(gridcontainers);
}
function BtnRemoveAdmin(event) {
var data = event.data;
removeadmin(event.data);
}
function removeadmin(userid) {
window.location = "removeadmin.php?userid=" + userid;
}
})();
simply event.data is undefined. Change _getAdminResult and BtnRemoveAdmin functions with this
function _getAdminResult(arr) {
var gridcontainers = [];
for (var i = 0; i < arr.length; i++) {
var gridcontainer = $("<div />").addClass("grid-container");
gridcontainer.append($("<div />").text(arr[i].userid));
gridcontainer.append($("<div />").text(arr[i].employeename));
gridcontainer.append($("<div />").text(arr[i].role));
gridcontainer.append($("<div />").append(
$("<button />")
.on("click", BtnRemoveAdmin)
.attr("data-userid", arr[i].userid)
.text("Remove")
));
gridcontainers.push(gridcontainer);
}
$("#name").append(gridcontainers);
}
function BtnRemoveAdmin() {
var data = $(this).attr("data-userid");
removeadmin(data);
}

jQuery bind not working on click

I have a strange problem, from the ones below only the first one works, i need to mention that both of them are in jQuery(document).ready(function(){});
There are no errors in the console.
This one works
jQuery('.delete_product_line').click(function(){
console.log('xxxxx2');
});
This one doesn't work
jQuery('body').on('click', '.delete_product_line', function(){ console.log('ccccc');});
This is the full example, i know it does not make any sense, also the #submitAddProduct works as it should.
jQuery(document).ready(function(){
jQuery('body').on('click', '#submitAddProduct', function(){
var interval;
var product_id = jQuery('#add_product_product_id').val();
var price_tax_excl = jQuery('#add_product_product_price_tax_excl').val();
var price_tax_incl = jQuery('#add_product_product_price_tax_incl').val();
var qty = jQuery('#add_product_product_quantity').val();
var id_combination = 0;
var initial_rows = jQuery('#orderProducts tbody tr').length;
var i = 0;
var rows = 0;
console.log(initial_rows);
if(jQuery('#add_product_product_attribute_id').length > 0)
id_combination = jQuery('#add_product_product_attribute_id').val();
interval = setInterval(function(){
if(i >= 5000)
{
clearInterval(interval);
interval = 0;
}
else
{
rows = jQuery('#orderProducts tbody tr').length;
if(rows > initial_rows)
{
i = 10000;
var response_z = $.ajax({ type: "POST",
url: aem_ajax,
cache: false,
data: { action: 'add_product_to_order', id_product: product_id, price_tax_excl: price_tax_excl, price_tax_incl:price_tax_incl, qty:qty, id_combination: id_combination, id_order: aem_id_order, id_employee: aem_id_employee, token: aem_token },
async: true,
success: function(data) {
}
}).responseText;
}
}
i = i + 100;
}, 100);
return false;
});
jQuery('.delete_product_line').click(function(){
console.log('xxxxx2');
});
jQuery(document).on('click', '.delete_product_line', function(){
console.log('xxxxx');
var parent = jQuery(this).closest('tr');
var id_order_detail = parent.find('.edit_product_id_order_detail').val();
var price_tax_excl = parent.find('.edit_product_price_tax_excl').val();
var price_tax_incl = parent.find('.edit_product_price_tax_incl').val();
var qty = parent.find('.edit_product_quantity').val();
var id_combination = 0;
var link = 'https://mytestsite.com/'+parent.find('a:eq(0)').attr('href');
var url = new URL(link);
var id_product = url.searchParams.get("id_product");
var response_z = $.ajax({ type: "POST",
url: aem_ajax,
cache: false,
data: { action: 'remove_product_from_order', id_order_detail: id_order_detail, id_order: aem_id_order, id_product: id_product, id_employee: aem_id_employee,qty: qty, price_tax_excl:price_tax_excl, price_tax_incl:price_tax_incl, token: aem_token },
async: true,
success: function(data) {
}
}).responseText;
return false;
});
});
Use document instead of 'body' in this case.
jQuery(document).ready(function() {
jQuery(document).on('click', '.delete_product_line', function(){
console.log('ccccc');
});
})

Iterate over array items and check property value

function GetViewModelData() {
var RDcViewModel = [];
var recordId = $.trim($("#recordId").val());
for (i = 1; i <= rowCount; i++) {
var item1 = $.trim($("#item1" + i).val()) == '' ? 0 : parseInt($("#item1" + i).val());
var item2 = $.trim($("#item2" + i).val()) == '' ? 0 : parseInt($("#item2" + i).val());
var GrandTotal = (item1 + item2);
var rdtCViewModel = new ItemDetailsViewModel(0, item1, item2, GrandTotal);
RDcViewModel.push(rdtCViewModel);
}
var obj = new ReportViewModel(recordId, RDcViewModel);
var viewmodel = JSON.stringify(obj);
return viewmodel;
}
I have the above sample function that i'm using to iterate over html table rows and storing the row values in an array.
Once i have my array populated, i'm using below code snippet to post the data to my controller.
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
//i want to check from here if viewmodel has any item(row) where GrandTotal is 0 (zero)
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function (data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function (e) {
return false;
}
});
});
}
What i now want to do in my PostData function is to check if my "viewmodel" object contains any item(row) where "GrandTotal" is 0.
using JSON.parse(viewmodel), prepare object of type ReportViewModel with RDcViewModel JS array of type ItemDetailsViewModel and iterate over it to find if any grandtotal == 0 for ItemDetailsViewModel instances
var viewmodel = GetViewModelData(),
var obj = JSON.parse(viewmodel);
var bFoundZero=false;
$.each(obj.RDcViewModelArray, function(idx, elem){
if( elem.GrandTotal === 0 ) bFoundZero=true;
})
if( bFoundZero ) return 0;
As you have stringified it, now you have to parse it back if you want to access its keys and values:
var PostData = function() {
$(".btnSubmit").click(function() {
var viewmodel = GetViewModelData(),
viewObj = JSON.parse(viewmodel),
flag = false; // <-----parse it back here
viewObj.forEach(function(i, el){
flag = el.GrandTotal === 0;
return flag;
});
if(flag){ return false; } // <------ and stop it here.
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function(data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function(e) {
return false;
}
});
});
}
There is no point iterating array again. Break the loop in GetViewModelData() and return false from that function. Then test it in PostData
Inside existing for loop:
var GrandTotal = (item1 + item2);
if(!GrandTotal){
return false;
}
Then in PostData()
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
if(viewmodel === false){
alert('Missing total');
return; //don't proceed
}
/* your ajax */

Check a range of pages and extract the <h1> content if the page exists using JQuery

There is a website like:
www.example.com/index.aspx?id=1
The id value is not ordered, maybe like 1, 32, 68, 61321, ...
How can I find out which pages exist and extract the content of the <h1> with jQuery?
I used following code in a loop, but no luck.
for (var i = 1; i <= 1000; i++) {
var URL = 'http://www.example.com/index.aspx?id=' + i.toString();
$.ajax({
url: URL,
type: 'GET',
success: function (res) {
var h = $(res.responseText).find('h1').text();
alert(h);
}
});
};
Try
$.when.apply($,
$.map(Array(1001), function(_, key) {
return $.get("http://www.example.com/index.aspx?id="
+ (key + 1)
, function(res, textStatus, jqxhr) {
var h = $(jqxhr.responseText).find("h1").text();
alert(h);
})
})
);

rendering list-images bbui from database mysql

I'm trying to make a list bbui image using ajax call in a mysql database, but in the process I do not get the same format as the image of bbui list, following my code
var idmember='glut1';
function dataOnLoad_initialLoad(element) {
var listItem, dataList = element.getElementById('dataList');
$.ajax({
type: "GET",
url: "ajax/history.php?id_member=" + idmember,
dataType: "json",
error: function(xhr, settings, exception) {
alert("error");
},
success: function(data){
$.each(data, function(key, val) {
listItem = document.createElement('div');
listItem.setAttribute('data-bb-type', 'item');
listItem.onclick = function() {
bb.pushScreen('detail.htm', 'detail');
};
listItem.setAttribute('data-bb-title', val.tglorder);
listItem.innerHTML = val.namastatus;
dataList.appendChild(listItem);
var order = val.idorder;
});
}
});
}
and then the code implemented in beforedetail.html like this code
<div id="dataList" data-bb-type="image-list" data-bb-images="none" data-bb-style="arrowlist">
</div>
I had a similar problem but my case was to generate an image list with a header to group items.
I did it the only way i know ho and it worked but am open to suggestions on how to do it better.
Here is the js code:
var listItem, header,
dataList = document.getElementById('dataList');// this is my list already in the DOM
var list = [];
var user = localDB.getScreenName();
$.ajax({
url: reg.api(),
data: {action: 'getAttire', formData: user},
type: 'post',
dataType: 'jsonp',
jsonp: false,
jsonpCallback: 'result',
beforeSend: function() {
document.getElementById('indicator').style.display = 'block';
},
complete: function() {
document.getElementById('indicator').style.display = 'none';
},
success: function(res) {
//showbList();
var title = [];
for (var i = 0; i < res.length; i++) {
if ($.inArray(res[i].item, title) === -1) {
title.push(res[i].item);//creates header array with unique values cos i had headers with duplicate names
}
// This creates header Array from the list
}
for (var k = 0; k < title.length; k++) {
header = document.createElement('div');
header.setAttribute('data-bb-type', 'header');
header.id = 'headers';
header.innerHTML = title[k];
header.style.background = '#f6f6f6';
header.style.fontSize = '20px';
header.style.fontWeight = 'bold';
// header.style.boxShadow = ''
list.push(header);//header created here
for (var i = 0; i < res.length; i++) {
if (header.innerHTML === 'Bag' && res[i].item === 'Bag') {
//var date =
listItem = document.createElement('div');
listItem.setAttribute('data-bb-type', 'item');
listItem.setAttribute('data-bb-img', res[i].img_link);
listItem.setAttribute('data-bb-title', res[i].name);
listItem.setAttribute('data-bb-accent-text', 'Added: '+jQuery.timeago(res[i].date));
listItem.setAttribute('dressup',res[i].DRESS_ID);
listItem.setAttribute('id','wardropeLink');
listItem.innerHTML = "Suited for: " + res[i].suited;
listItem.style.color = "#fff";
listItem.onclick = function() {
var selected = document.getElementById('wardropeLink').getTitle();
console.log(selected); // trying to get d title of a selected or clicked list but it returns the whole group. still working on it
};
list.push(listItem); //list item for a particular header created here
}
if (header.innerHTML === 'Trousers' && res[i].item === 'Trousers') {
listItem = document.createElement('div');
listItem.setAttribute('data-bb-type', 'item');
listItem.setAttribute('data-bb-img', res[i].img_link);
listItem.setAttribute('data-bb-title', res[i].name);
listItem.setAttribute('data-bb-accent-text', jQuery.timeago(res[i].date));
listItem.innerHTML = "Suited for: " + res[i].suited;
listItem.style.color = "#fff";
listItem.onclick = function() {
handleWardrope.listItems(res[i].DRESS_ID);
};
list.push(listItem);
}
}
}
var items = dataList.getItems();
if (items.length > 0) {
//list.insertItemBefore(item, items[0]);
} else {
dataList.refresh(list);//list added to DOM
if (bb.scroller) {
bb.scroller.refresh();
}
}
}
});
return false;
Hope this helps.
Warning and still trying to get the onclick function work for a particular list item but it seems to group them cos of the loop.
concerning the problem i had about getting the title of a list item
i solved it by calling the list selected function and then acted on the getTitle of the selected item.
code
listItem.onclick = function(){
var selected = document.getElementById('dataList').selected;
console.log(selected.getAttribute('dressup'));
}
what i did wrong before was i tried to get d selected item on d item itself and not on the imagelist.

Categories

Resources