I have a stacked bar chart, which gains data from an api.
It works fine when loaded, and the data is displayed as it should be.
Now I wish to add new data to the chart every ten minutes, calling the same API as when loaded, the chart should refresh asynchronously and he new data and axis label need to be updated as new data is gained.
What I have done so far..
https://plnkr.co/edit/s2Os8UlpSbCWlkNP6wuA?p=preview
var ma = d3.line()
.x(function(d) { return x(parseDate(d.date)); })
.y(function(d) { return y(d.ma); });
If you use jquery, then you can send an AJAX request using the $.ajax function. Make sure you handle the response in the result's done() function, as success is deprecated.
Plain AJAX request example:
HTML:
<!DOCTYPE html>
<html>
<body>
<div id="demo"><h2>Let AJAX change this text</h2></div>
<button type="button" onclick="loadDoc()">Change Content</button>
</body>
</html>
JS:
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
}
Taken from here. If you mastered AJAX requests, then the next step is to write a poller, using setInterval. The first parameter should be a function which sends a request and the second should be the time between two execution in milliseconds (10000 in this case). Or you can use an existing poller. This is one I have implemented:
function Initializable(params) {
this.initialize = function(key, def, private) {
if (def !== undefined) {
(!!private ? params : this)[key] = (params[key] !== undefined) ? params[key] : def;
}
};
}
function Poller(params) {
Initializable.call(this, params);
var that = this;
this.initialize("url", window.location.href);
this.initialize("interval", 5000);
this.initialize("type", "POST");
this.initialize("method", "POST");
this.initialize("data", {});
this.initialize("strict", true);
var defaultFunction = function() {};
this.initialize("done", defaultFunction);
this.initialize("fail", defaultFunction);
this.initialize("always", defaultFunction);
this.isRunning = function() {
return !!params.intervalID;
};
this.run = function() {
if (this.strict && (this.green === false)) {
return;
}
this.green = false;
$.ajax({
url: this.url,
method: this.method,
data: this.data
}).done(function(data, textStatus, jqXHR) {
that.green = true;
that.done(data, textStatus, jqXHR);
}).fail(function(jqXHR, textStatus, errorThrown) {
that.green = true;
that.fail(jqXHR, textStatus, errorThrown);
}).always(function(param1, param2, param3) {
that.green = true;
that.always(param1, param2, param3);
});
};
this.start = function() {
if (!params.intervalID) {
this.run();
params.intervalID = setInterval(this.run.bind(this), this.interval);
}
};
this.stop = function() {
if (!!params.intervalID) {
clearInterval(params.intervalID);
params.intervalID = undefined;
}
};
}
Related
I am trying to sort out back and forward browser buttons in my ajax page load setup.
This is my ajax code that calls page content:
jQuery(document).ready(function () {
$ = jQuery;
$("body").on("click", ".menuAjax a", function (e) {
//On click on body for ajax calls
e.preventDefault();
var pageID = $(this).data("id");
var catType = $(this).data("type");
var pageTitle = $(this).data("title");
var footerAdSwitch = $("#overFooter").data("footeradswitch");
var homePageSet = parseInt($("#homePageSet").val());
var $this = $(this);
//console.log($this);
var res;
var payload = JSON.stringify({
action: "router_loader",
pageid: pageID,
footeradswitch: footerAdSwitch,
homepage: homePageSet,
cattype: catType,
pagetitle: pageTitle,
});
XHR = $.ajax({
type: "get",
url: my_ajax_object.ajax_url + '/' + payload + '/view_' + (pageID || catType),
beforeSend: function () {
$("#ajaxPageLoader").show();
},
complete: function () {
$("#ajaxPageLoader").hide();
},
success: function (res) {
if (res != "") {
$("#ajaxpageLoad").html(res);
setTimeout(function () {
$("#ajaxPageLoader").hide();
}, 600);
$(".nav li.menu-item").removeClass(
"current-menu-item current_page_item"
);
$($this).parent().addClass("current-menu-item current_page_item");
const nextURL = $this[0].href;
history.pushState(res, pageTitle, nextURL);
document.title = pageTitle + " - company name";
$.getScript("/wp-content/themes/customTpl/js/functions.js");
var lazyLoadInstance = new LazyLoad({
threshold: 200,
});
$("html, body").animate({ scrollTop: 0 }, 0);
} else {
$("#ajaxPageLoader").hide();
}
},
error: function (req, status, error) {},
});
});
//Exclude expander btn from ajax call
$("body").on("click", ".btnNoBorder, .mobileMenueBtn, .closeBtn", function (e) {
e.stopPropagation();
});
window.addEventListener('popstate', function(e) {
$("#ajaxpageLoad").html(res);
updateContent(e.state);
});
});
Right now I ma stuck with popstate function, which I would like to pass urls of current position, so they are remembered once a users presses back button.
Can someone suggest me direction as to how to update history navigation with the browser buttons ?
I have 20 data packet in the client and I am pushing one by one to the server via Ajax post. Each call take approximately one minute to yield the response. Is there any way to make few of these requests run parallel.
I have used Jquery promise. However, still the request waiting for the prior one to get completed.
var dataPackets=[{"Data1"},{"Data2"},{"Data3"},{"Data4"},{"Data5"},
{"Data6"},{"Data7"},{"Data8"},{"Data9"},{"Data10"},
{"Data11"},{"Data12"},{"Data13"},{"Data14"},{"Data15"},{"Data16"},
{"Data17"},{"Data18"},{"Data19"},{"Data20"}];
$(dataPackets).each(function(indx, request) {
var req = JSON.stringify(request);
setTimeout({
$.Ajax({
url: "sample/sampleaction",
data: req,
success: function(data) {
UpdateSuccessResponse(data);
}
});
}, 500);
});
The when...done construct in jQuery runs ops in parallel..
$.when(request1(), request2(), request3(),...)
.done(function(data1, data2, data3) {});
Here's an example:
http://flummox-engineering.blogspot.com/2015/12/making-your-jquery-ajax-calls-parallel.html
$.when.apply($, functionArray) allows you to place an array of functions that can be run in parallel. This function array can be dynamically created. In fact, I'm doing this to export a web page to PDF based on items checked in a radio button list.
Here I create an empty array, var functionArray = []; then based on selected items I push a function on to the array f = createPDF(checkedItems[i].value)
$(document).ready(function () {
});
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function exportPDFCollection() {
var f = null;
var x = 0;
var checkedItems = $("input:checked");
var count = checkedItems.length;
var reportList = $(checkedItems).map(
function () {
return $(this).next("label").text();
})
.get().join(",");
var functionArray = [];
var pdf = null;
for (var i = 0; i < count; i++) {
f = createPDF(checkedItems[i].value)
.done(function () {
pdf = checkedItems[x++].value;
alert('PDF => ' + pdf + ' created.');
})
.fail(function (jqxhr, errorText, errorThrown) {
alert('ajax call failed');
});
functionArray.push(f);
}
$.when.apply($, functionArray)
.done(function () {
$.get("http://yourserver/ExportPage.aspx",{reports: reportList})
.done(function () {
alert('PDF merge complete.');
})
.fail(function (jqxhr, errorText, errorThrown) {
alert('PDF merge failed. Please try again.');
});
return true;
});
}
function createPDF(webPage) {
return $.get(webPage);
}
Looking at the Flux Documentation I can't figure out how the code to a ajax update, and a ajax fetch would fit into the dispatcher, store, component architecture.
Can anyone provide a simple, dummy example, of how an entity of data would be fetched from the server AFTER page load, and how this entity would be pushed to the server at a later date. How would the "complete" or "error" status of request be translated and treated by the views/components? How would a store wait for the ajax request to wait? :-?
Is this what you are looking for?
http://facebook.github.io/react/tips/initial-ajax.html
you can also implement a fetch in the store in order to manage the information.
Here is an example (it is a concept, not actually working code):
'use strict';
var React = require('react');
var Constants = require('constants');
var merge = require('react/lib/merge'); //This must be replaced for assign
var EventEmitter = require('events').EventEmitter;
var Dispatcher = require('dispatcher');
var CHANGE_EVENT = "change";
var data = {};
var message = "";
function _fetch () {
message = "Fetching data";
$.ajax({
type: 'GET',
url: 'Url',
contentType: 'application/json',
success: function(data){
message = "";
MyStore.emitChange();
},
error: function(error){
message = error;
MyStore.emitChange();
}
});
};
function _post (myData) {
//Make post
$.ajax({
type: 'POST',
url: 'Url',
// post payload:
data: JSON.stringify(myData),
contentType: 'application/json',
success: function(data){
message = "";
MyStore.emitChange();
},
error: function(error){
message = "update failed";
MyStore.emitChange();
}
});
};
var MyStore = merge(EventEmitter.prototype, {
emitChange: function () {
this.emit(CHANGE_EVENT);
},
addChangeListener: function (callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function (callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getData: function (){
if(!data){
_fetch();
}
return data;
},
getMessage: function (){
return message;
},
dispatcherIndex: Dispatcher.register( function(payload) {
var action = payload.action; // this is our action from handleViewAction
switch(action.actionType){
case Constants.UPDATE:
message = "updating...";
_post(payload.action.data);
break;
}
MyStore.emitChange();
return true;
})
});
module.exports = MyStore;
Then you need to subscribe your component to the store change events
var React = require('react');
var MyStore = require('my-store');
function getComments (){
return {
message: null,
data: MyStore.getData()
}
};
var AlbumComments = module.exports = React.createClass({
getInitialState: function() {
return getData();
},
componentWillMount: function(){
MyStore.addChangeListener(this._onChange);
},
componentWillUnmount: function(){
MyStore.removeChangeListener(this._onChange);
},
_onChange: function(){
var msg = MyStore.getMessage();
if (!message){
this.setState(getData());
} else {
this.setState({
message: msg,
data: null
});
}
},
render: function() {
console.log('render');
return (
<div>
{ this.state.message }
{this.state.data.map(function(item){
return <div>{ item }</div>
})}
</div>
);
}
});
I hope it is clear enough.
I managed to make this code to submit a form, it works fine, but I can not implement a validator does not need it, but it shows no message just does not send the form is empty.
I searched but could not quite do it. Can anyone help me?
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery('#newsletter').submit(function(){
var dados = jQuery( this ).serialize();
jQuery.ajax({
type: "POST",
url: "newsletter_cadastrar.asp?f=1",
data: dados,
success: function( data )
{
$('#resultado-form-newsletter').html(data);
}
});
return false;
});
});
</script>
<input id="nomenewslbase" name="nomenewslbase" type="text">
<input id="emailnewslbase" name="emailnewslbase" type="email">
Thank you for your attention.
If you are looking for applying jquery validation rules then you can do it like:
<script type="text/javascript">
function ValidationRules() {
}
ValidationRules.prototype.initializeSaveValidators = function() {
jQuery.validator.addMethod("csProjectName",
function(value, element) {
if ($.trim($('#txtProjectName').val()) == "") {
if ($.trim($(element).val()) != '')
return true;
else
return false;
} else
return true;
}, "Project Name is required");
jQuery.validator.addMethod("csDescription",
function (value, element) {
if ($.trim($('#txtDescription').val()) == "") {
if ($.trim($(element).val()) != '')
return true;
else
return false;
}
else
return true;
}, "Description is required");
};
ValidationRules.prototype.enableSaveValidators = function () {
jQuery.validator.classRuleSettings.csProjectName = { csProjectName: true };
jQuery.validator.classRuleSettings.csDescription = { csDescription: true };
};
ValidationRules.prototype.disableSaveValidators = function () {
jQuery.validator.classRuleSettings.csProjectName = { csProjectName: false };
jQuery.validator.classRuleSettings.csDescription = { csDescription: false };
};
jQuery(document).ready(function () {
var validationRules = new ValidationRules();
validationRules.initializeSaveValidators();
validationRules.enableSaveValidators();
$("#btnsubmit").click(function () {
applyjQueryValidation();
return false;
});
});
function applyjQueryValidation() {
var isValid = $('#newsletter').valid();
//here you can manually check for some extra validations
if (isValid==true) {
alert("valid");
//here is you ajax call
}else{
alert("invalid");
}
}
</script>
Also, you need to include jquery.validate.js
Here is the JSfiddle working example.
I'm wrapping a simple jQuery promise with RSVP and noticed that when I cause an error on purpose the failure callback is never invoked. I assume it's because when you use vanilla jQuery and the callback throws an error, the returned promise will not be moved to failed state (the opposite of the spec).
If I need to use jQuery $.ajax but I want to get true resolve/reject callbacks with RSVP what (if anything) can I do to the example below?
var peoplePromise = new Ember.RSVP.Promise(function(resolve, reject) {
$.getJSON('/api/people/', resolve).fail(reject).error(reject);
});
var catPromise = new Ember.RSVP.Promise(function(resolve, reject) {
$.getJSON('/api/cats/', resolve).fail(reject).error(reject);
});
Ember.RSVP.all([peoplePromise, catPromise]).then(function(things) {
things[0].forEach(function(hash) {
var thing = App.Person.create(hash);
Ember.run(self.people, self.people.pushObject, thing);
});
things[1].forEach(function(hash) {
var wat = hash.toJSON(); //this blows up
var thing = App.Person.create(hash);
Ember.run(self.people, self.people.pushObject, thing);
});
}, function(value) {
alert(value.status + ": promise failed " + value.responseText);
});
Example here: http://www.youtube.com/watch?feature=player_detailpage&v=g5CSaK3HqVA#t=1080
var ajaxPromise = function(url, options){
return Ember.RSVP.Promise(function(resolve, reject) {
var options = options || {};
options.success = function(data){
resolve(data);
};
options.error = function(jqXHR, status, error){
reject([jqXHR, status, error]);
};
$.ajax(url, options);
});
};
var peoplePromise = ajaxPromise('/api/people/',{
dataType: "json"
});
var catPromise = ajaxPromise('/api/cats/',{
dataType: "json"
});
Ember.RSVP.all([peoplePromise, catPromise]).then(function(things) {
things[0].forEach(function(hash) {
var thing = App.Person.create(hash);
Ember.run(self.people, self.people.pushObject, thing);
});
things[1].forEach(function(hash) {
var wat = hash.toJSON(); //this blows up
var thing = App.Person.create(hash);
Ember.run(self.people, self.people.pushObject, thing);
});
}, function(args) {
var jqXHR = args[0];
alert(jqXHR.status + ": promise failed " + jqXHR.responseText);
});
http://emberjs.jsbin.com/aREDaJa/1/