ajax conditional var before posting - javascript

I have a like button. It shows on each item of an activity feed. I recently added the ability to like comments as well. Need some help adjusting the ajax to work with this. I currently grab the closest .feeditem and get the id, which is formatted to have the ID of the item.
The comments are showing in the same .feeditem div, so clicking like executes the same code, but does not save the right information. Is there a way to make it first check if one of the parent divs id starts with activity-comment- and if it does, have it select different divs, and if its not within that parent id, select the default (below)?
Or if you have a better way to implement this altogether please suggest. Newer to AJAX so this may not be the most effective way.
$likeButton.click(function (event) {
event.preventDefault();
var $itemClicked = $(this)
**//START SELECT**
var liking_user_id = $itemClicked.closest('.feeditem').attr('data-member').match(/\d+/);
var activity_id = $itemClicked.closest('.feeditem').attr('id').match(/\d+/);
**//END SELECT**
var data = {
'action': 'save_like',
'activity_id': activity_id,
'liking_user_id': liking_user_id
}
$.ajax({
type: 'post',
url: ms_user_actions.ajaxurl,
data: data,
success: function (response) {
if (!response.success) {
}
if (response.data.like == true) {
$itemClicked.siblings('.feedBox_Likes').text('You Like This!');
$itemClicked.html('Unlike').attr("like", "unlike");
}
if (response.data.unlike == true) {
$itemClicked.html('Like').attr("unlike", "like");
}
}
});
});

Having to make some assumptions here as there's no HTML in the question. In particular, I'm assuming that you want liking_user_id and activity_id in both cases, and that these two values are read from the relevant container nodes (divs) in the same way.
If those assumptions are valid, then the easiest approach is probably to devise another class name (eg. 'likeContainer') and apply it to the outer (feeditem) container and each of the inner comment containers. This class name will be additional to any existing class names, eg <div class="feeditem likeContainer">
The jQuery would then be as follows :
var liking_user_id = $itemClicked.closest('.likeContainer').attr('data-member').match(/\d+/);
var activity_id = $itemClicked.closest('.likeContainer').attr('id').match(/\d+/);
Thus,
when a comment's 'like' is clicked, .closest() will find an inner, comment container
when a non-comment's 'like' is clicked, .closest() will find an outer, feeditem container.
If the assumptions are not valid, then you might consider building the outer and inner divs differently. This might be the line of least resistance.

Related

Trying to use an id from the same page that my .click function was triggered on, in an ajax function

newbie to coldfusion/jquery/programming general here. So the overview of my problem is this: I have a ticket id that corresponds with a specific row in my database. When I click a button, I would like one of the columns in that row to change values to "In Testing". My issue is that I do not know how to pull that ticket id number into my jquery function, or if this is even possible. My code:
<script src="/TicketFaster/js/jquery-1.11.3.js"></script>
<script src="/TicketFaster/js/scripts.js"></script>
<cfset ticketid="#ticketid#">
<button id="in_testing" type="button">In Testing</button>
my js:
$(document).ready(function() {
$("#in_testing").click(function() {
var x = (#ticketid#);
$.ajax({
url: 'ticketcomponent.cfc?method=in_testing',
type: 'POST',
data: {
test: x
}
});
});
});
The big problem is that these pages are being generated dynamically, so each one will have a different ticket id. Therefore, I need to have the ticket id variable be imported rather than just hard coded in to the jquery function. So is this possible? I did not include the query because it works fine when I use it in other places, just getting the data delivered is the tough part. I appreciate any help you can give me :)
Edit: I was requested to post what I'm trying right now.
The original coldfusion is the same so I'm not going to post that again. Here is the js I'm using:
$(document).ready(function() {
$("#in_testing").click(function() {
var x = (<cfoutput>#ticketid#</cfoutput>);
alert(x);
});
});
(I also tried without the cfoutput tags)
As you can see, I'm just trying to do a simple alert to check if my variable has been correctly set. Once I get that to work, then the ajax should follow fairly quickly because I have some experience in that.
What is your specific issue?, can you share a jsfiddle?
for dynamic events replace
$("#in_testing").click(function() {});
for
$(document).on('click','#in_testing', function() {});
This value
var x = (#ticketid#);
in jquery is some like that
var x = $('#ticketid').val(); // for value or $('#ticketid') for object
you just have to take account id created dynamically

Dynamic table onclick

I have the following issue i would like to get some help for.
There is a combobox (select) where i choose an item and i get back a dinamic table from php. The table contains example names. Firstname, Lastname and ID(which is hidden). When i click on the table i get the value of the ID of the selected row. So far it is works fine. The problem that the event doesnt want to fire for first. After that it works fine but i need it for first as i have a function which auto click on the first row but this doesnt work until i solve this problem. I made a code which works fine with a html table. But not with the dinamic one. Please help.
Here is the code works fine with dinamic table but just after 2nd click:
function nametableclick() {
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data=(this.cells[3].innerHTML);
var data = data;
$.ajax({
type: "POST",
url: "list.php",
data: "data="+data,
Type: "json",
success: function(msg) {
msg = JSON.parse(msg);
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
}
});
};
};
};
And here is the code works well but just with html table:
(Actually is same but i use onload)
onload = function() {
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data=(this.cells[3].innerHTML);
var data = data;
$.ajax({
type: "POST",
url: "list.php",
data: "data="+data,
Type: "json",
success: function(msg) {
msg = JSON.parse(msg);
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
}
});
};
};
$("#nametable tr:eq(0) td:first-child").click();
};
When i use the onload function for the dinamic table it just doesnt work at all.
Thanks for any help in advance.
This question does not suit well for an answer. Instead, I'll do some code analysis.
onload = function() ... - well not terrible but kinda sloppy. Also looks like this is possible a global namespace leak. I'm going to assume this should be window.onload in which case I'd wonder why jQuery's ready event isn't used $(function() { ... }).
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++) {
rows[i].onclick = function() { ... };
}
Ok now were again running away from jQuery as if it was diseased some how. And then were looping over the array of rows only to construct a new function each time and attach them to the onclick (again avoiding jQuery)? Constructing functions inside a loop is a very bad idea and most linters will complain loudly about that. A suggestion:
$('#nametable tr').on('click', function() { ... });
This will attach the click handler to all the <TR> rows in the table with the id="nametable" attribute.
data=(this.cells[3].innerHTML);
var data = data;
My heart skipped a beat here!. First your pulling out the HTML content into (what I thought was a global variable) until I saw the next line and realized we have variable hoisting. But wait your assigning data to itself. Lastly, the name data doesn't provide any context as to the content of the innerHTML. Since I don't have the data I could only guess so in these examples I'll leave it as data. In the future think about picking names which provide context to their content and use. That way when you read the code you don't have to hunt for what the variables are for or how to use them.
var data = $(this, 'td:eq(3)').text();
Finally, the use of data is to directly concatenate it into a post request. I would assume HTML is not desired in that server API. Not to mention the avoidance of jQuery's parameter building by forcing the data to a string. Instead use a JS object:
$.ajax({
type: 'POST',
url: 'list.php',
data: {data: data} // This is a very poorly designed server API
}).then(function(data) {
...
});
Also, the use of Type: 'json' suggests that your server is not returning proper HTTP headers. First off there is no Type property for jQuery's ajax instead I think you wanted dataType. However the need for a dataType suggests the server is not sending the proper headers. If the PHP script were to return application/json instead of plain/text then jQuery could parse the response for you avoiding the need for JSON.parse on your own which can be a bit error prone.
$("#dob").html(msg.dob);
$("#age").html(msg.age);
$("#sex").html(msg.sex);
Be warned by using html() your directly injecting HTML into the DOM that you received from a third party. This is a big cross site scripting vulnerability. Use text() instead to push data into the DOM unless you know and can assert the trust of your server and the connection to it (SSL to avoid man in the middle). Probably not important for this example but still worth keeping in mind because it's far to easy to have this show up in the wild.
$("#nametable tr:eq(0) td:first-child")
When you have a selector like this it is far easier and readable to instead provide contextual hooks instead of relying on the make up of the DOM. Add things like class="clickable-row" or class="person-data dob" to your HTML markup. It makes for maintenance and readability.
Thanks for the quick reply. Im sure if there are lot of mistakes as i just started to learn this(i mean php html ajax ect.) a few weeks ago so i dont clearly understand everything and i use things i should not use or should do it another way. But there is a simple program i would like to make it done and learn from that. So when i dont know something im trying to get some info (like: w3schools.com) or check other topics which similar what im looking for.
Sorry i left there the
Var data = data;
My mistake. Dont need there. i was trying out something before and left there. Does not make any different anyway.
next:
The onload = function() {
i found in another topic as solved result and it works with a static table but not with dynamic.
I have tried the following. i did not mentioned:
window.onload = nametableclick;
function nametableclick() {
data here
}
But does not work with dynamic table either.
Next:
var rows = document.getElementById("nametable").rows;
for(var i = 0; i < rows.length; i++)
{
rows[i].onclick = function()
{
data2=(this.cells[3].innerHTML);
What it does for me it finds the selected row and comes back with the value of the 3rd(actually 4th) cell which is the ID in my prog. I need this cos i want to sent this value to the php to get all the data from the table where ID = the value. And it works fine.
As i mentioned the prog works fine even if it is not the best way to do it. Slowly i gonna learn how to do it better way. But at the moment the only problem with that is that the dynamic table onclick event fires only after the 1st click.
Thanks and sorry if im a bit hard case. :-)))
Oh 1 more thing:
"First off there is no Type property for jQuery's ajax instead I think you wanted dataType."
For some reason if i type dataType it just does not work at all. I have no idea why. I watched some training videos and read some short courses about ajax and some of them mentioned using dataType some of them just simple type. I followed everything but did not worked for me. i spent like 5 hours another day to find out why actually i have a topics here with that question as well.
get data from mysql with ajax and json into different textareas
And accidently i tried with uppercase T once and it worked. Have no idea why.

Appending new results to an open jQuery autocomplete menu

I have an app in which I have multiple search sources. Previously, the users had to choose in what source to search in before searching. If they did not choose, the app would default to one of the options.
However, now they want to search in all the sources at the same time. This is fine enough, but the problem is that when one of the searches returns, it overwrites the previous search result. Pretty much expected behavior. What I basically want is to append the new results to the already open autocomplete menu, instead of overwriting the old results. Naturally, the autocomplete menu would have to empty when it closes.
I guess that this is possible to do, but what approach is the best? I could just have an array I guess, which I append results to and then overwrite _renderMenu to use this array instead of the items one that is passed to the function. Then empty said array at the close event.
Is this the best way to go though? Or is there a more elegant solution?
Some code:
Ok, so searchAction is called by jquery autocomplete eventually. In collection.search I do the ajax call, here the URL is created based in the this parameter, then respondWhithData is called and maps the search result to a proper format (ie value and label for the autocomplete menu). After reponse is called from respondWithData, jquery automagically renders the resultsmenu. Thus, I probably have to overwrite the reponse event function as well as the _renderMenu and possibly _renderItem, yes?
searchAction: function(searchTerm, collection, response){
var self = this;
$.when(collection.search(searchTerm, this)).then(function(data) {
self.respondWithData(data, response);
});
},
respondWithData : function(data, response) {
if (data.length > 0) {
var responseVal = _.map(data, this.mapData);
this.checkResponseCount(responseVal);
response(responseVal);
}
else {
response(this.emptyResult());
}
},
To be clear, the problem is not the multiple search itself, but rendering the asynchronos results. I want to render the first results that come back, and then appends the rest as soon as they are returned from the server.
Edit 2:
Just tried to edit ui.content in the autocompleteresponse event, but any edit does not take once it renders for some reason...
Edit 3: Ah, ui.content can only be modified directly, not changed. If I push every single change instead of concating two arrays ui.content shows what I want.
It works I guess, but its not perfect.
I can figure how looks your scenario but I'm guessing:
You should have like:
function search1() {
$.ajax({ ...
success: function(data) {
$('#myResultsDiv").html(data)
}
});
}
etc
Instead of overwritting the #myResultsDiv you need to Append the results like:
function search1() {
$.ajax({ ...
success: function(data) {
$('#myResultsDiv").append(data)
}
});
}
Edit: You can also do something like this:
var resultsArray = [];
var searchDone = 0;
var totalSearchs = 5; //assuming 5 searches
function search1() {
function search1() {
$.ajax({ ...
success: function(data) {
//APPEND data to resultsArray
searchDone++;
if(searchDone==totalSearch) //syncronize the 5 searchs before render
renderSearchs(resultsArray);
}
});
}

How can I select a DOM element that was created by another event?

The first click event sends an API call that returns several search results.
The second click event should occur when clicks 'upvote', which is an option in each returned search result.
Problem is, it seems that I can't select upvote buttons in search results because they were created (via cloning another element) after the first click event.
Can anyone explain why this happens?
Part of the first click event:
success: function(json) {
var reviews = json.reviews;
$.each(reviews, function(i) {
var critic = reviews[i].critic;
var quote = reviews[i].quote;
var score = reviews[i].original_score;
$('#tile-demo').clone().removeAttr('id').removeClass('hidden')
.find('.critic-name').text(critic).end()
.find('.critic-score').text(score).end()
.find('.critic-quote').text(quote).end()
.appendTo('.review-grid');
}); //end each loop
} //end success call
the new call, which should select a clone of #tile-demo:
$('.search-results').click(function(){
var goodCritic = $(this).siblings('.critic-name').text();
console.log(goodCritic);
});
Use On method as the following:
$('#containerId').on('click','upvotebuttons',function(){write your code here});
where containerId is the id of the container div where you render new data, and replace [upvotebuttons] with [class name] of the upvote buttons.
I just came across a quick screencast by Jeffrey Way that suggests a slightly different solution. The other answer works fine--this is just another way to go about it (still uses event delegation).
$('#parent-of-target').click(function(e) {
if ( $(e.target).is('#target-element') ) {
alert('clicked');
}
});

Finding the element after an ajax event

I'm working on a site that allows users to love an item (like an item). The event is handled with jQuery and AJAX. The item array holds quite a lot of items and each item has a button to 'love'. I decided to efficiently reduce the number of forms on the page by putting one form at the bottom of the page and just submit it remotely.
So every time a user clicks the love button, the data attribute that holds the item id is put into the form and the form is submitted. Simple stuff.
But I'm finding the data response a bit more complex because I don't know how to find the element id of the item I want to update. I can't just use this or event.target because its inside a different event. I've also tried to carry the event parameter into the submit event, but it didn't work.
$(".love_item").click (event) ->
$(".love_item_item_id").val $(this).data 'id'
$(".love_item_form").submit()
$(this).hide(200)
$("form.love_item_form").submit (evt) ->
evt.preventDefault()
$form = $ #
$form.find(':submit').prop 'disabled', true
$.post($form.attr('action'), $form.serializeArray(), type: 'json').done (data) ->
$(event.target).parent().find(".item_info_box").html data
The last line, where it says event.target is as far as I've got. Its obvious that this variable is not carried, but I don't really know what to place there to achieve my goal. Also, I know that I could pass additional parameters through the form action (in other words send them to the rails controller and back), but I'd rather not. Any ideas?
You don't need an abitrary form at all. Something like this would work:
Example Markup (notice the data attribute):
Item to like
jQuery:
$('a.likeable').on('click', function() {
var $item = $(this);
var id = $item.data('id');
$.post('url/like/' + id, function() {
// success
// do something with $item here.
});
});
If you have an element like this: <div id="foo" data-id="foo1234">Foo</div>
You can select it after your ajax post like this, assuming you still have the ID of foo1234:
$('[data-id="' + id + '"]').doSomething();
Just use jQuery's ajax functionality
$('.love_item').on('click', function(e) {
$.ajax({
type: 'POST',
url: *insert url here*,
data: 'id=' + e.currentTarget.data-id,
success: function(response) {
var element = e.currentTarget;
// do whatever
}
})
});

Categories