I'm building a random quote generator web app, and I'm able to call an API using JQuery, then use the returned JSON data to print out a quote. I've implemented a button to attempt to call the API for another quote, and which calls the getJSON function, but doesn't get new JSON data.
The full code is on CodePen: http://codepen.io/oscarwong67/pen/eZLQLz
Here's what I use to get the Quote:
var getQuote = function() {
$.getJSON("http://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1" + "?callback?", function(json) {
console.log(json);
$("#quote").html(json[0].content);
$("#speaker").html("- " + json[0].title);
});
}
getQuote(); //called when the page initially loads
$("#new-quote").on("click", function() {
getQuote();
});
And here's the relevant HTML that it changes:
<div class="col-xs-12 col-sm-8 col-md-6 text-center" id="quote-div">
<p id="quote">Loading Your Quote</p>
<p id="speaker"></p>
<button class="btn btn-default btn-block" id="new-quote">New Quote!</button>
</div>
The function is called when the page initially loads, and will call on the button click, but the JSON returned DOES NOT change.
$.getJSON has an issue with caching. You need to set the cache: false. Just do that and you code works fine.
To set cache:false there are a number of ways. Two possible ways are:
$(document).ready(function() {
$.ajaxSetup({ cache: false });
});
and
$.ajaxSetup({ cache: true});
$.getJSON("/url",function(data,item) {
// do stuff with callback data
$.ajaxSetup({ cache: false});
});
Your final JS:
var getQuote = function() {
$.getJSON("http://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1" + "?callback?", function(json) {
console.log(json);
$("#quote").html(json[0].content);
$("#speaker").html("- " + json[0].title);
$("#speaker").css('text-align', "right");
$("#speaker").css('padding-right', "2%");
$("#speaker").css('font-size', "16pt");
$("#speaker").css('font-weight', "bold");
$.ajaxSetup({ cache: false });
});
}
Codepen
Related
I'm trying to understand how the Jquery Ajax methods works. Right now, I have some problems calling the ActionResult method in the controller that will return a PartialView.
Have created an button which I will use to get new data in from the server (Ajax call should run)
Code: (ActionResult in Home controller)
public ActionResult All()
{
List<Student> model = db.Students.ToList();
return PartialView("_Student", model);
}
This method is the one I'm trying to call when I press the button in the main Index view.
Code: (Index view)
<div class="row">
<div class="small-12 column sbw-travel">
<h2>Travel</h2>
<div class="row">
<div class="small-12 columns">
<button id="button1" class="sbw-travel-button">Search</button>
</div>
</div>
<div class="small-12 sbw-travel-box" id="rooms">
</div>
</div>
</div>
When the user hit the button, an Ajax call should run, and the list will appear in the section with id=rooms.
Script: (Ajax code)
$(document).ready(function () {
$('#button1').click(function () {
$.ajax({
type: 'GET',
url: #Url.Action("All", "Home"),
datatype: "html",
success: function () {
$('#rooms').html(???);
}
});
return false;
});
});
Can any of you see if I have forgot something to make this run like I have described?
The result is on the succes event. Try:
$(document).ready(function () {
$('#button1').click(function () {
$.ajax({
type: 'GET',
url: #Url.Action("All", "Home"),
datatype: "html",
success: function (data) {
$('#rooms').html(data);
}
});
return false;
}); });
I would suggest loading firebug when you click the button (enable the console), make sure the requested URI is responding with valid HTML data on the click event.
I also generally find using something like:
$('#button1').on('click', function () { ...
usually yields better results, see here: Difference between .on('click') vs .click()
Below is my code..
HTML Code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="body">
<div class="dropdown_div">
<select id="q_type" class="dropdown" onchange="getSubject(this.value)">
<option>Question1</option>
<option>Question2</option>
</select>
</div>
<div class="dropdown_div">
<select id="q_subject" class="dropdown">
<option>Subject1</option>
</select>
</div>
</div>
JS Code
function getSubject(val){
$("option", $("#q_subject")).remove();
var option = "<option>Subject</option>";
$("#q_subject").append(option);
$.ajax({
url: "api.path",
type: 'POST',
dataType: 'json',
data: {id: id},
async: true,
cache: false,
success: function(response) {
alert("Hi");
$("option", $("#q_subject")).remove();
var option = "<option>Subject1</option>";
option += "<option value=1234>Subject2</option>";
$("#q_subject").append(option);
}
});
}
How do I use pushState into my code and let user can click back button to return last page and then still see the ajax data?
First of all, you should save data received from ajax request to browser local storage. Afterwards, in order to show ajax result when browser "back" button was fired, you should bind statements that you are calling in ajax.success() method to window onpopstate event. To omit code duplication, it`s better to use a declared function instead of anonymous one.
function success(response) {
alert("Hi");
$("option", $("#q_subject")).remove();
var option = "<option>Subject1</option>";
option += "<option value=1234>Subject2</option>";
$("#q_subject").append(option);
}
Save data to localstorage and call success function:
$.ajax({
url: "api.path",
type: 'POST',
dataType: 'json',
data: {id: id},
async: true,
cache: false,
success: function(response) {
localStorage.setItem("response", response);
success(response);
}
});
Call success() when "back" button was fired:
window.onpopstate = function (e) {
var res = localStorage.getItem('response');
success(res);
}
I would rather suggest you to use sessionStorage which expires when the browser window is closed :)
$.ajax({
url: "api.path",
type: 'POST',
dataType: 'json',
data: {id: id},
async: true,
cache: false,
success: function(response) {
sessionStorage.setItem("DataSaved", response);
success(response);
}
});
And then
window.onpopstate = function (e) {
var res = sessionStorage.getItem('DataSaved');
success(res);
}
You can solve this using the local Storage or Session storage. You will also need to have a onload function callback, to check if there are any previous values that you stored in the local/session storage, if yes, then show that data in the select box.
I noticed this Back() issue when using Ajax to navigate an MVC-5 application from within a JavaScript generated diagram. All clicks in the diagram are handled by Ajax.
Above solutions do not replace the complete body, in the repaired cases a Back() would restore just the edit fields. In my case, I don't need that. I need to replace the entire page from the AJAX and also enable the Back button to return to my original diagram context.
I tried above solution to replace body, and I have to note, it would only trigger the window.pop event after
history.pushState({}, '')
But when the event triggered and it uses Ajax to fill the body, my Javascript would not properly re-initialize the diagram page.
I decided to use another pattern, to circumvent the the window.pop event and avoid the back-issue. Below code will not return into the Ajax code context, but instead simply replace current page, processing the Ajax return information from the server (=Controller) as a redirect link, like
var url = "/ProcessDiagram/MenuClick?command=" + idmenuparent+"_"+citem; // my Ajax
$.get(url,
function (data) {
window.location = data; // Server returns a link, go for it !
return true; // Just return true after going to the link
});
.. this will preserve the Back() context, because the browser will take care of things.
Controller side composes the redirect link, like
public ActionResult MenuClick(string command)
{
List<string> sl = command.Split(new char[] {'_'}).ToList();
var prId = int.Parse(sl[0].Substring(3));
if (sl[1] == "PU")
return Content("/ProductionUnitTypes/Details/" + UnitContextId(prId) );
if (sl[1] == "IR")
return Content("/ItemRoles/Details/" + RoleContextId(prId) );
// etcetera
}
I solved it by including the below code just before the $.get() function
$.ajaxSetup({cache: false});
It works! Try it :)
i have a several html buttons (not within a form).
When clicked they call a JavaScript function that after conformation, runs an ajax call.
This part all works OK, but i would then like to change the class of whichever button was clicked on success of the ajax call.
i have tried various methods seen on stackOverflow, but none of them seem to work...
can i please ask what am i doing wrong?
here is the simplified HTML (buttons)
<button class="btn btn-primary" onclick="primaryImage(4107,19372,'/abbie1.jpg'); return false;">
set as profile image
</button>
<button class="btn btn-primary" onclick="primaryImage(4107,19373,'/abbie2.jpg'); return false;">
set as profile image
</button>
<button class="btn btn-success" onclick="primaryImage(4107,19374,'/abbie3.jpg'); return false;" disabled="disabled">
profile image
</button>
Please note: the last button is already the active/success button, and i would also like to remove the class on success too (as only one should be active), but that is maybe my next stage....
here is the javaScript, (i have left in some of the methods i have tried, but commented them out)
function primaryImage(eid,pid)
{
if (confirm("Are you sure you wish to use this as your profile image?"))
{
$.ajax({
type: "POST",
async: false,
cache: false,
dataType: "json",
url: "ajax_photo.php",
data: "action=primary&eid="+eid+"&pid="+pid,
//context: this,
success: function(data){
if(data.result=='success')
{
alert('The image is now set as the profile image');
//$('button').click(function(){
// $(this).addClass('btn-success');
//});
//$('button').on(data.result=='success', function(e) {
// $(this).toggleClass("btn btn-success"); //you can list several class names
// e.preventDefault();
//});
//$(this).removeClass('btn-primary').addClass('btn-success');
}
else
{
alert('An error occurred when trying to set the image: ' + data.result);
}
}
});
}
}
I would be very grateful for any advice of what i am doing wrong
(as you can see, i am not too good with JS (yet))
Thanks!
Ford
As noted in your commented out code, you are binding the click event after click event has already been fired.
I would suggest you to pass a reference of the button that was clicked in the primaryImage() function itself as such:
<!-- In your HTML -->
<button class="btn btn-success" onclick="primaryImage(this, 4107,19374,'/abbie3.jpg'); return false;" disabled="disabled">
profile image
</button>
function primaryImage(button, eid,pid){
/** ... */
Then using that referenced button, you can add or remove CSS classes to the element, as well as the siblings of the element (using jQuery's siblings() method).
//your ajax call
success: function(data){
if(data.result=='success') //make sure this really is success
{
alert('The image is now set as the profile image');
$(button).removeClass('btn-primary').addClass('btn-success');
$(button).siblings('button').removeClass('btn-success').addClass('btn-primary');
}
}
As you don't use the jQuery .click() event, I think you need to pass the button in your function args.
So your button will look like
<button class="btn btn-primary" onclick="primaryImage(this, 4107,19373,'/abbie2.jpg'); return false;">
set as profile image
</button>
Then your function will be like
function primaryImage(el, eid,pid)
{
if (confirm("Are you sure you wish to use this as your profile image?"))
{
$.ajax({
type: "POST",
async: false,
cache: false,
dataType: "json",
url: "http://anzvirtuel.org",
data: "action=primary&eid="+eid+"&pid="+pid,
//context: this,
success: function(data){
if(data.result=='success')
{
$(el).addClass('btn-success');
alert('The image is now set as the profile image');
// keep doing whatever you want...
}
else
{
alert('An error occurred when trying to set the image: ' + data.result);
}
}
});
}
}
As I have not fully understood your commented JS I'll let you put the code you want, just remember that your button will be accessible in jQuery with $(el).
Hope it may helps you
You should pass the clicked element to the primaryImage() function, and use it on success to do whatever you like.
<button class="btn btn-primary" onclick="primaryImage(this, 4107,19372,'/abbie1.jpg'); return false;">set as profile image</button>
And in your JS
function primaryImage(element, eid,pid)
{
[...]
success: function(data){
if(data.result=='success')
{
$(element).addClass('btn-success');
}
else
{
alert('An error occurred when trying to set the image: ' + data.result);
}
}
[...]
}
You could use data-* attributes instead of onclick (MDN Documentation) and then access those throught jQuery, so your code is more clean and HTML / JS are separated.
Try this code, I've created three data attributes (data-eid, data-pid and data-image) for your params and also replaced your JS to make the whole stuff work with those data attributes. Those attributes can be accessed with following jQuery code - var eid = $(this).attr('data-eid'); as an example
This line of code removes the btn-primary class from the clicked button, adds a btn-success class to it and disables it, so it can't be toggled again.
pushedBtn.removeClass("btn-primary").addClass("btn-success").prop("disabled", true);
HTML
<button class="btn btn-primary" data-eid="4107" data-pid="19372" data-image="/abbie1.jpg">
profile image
</button>
<button class="btn btn-primary" data-eid="4107" data-pid="19373" data-image="/abbie2.jpg">
profile image
</button>
<button class="btn btn-primary" data-eid="4107" data-pid="19374" data-image="/abbie3.jpg">
profile image
</button>
JS
$(".btn").click(function (e) {
if (confirm("Are you sure you wish to use this as your profile image?")) {
var eid = $(this).attr('data-eid'); //like 4107
var pid = $(this).attr('data-pid'); //like 19372
var image = $(this).attr('data-image'); //like /abbie1.jpg
var pushedBtn = $(this);
$.ajax({
type: "POST",
async: false,
cache: false,
dataType: "json",
url: "ajax_photo.php",
data: "action=primary&eid=" + eid + "&pid=" + pid,
//context: this,
success: function (data) {
if (data.result == 'success') {
alert('The image is now set as the profile image');
pushedBtn.removeClass("btn-primary").addClass("btn-success").prop("disabled", true);
} else {
alert('An error occurred when trying to set the image: ' + data.result);
}
}
});
}
});
There are a ton of proposed answers to my question, but even with all the answers I have found, I can not seem to get any to work. I can make the JS work by adding a delay in execution of the code, but I can't rely on a delay to execute the JS after div has finished loading it's HTML.
I'm creating a page where users can search for an item, and the results are displayed in a div using AJAX. I need some JS to run after the div's html has finished loading. Some of the results data will be hidden until a user clicks on it. The JS code to accomplish this is what I am trying to run once the div finishes loading.
I have tried the following extensively with no luck anywhere:
.load
.ajaxComplete
.complete
.success
.done
Document.ready
I'm sure there are a few others as well, but my brain is just too beat up from dealing with this to remember everything I've tried so far.
My HTML:
<form name ="CardName" method="post" action="">
<div "class="w2ui-field">
<div> <input type="list" Name="CardName" id="CardName" style="width: 80%;"></div>
</div>
<div class="w2ui-buttons">
<input type="submit" name="search" style="clear: both; width:80%" value="Search" class="btn">
</div>
</form>
<div class="Results" id="Results" name="Results"></div>
My JS:
$(function() {
$("#CardSearch").bind('submit',function() {
var value = $('#CardName').val();
$.ajax({
method: "POST",
url: "synergies.php",
data: {value}
})
.success(function(data) {
$("#Results").html(data);
})
.complete(function() {
alert("div updated!"); //Trying to run JS code AFTER div finishes loading
});
return false;
});
});
If there is anything else that could help with this request just let me know!
Thanks in advance!
Note that success and failure are options that you should provide to the $.ajax call, not the returned promise. Also, bind is deprecated in favour of on since jQuery 1.7. Finally, you need to give the value that you're posting to your PHP page a key so that it can be retrieved via $_POST. Try this:
$("#CardSearch").on('submit', function(e) {
e.preventDefault();
$.ajax({
method: "POST",
url: "synergies.php",
data: {
CardName: $('#CardName').val()
},
success: function(data) {
$("#Results").html(data);
},
complete: function() {
alert("div updated!"); //Trying to run JS code AFTER div finishes loading
}
})
});
You can then retrieve the value sent in your synergies.php file using $_POST['CardName'].
If you prefer to use the method provided by the returned promise, you can do that like the below, although the result is identical.
$("#CardSearch").on('submit', function(e) {
e.preventDefault();
$.ajax({
method: "POST",
url: "synergies.php",
data: {
CardName: $('#CardName').val()
}
}).done(function(data) {
$("#Results").html(data);
}).always(function() {
alert("div updated!");
})
});
you can try Synchronous Ajax request, demo code is given below:
$(function() {
$("#CardSearch").bind('submit',function() {
e.preventDefault();
sendData = $('#CardName').val();
reqUrl = "synergies.php";
// this will wait until server request complete
var ajaxOpt = AjaxSyncRequest(reqUrl, sendData);
// after complete server request
ajaxOpt.done(function(data) {
$("#Results").html(data);
});
});
});
function AjaxSyncRequest(reqUrl, sendData) {
var ajaxData = $.ajax({
method: "POST",
url: reqUrl,
data: {
data: sendData
}
});
return ajaxData;
}
I have several buttons which should change content of region on the page. I've read numerous tutorials how can lazy load can be implemented using ajax, but unfortunately with no success. Here is my html:
<div>
<div>
<button id="btn_goals">Goals</button>
<button id="btn_achievements">Achievements</button>
</div>
<div id="region_content"></div>
</div>
and here is my js:
$(document).ready(function () {
$('#btn_goals').on('click', function () {
$.ajax({
url: '#Url.Action("Index", "Goals")',
success: function (data) {
$('#region_content').html(data);
}
});
});
$("#btn_achievements").on("click", function () {
......
});
});
what is the problem?
********** EDIT ************
Well, I changed url in ajax parameters from url: '#Url.Action("Index", "Goals")' to url: '/Goals/Index' and it starts work fine. What is the reason?
Try following the following steps:
Use console.log("Inside Success function"+ data); to test whether the required data is being returned from the controller method.
Use Ctrl+Shift+I in your browser to view the console. If Successful:
Use:
var div = document.getElementById("region_content");
div.innerHTML = div.innerHTML + data;
Make sure your type conversions are done right.
Also specify type: POST in your ajax function.
If you do not see 'Inside Success function' on your console, there might be something wrong with your controller function.