Javascript - Get text via ajax and display in a link - javascript

Use Case: I want to represent some text with ellipsis (e.g. My name is ...) in a HTML LINK/ anchor, where the text is fetched by an ajax call.
Whenever the user clicks the link, I load the text completely in a modal dialog box) by making the same ajax call used to fetch the text.
Here is the code:
"aoColumns": [
<Some code for columns>
{"mData": "id", sWidth:"180px","mRender": function ( data, type, full ) {
var obj = JSON.parse(JSON.stringify(full));
JSRoutes.com.app.controllers.File.getContent(obj["fileId"]).ajax({
data: {},
success: function(data) {
console.log("This is the data I want to represent in ellipsis: " + data);
}
});
return "<a>" + <HOW TO PUT CONTENT (data) HERE> +"</a>";
]
Problem: How to make the ajax call to fetch file content and provide the anchor element's text at the same time. Because by the time we 'return', the ajax call might not have finished.
I might not have been successful in explaining the question clearly, so comments and questions are welcome to improve the question.

Finally, I went with using the element id to modify the text later in the ajax function success callback.
As the file Ids are unique, I can provide unique HTML anchor ids.
"aoColumns": [
<Some code for columns>
{"mData": "id", sWidth:"180px","mRender": function ( data, type, full ) {
var obj = JSON.parse(JSON.stringify(full));
JSRoutes.com.app.controllers.File.getContent(obj["fileId"]).ajax({
data: {},
success: function(data) {
var linkText = "";
var n = 70;
if (data.length > n) {
linkText = data.substr(0,n) + " ...";
} else {
linkText = data;
}
$( '#file_'+obj["fileId"]).text(linkText);
}
});
return "<a> id=file_" + obj["fileId"] + ">" + "This will be loaded soon" +"</a>";
}
]

The first letter 'a' in 'ajax' stands for async, means you cannot get the result directly, but the result will be provided to your callback function later.
In your example:
JSRoutes....ajax({
success: function(data){
// async callback
}
});
This success function is which will be executed after the ajax returns.
So that you should return an empty <a> element first, and fill the content later in the callback.
example:
var a = document.createElement('a');
JSRoutes......ajax({
success: function(data){
a.textContent = data;
}
});
return a;

AJAX are asynchronous. so if you want to finish the some task first and calling the second function only after the completion of the first one than you have to write it in Javascript function instead of calling it in jQuery.

Related

AJAX query not always updating information consistently

I am experiecing some issues with AJAX updating the page. The actual data in the database is updated but this is not always reflecting in real time on the web page.
For example, I have the following event:
$("#add_note").click(function(e) {
//e.preventDefault();
$("#add_note_form").validate({
rules: {
contact_note: {
required: true
}
},
submitHandler: function(form) {
contact.modal_update({
'obj' : $('#add_note_form'),
'uri' : '/contact/add_note/'
});
}
});
});
This function when a new note is created calls a callback to validate the form fields first and then if successful calls a callback inside a seperate class to conduct the update. See the modal_update class below:
// Update modal
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url);
// Hide Modal
obj.closest('.modal').modal('hide');
// Refresh
this.refresh();
}
This then figures out the correct route to ajax and calls a ajax call back inside the same class:
// AJAX post
this.post_data = function(obj,uri)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
}
});
}
I am then running another class callback to "refresh" the data in all the elements on the page:
this.refresh = function()
{
// Refresh the ajax requests
this.get_contact_data();
this.get_notes();
this.get_contact_log();
this.get_contact_tasks();
}
This class re loads the functions which run on page load to get the inial data into the tables/fields on the page. See "get_notes" below:
// Get notes
this.get_notes = function()
{
// Get all notes and populate table
var log_uri = this.site_url + "/contact/get_notes/" + this.contact_id;
this.get_data(log_uri,function(data) {
notes = $("#contact_notes ul");
notes.empty("");
// Populate the contact fields, assuming there is a result to play with
if (data != false) {
//alert(JSON.stringify(data));
$("#notes-tab .count").html("(" + data.length + ")");
$.each( data, function( key, value ) {
notes.append("<li class='list-group-item' modal-id='editNoteModal' data-target='" + value.ID + "'><div class='row'><div class='col-lg-3'><i class='fa fa-sticky-note mr-3'></i>" + value.timestamp + "</div><div class='col-lg-7'>" + value.note + "</div><div class='col-lg-2'><a href='#' class='edit mr-3'><i class='fa fa-edit mr-1'></i>Edit</a><a href='#' class='delete'><i class='fa fa-times mr-1'></i>Remove</a></div></div></li>");
});
console.log('Notes loaded');
} else {
notes.append("<li>There are currently no notes for this contact</li>");
}
});
}
Now the problem:
For some reason this does not update consistently in real time. The data is updated fine on the server side but on the client side the update/refresh does not always update. I might add a note and get a correct update response but the refresh method seems to be receiving the old data and always be one note behind. So the next time I add a note, the one I added before then appears and so forth.
Another problem I am experiencing is the methods seem to stack on each event so if I add one note (or one of the other methods) I will see the console say "notes loaded" but on the second note it says "notes loaded" twice, then on the 3rd note added 3 times and so forth.
I am sure there must be something fatal flaw in the design of my code here but I am not experienced enough with javascript/jquery to notice what direction I am going wrong so I can fix it.
I thought that this was an issue with ajax caching and not refreshing the result so I have adjusted the ajax request as cache none and also to send no cache headers. I am running in wamp.
In your case, your refresh code will always run before your data got updated. Because ajax is asynchronous so the code behind and below ajax will always execute nearly the time your ajax running.
At the time you run your post_data function to call the API, the refresh function got run too. So it's done before your data got updated.
You should run refresh function inside ajax callback. For example:
this.post_data = function(obj,uri, callback)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
callback();
}
});
}
And in modal_update, you pass refresh function to post_data as a callback:
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url, this.refresh);
// Hide Modal
obj.closest('.modal').modal('hide');
}
You should read more about asynchronous ajax. You can use other tricky solution is setTimeout to run this.refresh but I do not recommend that because you not sure when the update is done.

JavaScript/Ajax -- document load, some controls not loaded

This is a little complicated, but let me try to sum-up. I have two sets of Javascript code that use AJAX and JSON (and PHP and ...) to get specific data and load a set of controls. In one case, called from a click event handler all the controls are loaded properly with the correct data, all is well. In the second, when the page first loads (called properly, the code does execute when the page loads and it does return values), unless I add an alert() dialog in the code, several controls do not actually get loaded. If the alert() is in the function, the controls are loaded. This is, to put it mildly, confusing.
The code that doesn't work is identical to the code that does. Here's the code called when the form loads:
function getFirstAward()
{
// this has to go get the first award at the top of the list
// (sort order) by rank and date, and return that to the entryfields:
var namecode = document.getElementById("namecode").value;
// now we need to set up the Ajax code to return just this specific
// award, and stuff it into the fields above ..
$.ajax
({
type: "POST",
url: "<?php echo $admin_html_RootPath; ?>lookups/returnFirstAward.php",
data: { 'namecode' : namecode },
dataType: "json", // return value is json array
//cache: false,
success: function(data)
{
// why is this necessary?
//alert( "First Award in List loaded" );
// first get the data array and break it up ...
document.getElementById("awardcode").value = data[0];
document.getElementById("currentaward").value = data[1];
getAwards();
document.getElementById("awardnumber").value = data[2];
document.getElementById("awarddate").value = data[3];
document.getElementById("eventname").value = data[4];
document.getElementById("region").value = data[5];
// Barony ... is it empty? If not, enable it, and set the value
if ( data[6] != "" )
{
document.getElementById("barony").disabled = false;
document.getElementById("barony").value = data[6];
}
else
{
// empty, enable, set value to empty, and disable it
document.getElementById("barony").disabled = false;
document.getElementById("barony").value = "";
document.getElementById("barony").disabled = true;
}
document.getElementById("royalcode").value = data[7];
// this one is necessary because of the way the code for getRoyals works:
document.getElementById("currentroyalcode").value = data[7];
getRoyals();
document.getElementById("notes").value = data[8];
tinymce.get('notes').setContent(data[8]);
document.getElementById("laurelprimary").value = data[9];
tinymce.get('laurelprimary').setContent(data[9]);
document.getElementById("laurelsecondary").value = data[10];
tinymce.get('laurelsecondary').setContent(data[10]);
// set focus on the currentaward entry:
document.getElementById("currentaward").focus();
}, // end success
error: function( xhr, textStatus, err )
{
//alert( data );
alert( xhr + "\n" + textStatus + "\n" + err );
} // end error
}); // end ajax call
} // end of function: getFirstAward
If I uncomment the alert() dialog, all the controls appear correctly. If not, the last four do not. I have tried reiterating that code to see if that helped (setting the value for the different controls, etc.) and it didn't make a difference. I tried using location.reload() and it didn't do any good (whether with the parameter or not: location.reload(true), makes no difference).
I think your code get executed before page loads completely and missed out few details/value needed for proper code execution. Try the following
setTimeout(function() {
getFirstAward();
}, 0); // try changing the duration from 0 to 100/500 whichever works for u.

Pass Ajax Variable value to html element in different page

How can I pass data from a query in php and set it's result using an ajax method.
Here is what I have so far in a file called file1.php:
<script type = "text/javascript">
function myAjax () {
$.ajax( { type : 'POST',
data : { },
url : 'query.php',
success: function ( data ) {
$doc = new DomDocument();
$doc->Load('file2.php');
$element = $doc->getElementById('resultFromFile1');
},
error: function ( xhr ) {
alert( "error" );
}
});
}
</script>
I wanna put the contents in this html element in the php file file2.php:
<p id ="resultFromFile1" name = "results">No Results</p>
Many stack overflow posts haven't been any help. Could someone point me in the right direction?
It's wrong approach.
You should rather create php script which will save your ajax request data in let's say database and then in file2.php load this data from DB, not directly update file
First of all what kind of content is query.php returning? Is it a JSON Object or are you just "echoing" the output as a string?
Next Question: Are you using jQuery, AngularJS or something in that direction?
Usually what you want to do is get the information from the "query.php" and pass it as a JSON formatted ajax result...
Now to your actual Problem: You want to get the element called "resultFromFile1" that's inside file2.php but you aren't adding anything to the "visible scope" yet since Load only loads the content but it doesn't add the content to any element you have to define an element holding your "file2.php". If i were you to avoid all these Problems i would use AngularJS for displaying your data in to a view and just include your "result" template via ng-include and let the ajax fill the document..
To solve your Problem:
<script type = "text/javascript">
// Your Solution
function myAjax () {
$.ajax( { type : 'POST',
data : { },
url : 'query.php',
success: function ( data ) {
$doc = new DomDocument();
$doc->Load('file2.php');
$element = $doc->getElementById('resultFromFile1');
},
error: function ( xhr ) {
alert( "error" );
}
});
}
// My Solution for this problem using native js
// Load the "file2" contents in to the file2Holder element
LoadUrlToElement('file2.php','file2Holder',function(data){
/* When the first loading of file2.php is done, load the results from the query.php and put it in to the element called "resultFromFile1" which we just loaded and placed in to the dom before. But i would recommend you to use AngularJS to avoid this Callback hell and get many cool features that webdevelopers don't want to miss these days.... */
LoadUrlToElement('query.php','resultFromFile1',function(){
alert('Content of resultFromFile1 is => '+document.getElementById('resultFromFile1'));
});
});
function LoadUrlToElement(url,elementID,done) {
$.ajax( { type : 'POST',
data : { },
url : url,
success: function ( data ) {
if(document.getElementById(elementID) === undefined){
alert("Can't proceed cause the content holder"+elementID+" is not found");
return; // Abort here cause there is no container with this id...
}
document.getElementById(elementID).html = data;
if(done !== undefined && typeof done === 'function') done(data);
},
error: function ( xhr ) {
alert( "error" );
}
});
}
</script>
<div id="file2Holder"></div>

Issue populating ajax response into a div

What am I missing? I've added the get element by Id and I'm definitely getting a response back, I checked using firebug and the response is correct. But I can't figure out why it won't populate my div area.
<script>
$(document).ready(function () {
$("#cmdSend").click(function () {
// Get he content from the input box
var mydata = document.getElementById("cmdInput").value;
$.ajax({
type: "POST",
url: "/Terminal/processCommand",
data: { cmd: mydata }, // pass the data to the method in the Terminal Contoller
success: function (data) {
//alert(data);
// we need to update the elements on the page
document.getElementById("terminal").value = document.getElementById("terminal").value + mydata;
document.getElementById("terminal").value = document.getElementById("terminal").value + data;
},
error: function (e) { alert(e); }
})
});
});
</script>
And the Div I want the response to be put in:
<div class="terminal" style="overflow:scroll">
<br>
</div>
First, you are calling document.getElementById(), but your div does not have an ID of terminal, it has a class called terminal.
Second, you are using jQuery but then switch back to classic JavaScript. You could update your code to the following:
success: function (data) {
//alert(data);
// we need to update the elements on the page
var existingHtml = $(".terminal").html();
$(".terminal").html(existingHtml + mydata + data);
}
Note that the $(".SomeName") selector is for selecting by class and $("#SomeName") is to select by id.
Edit and Note
If this terminal div could start to get a lot of data inside of it, you may look at using the .append() function in jQuery to prevent having to make a copy of the HTML and overwrite the HTML each time a request is made. The update would be something similar to the following (its a little shorter and should be more efficient as well)
success: function (data) {
//alert(data);
// we need to update the elements on the pag
$(".terminal").append(mydata + data);
}
If you want to get your element by id, add an id to the div:
<div id=terminal class="terminal" style="overflow:scroll">
<br>
</div>
If you want to change the contend of div not using jquery, you should use innerHTML instead of value.
document.getElementById("divID").innerHTML = document.getElementById("divID").innerHTML + data

Use the result of an ajax request as a variable

I would like to know how I can use the result of an ajax request as an "object". I'll try to explain. I have an ajax request that get a number, every 2 seconds, to an xml file. Then I render it into my html.
Here is my js:
var url = window.location.pathname.split('/');
var id = url[3];
setInterval(function() {
$.ajax({
type: "GET",
url: "http://myxml",
success: parseXml
});
}, 2000);
function parseXml(xml){
$(xml).find("user").each(function() {
if($(this).attr("id") === id ) {
$(".DubScore").html($(this).attr("count"))
}
});
}
and my html:
<div class="DubScore"> </div>
It works find, I have a count displayed to my page.
What I want to do, is to take this number and be able to do whatever I wan't with it in my html. For example, name it "Score", and be able to do "Score" + 2 , and things like that.
I hope my question is clear enough. Thank you for your help.
You can parse the attribute value and store it in a global variable :
var score;
function parseXml(xml){
$(xml).find("user").each(function() {
if($(this).attr("id") === id ) {
score = parseInt($(this).attr("count"), 10);
}
});
}
Afterwards, you may do, for example,
score += 2;
$(".DubScore").html(score);

Categories

Resources