AJAX Targeting individual anchor elements - javascript

I have a PHP-generated table of items. Each row has a link that, when clicked, should expand the row with additional information.
I've tried using JQuery to get the data and return it, which works - but only for the first row. Every link in each row returns data into the first row only. This is because this row has a static ID, which is what I'm targeting.
I thought about trying to assign a dynamic ID when PHP generates each row by dropping a variable in there, but I'd then need to have JQuery return the id of the parent td element whenever the link is clicked so that it targets that specific row, but I don't know how to go about this.
AJAX Function
$(document).ready(function() {
$("a.test").click(function(event) {
$.post("includes/modal.php", { id: event.target.id }, function(response) {
var ticket = document.createElement("p");
ticket.innerText = response;
document.getElementById('myDiv').appendChild(ticket);
});
$(document).ready(function(){
$("button").click(function(){
$('p').hide();
});
});
});
});
PHP Generated rows and columns
echo "
<tr>
<td>$dateChange</td>
<td>$ticketSubject</td>
<td id='myDiv'>
<a class='test' type='button' href='#' id=$ticketID>
View Ticket
</a>
<button>Hide</button>
</td>
<td>$ticketState</td>
</tr>";
I would like the user to click the link on each row and have that row expand with the new data returned by the JQuery.
I can envision this working if the getElementById() part could somehow pull the appropriate column id, which would be dynamically assigned, like so:
<td id=$postID>
I don't know if this would be the best way to go about this, but it's my current thinking. I don't know of any JQuery method that targets each unique instance clicked.

Modify your markup as:
echo "
<tr>
<td>$dateChange</td>
<td>$ticketSubject</td>
<td>
<a class='test' type='button' href='includes/modal.php?id=$ticketID'>
View Ticket
</a>
<button>Hide</button>
</td>
<td>$ticketState</td>
</tr>";
Here, I add href attribute with the link to required page. Also I removed id='myDiv' as id must be unique on the page.
In javascript you just do a POST-request to this href:
$(document).ready(function() {
$("a.test").click(function(event) {
// $(this) gives you the clicked element as jQuery object
$.post($(this).attr('href'), function(response) {
// according to your markup you can do:
$(this).parent().append('<p>' + response + '</p>');
// Instead of these lines below
/*var ticket = document.createElement("p");
ticket.innerText = response;
document.getElementById('myDiv').appendChild(ticket);*/
});
// return false to prevent default action on `a` click
return false;
// I don't know what you expect when put `ready` into `ready`
/*$(document).ready(function(){*/
$("button").click(function(){
$('p').hide();
});
/*});*/
});
});

You need to add unique number in your div id say $ticketID
echo "
<tr>
<td>$dateChange</td>
<td>$ticketSubject</td>
<td id='myDiv$ticketID'>
<a class='test' type='button' href='#' id=$ticketID>
View Ticket
</a>
<button>Hide</button>
</td>
<td>$ticketState</td>
</tr>";
And in your JQuery
$(document).ready(function() {
$("a.test").click(function(event) {
$.post("includes/modal.php", { id: event.target.id }, function(response) {
var ticket = document.createElement("p");
ticket.innerText = response;
document.getElementById('myDiv'+event.target.id).appendChild(ticket);
});
$(document).ready(function(){
$("button").click(function(){
$('p').hide();
});
});
});
});
Hope it helps!

Related

How to change the value in the input field while we click on dynamically created edit icons?

Here in the code there is ajax which assigning the values to the fields but there is the edit icon which is created dynamically it means that how many address you added in the database then number of times edit icon will be created. My need is that when I click on first button then it will alert its id value and when I clicked on the other one then it will alert its id value
Following is my code I tried:-
var full_url = document.URL; // Get current url
var url_array = full_url.split('=') // Split the string into an array with / as separator
var UserId = url_array[url_array.length-1]; // Get the last part of the array (-1)
$.ajax({
url:"url,
type: "GET",
dataType: 'json',
async: false,
data:{"UserId":UserId},
success: function(response){
if (response.response.total_record[0].status === "active") {
$('#email').html(response.response.total_record[0].email);
$('#name').html(response.response.total_record[0].first_name+" "+response.response.total_record[0].last_name);
$('#first').val(response.response.total_record[0].first_name);
$('#last').val(response.response.total_record[0].last_name);
$('#phone').val(response.response.total_record[0].phone_number);
$('#alternative').val(response.response.total_record[0].alternative_number);
$('#id').val(response.response.total_record[0]._id);
$('#status').val(response.response.total_record[0].status)
if (response.response.total_record[0].status === "active") {
$('#activate').hide();
}
if (response.response.total_record[0].status === "deactivate") { $('#activate').show();
$("#deactivate").hide();
}
$.each(response.response.total_record[0].address,function(i,item){
console.log(response.response.total_record[0].address[i])
$('#edit_id').val(response.response.total_record[0].address[i]._id)
$('.cards').append('<div class="location-list"><header class="header_title"><div class="location_heading"><h3>Location:</h3></div><div class="edit_icon"><a class="editByAnchor" id='+response.response.total_record[0].address[i]._id+' href="#" data-toggle="modal" data-target="#edit_address"><i class="fa fa-edit"></i></a></div></header><div id="dAddress" class="location-detial"><p><span id='+response.response.total_record[0].address[i]._id+'>'+response.response.total_record[0].address[i].address+'</span></p></div></div>');
});
}
}
});
Html
<input type="hidden" id = "edit_id" value= "">
Jquery for finding the clicked
$('.editByAnchor').change(function() {
alert("You just clicked checkbox with the name " + this.id)
});
Produces the output
<a class="editByAnchor" id="1" href="#" data-toggle="modal" data-target="#edit_address"><i class="fa fa-edit"></i></a>
/*more like this but id will be change base on the dynamically fields*/
The above output anchor tag having id attribute it will assigned dynamically as you see my code so how will I get the id attribute of each icon by clicking them.
For dynamically created element use on(). Also you have to use click event instead of change:
$('.editByAnchor').on('click', function() {
alert("You just clicked checkbox with the name " + this.id)
});
By taking the reference of this link I post a answer for this everything is alright I have to change my code by following
$(".editByAnchor").click(function(){
var id = this.id;
alert(id)
});

Get value from an attribute using JQuery

I have a table in my page that contains many rows, each row has an image which has an <a href> this <a href> has two attributes class and data-delete-id, so I have a multiple <a href> that has the same attributes and the same value for class.
each <a href> has a different value for the data-delete-id attribute.
In my JavaScript I have this code :
<script>
$(function() {
$('.deleteButton').confirmOn('click', function(e, confirmed){
// get jquery object access to the button
var $thisButton = $(this);
// this gets that data directly from the HTML
var id = $thisButton.data('delete-id');
if(confirmed) {
alert("<?php echo site_url('users/deleteUser')?>" + '/' + id);
}
});
});
</script>
So when I click on some <a href> that function well be fired, and it gets the id value from the data-delete-id attribute.
The problem is that id value it's always the value for the first <a href> in my HTML code.
I only want to get the value for the data-delete-id attribute for the clicked <a href>.
How can I do that ?
I checked the code for confirmOn here and it does not seem to register with each item in a set of selected elements. This is a bug with the plugin, but a workaround would be to wrap the whole thing in an each.
$(function() {
$('.deleteButton').each(function() {
$(this).confirmOn('click', function(e, confirmed){
// get jquery object access to the button
var $thisButton = $(this);
// this gets that data directly from the HTML
var id = $thisButton.data('delete-id');
if(confirmed) {
alert("<?php echo site_url('users/deleteUser')?>" + '/' + id);
}
});
});
});

Get values of div, check if the value is in td, if so, change class

I need to return a value(s) within a div, then check another div to see if the values exist. If they do, change the class of the link. The loop is working great. I need to now check the other field.
var cart = '';
$('.basic-cart-cart-node-title.cell').each(function (i, div) {
cart += ' ' + $(div).text();
});
if(cart != "")
{
//do something
}
I need to see if the value returned by cart is in a table value:
<td class="views-field views-field-title">
<a href="/accessory/oi-01">
<span class="assess-title">OI-01</span>
</a>
<p>
<a class="add-to-quote" href="/cart/add/3">Add to Quote</a>
</p>
</td>
If the values match, I need to change the class from "add-to-quote" to "added-to-quote". The example with for the td, is showing one of many that are on the page with various other numbers. I am trying to find only the one that matches the value returned by cart. Any thoughts???
Thanks!
Try with this code:
if(cart != "")
{
//Find all the "assess-title"s
$('.views-field.views-field-title > a > .assess-title').each(function (i, span) {
var $span = $(span);
if(cart.indexOf($span.html())!=-1){//The cart contains it?
$span.parent().next().find("a.add-to-quote").addClass("theClassToAdd").html("Added to Quote");
}
});
}
EDIT:
Here is a jsFiddle

Using Javascript or Jquery to dynamically create incrementing id for table as each row is created

I would like for a user to click an image in this table which is created dynamically based on the JSON data sent from the web service, and have the image change. When clicking the image again it will change back to the first image (inter-changing between only two images).
I have a table being created via jQuery's $.ajax() function which looks like this:
<table border="0" width=80% id="table">
<thead>
<tr>
<td><h3>Check to Renew</h3></td>
<td width=40%><h3>Vendor Part</h3></td>
<td width=100%><h3>Part Description</h3></td>
<td><h3>Unit Price</h3></td>
<td><h3>Quantity</h3></td>
</tr>
</thead>
<tbody>
<tr class="template">
<td><img src="images/checkmark.png" alt="check" id="row1" onclick=""></td>
<td>$vendorPart</td>
<td>$partDescription</td>
<td>$price</td>
<td><input class="quantityClass" name="quantity" value="$quantity"/></td>
</tr>
</tbody>
</table>
Here is the simple Javascript function which changes the images:
renewimg=Array("images/checkmark.png","images/gray_x.png");
function rowImageRefresh(y)
{
document.getElementById(y).src=renewimg[++m];
if (m==1)
{m=-1;}
}
This Javascript function work's beautifully, however only if I pass it the images id (in this case specific to the row). Hard coding for testing purposes proved this. My issue is I would like to be able to create a row id on the fly as the table row is created and then have functionality where that id can be passed.
I guess if I were to illustrate this more it would look something like this:
JavaScript: var row = 1;
HTML:
//table data
<td><img src="images/checkmark.png" alt="check" id="row+[i];i++;" onclick="rowImageRefresh(this.row.id)"></td>
//more table data
Where the id is created dynamically on the fly as each row is created and the onclick function passes the row of the image clicked.
You don't actually need an id at all. For example:
<img src="images/checkmark.png" alt="check" onclick="toggle(this)">
Then the script:
function toggle(element)
{
var sources = ["images/checkmark.png", "images/gray_x.png"],
current = $(element).data('state') || 0;
current = 1 - current;
$(element).data('state', current);
element.src = sources[current];
}
It toggles between the two states, remembering the current state using .data().
You could set individual row id's with id="x". Or, you could just use jQuery to find the index from where the click event occured and get the index of that part.
$('img.check').click(function(){
var id = $(this).index();
rowImageRefresh();
});
Here's one way you might assign an id to each image based on its row index:
$.each(rows, function(index, row) {
var data = $.extend({}, row, { id: "row" + index });
var $row = $(template(data));
$row.removeClass('template');
var $img = $('img', $row);
$img.on('click', function() {
var $this = $(this);
if ($this.data('checked') === true) {
var checked = $this.attr('src');
var unchecked = $this.data('src');
$this.attr('src', unchecked);
$this.data('src', checked);
$this.data('checked', false);
} else {
var unchecked = $this.attr('src');
var checked = $this.data('src');
$this.attr('src', checked);
$this.data('src', unchecked);
$this.data('checked', true);
}
});
$tbody.append($row);
});
The HTML for the image would look like this:
<img src="checked.png" alt="check" data-checked="true" data-src="unchecked.png" id="${ id }" />
Here's a working example: http://jsfiddle.net/potatosalad/MJYpA/1/
I used lodash.js for the template, but whatever you're doing to generate the row HTML should work the same.
Consider using a custom data attribute instead of trying to generate unique ids.
<img src="..." data-partid="$vendorPart" class="part-img" />
$(".part-img").on("click", function() {
var id = $(this).data("partid");
// or
var id = $(this).attr("data-partid").val();
rowImageRefresh(id);
});
Edit:
Seems like you are trying to toggle a checkbox image. A better way might be to change the background image using css and sprites. Then on click you swap the class depending on state.

How to write .trigger() code for the template?

I have a table below which contains a textbox and next to the textbox it contains a hyperlink known as "Open Grid". If the user clicks on this link, it opens up a grid and on this grid it displays number buttons from 3 - 26.
<table id="optionAndAnswer" class="optionAndAnswer">
<tr class="option">
<td>1. Option Type:</td>
<td>
<div class="box">
<input type="text" name="gridValues" class="gridTxt maxRow" id="mainGridTxt" readonly="readonly" />
<span href="#" class="showGrid" id="showGridId">[Open Grid]</span>
</div>
<table class="optionTypeTbl">
<tr>
<tr><td><input type="button" value="3" id="btn3" name="btn3Name" class="gridBtns gridBtnsOff">
<input type="button" value="4" id="btn4" name="btn4Name" class="gridBtns gridBtnsOff">
<input type="button" value="5" id="btn5" name="btn5Name" class="gridBtns gridBtnsOff">
<input type="button" value="6" id="btn6" name="btn6Name" class="gridBtns gridBtnsOff">
//...goes all the way to btn26
</tr>
</table>
</td>
</tr>
</table>
Now the code below is able to trigger one of the grid buttons to state that a grid button is clicked. This code is below:
$('#btn'+gridValues).trigger('click');
Now everything above is fine.
THE PROBLEM:
The issue I have is that a user can add a row containing the same template as the option control on top. But within this option and answer control, the user can change an option type if they wish by clicking on one of the grid buttons in this template. So my question is that how do I write the .trigger() to correctly point to a grid button within this template? If you look at the above code, it users the button's id, but if you look at code below which does the template, it doesn't contain an id, it simply just copies the option and control features from above into the template.
Below is the template:
function insertQuestion(form) {
var context = $('#optionAndAnswer');
var $tbody = $('#qandatbl > tbody');
var $tr = $("<tr class='optionAndAnswer' align='center'>");
var $options = $("<div class='option'>Option Type:<br/></div>");
var $questionType = '';
$('.gridTxt', context).each( function() {
var $this = $(this);
var $optionsText = $("<input type='text' class='gridTxtRow maxRow' readonly='readonly' />")
.attr('name',$this.attr('name')+"[]")
.attr('value',$this.val())
.appendTo( $options )
.after("<span href='#' class='showGrid'>[Open Grid]</span>");
$questionType = $this.val();
});
$td.append($options);
$tbody.append($tr);
}
UPDATE:
I have created a URL for this application here. Please follow the steps to use the application and then you can see what is happening:
Step 1: When you open application, you see a green plus button on the
page, click on it and it will display a modal window.
Step 2: In modal window there is a search bar, type in "AAA" and
submit search, you will see a bunch of rows appear.
Step 3: In the first row, you see under "Option Type" A-D, click on
the "Add" button within this row, the modal window will close and you
see in the grey textbox on right hand side that "Option Type" textbox
equals 4 and it displays the Answer buttons A,B,C and D, this is
because as you remember the option type for that row was "A-D".
Now this works fine but it only works for the top option and answer control, follow the steps below:
Step 4: Click on the "Add Question" button, it adds a row underneath
containing the details from the option and answer control on top.
Step 5: Within the row you have just added, you see a green plus
button on left hand side, click on this button and perform the same
search "AAA" in search box.
Step 6: This time select the last row by clicking on its "Add"
button, the "Option Type" for this row is "A-G" so it should display
"Answer" buttons A,B,C,D,E,F and G, but it doesn't do this, it still
states "A,B,C,D".
So how do I change the answer buttons display in the option and answer control within one of the appended rows?
The addwindow() function you see in the view source in the application is the function which occurs after the "Add" button is clicked on. The "Add" button is in an included PHP script and the code for this button is below and with it are all the columns you see after you have performed a search in the modal window:
echo "<table border='1' id='resulttbl'>
<tr>
<th class='questionth'>Question</th>
<th class='optiontypeth'>Option Type</th>
<th class='noofanswersth'>Number of <br/> Answers</th>
<th class='answerth'>Answer</th>
<th class='noofrepliesth'>Number of <br/> Replies</th>
<th class='noofmarksth'>Number of <br/> Marks</th>
</tr>";
foreach ($searchResults as $key=>$question) {
echo '<tr class="questiontd"><td>'.htmlspecialchars($question).'</td>';
echo '<td class="optiontypetd">'.htmlspecialchars($searchOption[$key]).'</td>';
echo '<td class="noofanswerstd">'.htmlspecialchars($searchNoofAnswers[$key]).'</td>';
echo '<td class="answertd">'.htmlspecialchars($searchAnswer[$key]).'</td>';
echo '<td class="noofrepliestd">'.htmlspecialchars($searchReply[$key]).'</td>';
echo '<td class="noofmarkstd">'.htmlspecialchars($searchMarks[$key]).'</td>';
echo "<td class='addtd'><button type='button' class='add' onclick=\"parent.addwindow('$question','$searchMarks[$key]','$searchNoofAnswers[$key]','$searchOption[$key]','$searchReply[$key]','$searchAnswer[$key]');\">Add</button></td></tr>";
}
echo "</table>";
I'm afraid I must be the bearer of bad news. The problem you are having stems from the overall design. Your HTML and javascript really need a bottom-up overhaul with the aim of getting all javascript into a single $(function(){...}) structure, and thus into the same scope. To achieve this you will need to :
Attach all event handlers in javascript in favour of the HTML attribute approach (currently hybrid).
Purge the iFrame in favour of fetching previous questions via AJAX.
In the process you will also purge some duplicate click handling (plus button img and its <a>...</a> wrapper).
Then, you can start to find a solution to your problem :
Delegate all event handling associated with the original "Option and answer" block to a container that is common to it and all future "Option and answer" blocks. The common container may be document but preferably something more specific. This appears to be partly achieved already.
Ensure that all internal referencing within the original "Option and answer" block works with classes rather than ids. .closest() and .find() will be useful here.
On clicking the "+" button, store a reference to the "Option and answer" block (eg. a jQuery object representing its container, discovered relatively). Easiest approach is to store this reference in a variable in the $(function(){...}) scope. (Now you are benefiting from making all those structural changes). The "Add" buttons' click handler will use this reference to affect the correct "Option and answer" block.
On "Add Question", use jQuery's .clone(true, true) to make a copy of the original block (then insert the clone into the DOM). If the other fixes have been applied, then all functionality (click handlers) will attach to the clone automatically.
I work quite quickly but it would still allow 1-2 days for this.
Here's how I would organise the javascript.
$(function() {
// **********
// Data area
// **********
var $$ = { // reusable static jQuery objects
'optionTypeTbl': $('#optionTypeTbl'),
'o_and_a_proto': $("#proto"),
'o_and_a_extras': $("#extras"),
'modal': $("#modal")
},
$o_and_a_section = null;
// ******************
// Utility functions
// ******************
function trim(str) {
return str.replace(/(^\s*)|(\s*$)/gi, "") // removes leading and trailing spaces
.replace(/[ ]{2,}/gi," ") // replaces multiple spaces with one space
.replace(/\n +/,"\n"); // Removes spaces after newlines
}
// ****************
// Initial actions
// ****************
$$.modal.hide();
$("input.gridBtns").removeClass("gridBtnsOn");
$("input.answerBtns").removeClass("answerBtnsOn");
$$.optionTypeTbl.hide();
// code above makes sure all buttons start in the OFF state (so all button are white).
// **********************************************
// Handlers for elements inside the main window
// **********************************************
$(document).on('click', function() {
$$.optionTypeTbl.fadeOut('slow');
});
$("input.gridBtns", $$.optionTypeTbl).on('click', function() {
var $this = $(this);
var $container = $this.closest('.optionAndAnswer');
$container.find(".gridBtns").removeClass("gridBtnsOn");
$this.addClass("gridBtnsOn");
$container.find(".gridTxt").val($this.val());
//$container.siblings('span[name=gridValues[]]').val($this.val()); // ???
$container.find('.answerBtns').each(function(index) {
if (index < Number($this.val())) {
$(this).show();
} else {
$(this).hide();
}
});
});
$$.o_and_a_proto.find(".showGrid").on('click', function(e) {
var $this = $(this);
var $container = $this.closest(".optionAndAnswer");
$("input.gridBtns").removeClass("gridBtnsOn");
var value = $container.find(".gridTxt").val();
//$("#btn" + value.replace(/\s/g, '')).addClass("gridBtnsOn"); //???
$$.optionTypeTbl.appendTo($this.closest("div.box")).show().css({
left: $this.position().left,
top: $this.position().top + 20
});
e.stopPropagation();
});
$$.o_and_a_proto.find(".plusimage").on('click', function() {
$o_and_a_section = $(this).closest(".optionAndAnswer");
$$.modal.modal();
});
$$.o_and_a_proto.find(".answerBtns").on('click', function() {
//btnclick(this); // ???
});
$("#addQuestionBtn").on('click', function insertQuestion() {
$$.optionTypeTbl.hide().appendTo(document);//ensure this itinerant table is not cloned
$$.o_and_a_extras.append($$.o_and_a_proto.clone(true,true).attr('id','')).find("span#plussignmsg").remove();
});
// **********************************************
// Handlers for elements inside the modal window
// **********************************************
$$.modal.find("#close").on('click', function() {
$.modal.close();
return false;
});
$$.modal.find("form").on('submit', function() {
var form = $(this).get(0);
$.ajax({
url: 'previousquestions.php',
data: {
'searchQuestion': 1,
'questioncontent': trim(form.questioncontent.value)
},
type: "get",
success: function(html) {
$("#searchResults").html(html);
},
error: function() {
alert("Something went wrong");
}
});
return false;
});
$$.modal.find("#searchResults").on('click', 'button.add', function() {
var $container = $(this).closest("tr");
var g = $container.find("optiontypetd").data('g');
var btn = $container.find("answertd").text();
$o_and_a_section.find("input.gridTxt").val(g);
if($o_and_a_section.closest("#detailsBlock").length) { //if is original Options and Answers section
//do something ???
//$('#btn'+g).trigger('click'); //???
}
$.modal.close();
});
});
This works to an extent, but please note that it requires associated changes to the HTML and CSS.

Categories

Resources