I am loading multiple d3 line graphs in a Ruby on Rails app and want to display a loading image (gif) while I wait for my data response to populate them.
What's the best, easiest way to do this? Should I place some jQuery inside my Ajax call or before it, perhaps?
I send a ajax request for some .json and draw the graphs in a .js file that looks like this:
my_d3_file.js:
var loadData = function () {
var path = window.location.pathname.split('/');
var site_id = path[path.length - 1];
$.ajax({
type: 'GET',
contentType: 'application/json; charset=utf-8',
url: '/data_reports.json?site_id=' + site_id + '&graphable=true',
dataType: 'json',
success: function (data) {
drawGraphs(data)
},
failure: function (result) {
error();
}
});
function drawGraphs(data) {
var svg = d3.select("#plot1").append("svg")...
// etc, code for d3 graphs
}
$(document).ready(function () {
loadData();
})
My html looks like this:
my_graphs.html.erb
<div id="plot1" class="plot"></div>
My Rails file structure looks like this:
assets
images
my_loading_image.gif
javascripts
my_d3_file.js
stylesheets
my_css.css
views
graph_folder
my_graphs.html.erb
Does something like this get me started? I'm just not sure where everything needs to be placed, specifically in my JavaScript file, in relation to the ajax call.
Inside ("#plot1"):
<img src="../../assets/images/ajax-loader.gif" id="loading-gif"
style="display:none" />
//also, is my file path correct?
In my css:
#loading-indicator {
position: relative;
left: 10px;
top: 10px;
}
In my_d3_file.js:
$(document).ajaxSend(function(event, request, settings) {
$('#loading-gif').show();
});
$(document).ajaxComplete(function(event, request, settings) {
$('#loading-gif').hide();
});
Thanks so much! Let me know if I can provide more info!
Just include the spinner graphic inside the #plot1 tag
<div id="plot1" class="plot">
<img src="../../assets/images/ajax-loader.gif"/>
</div>
At the time you want to draw your graph here just select the image and remove it, and create an svg tag instead
d3.select("#plot1 img").remove();
var svg = d3.select("#plot1").append("svg")
.attr("width", 500)
.attr("height", 500);
Just add your drawing to this svg variable
Maybe this helps, in your ajax call use the beforeSend callback to display the loading gif, and in your success callback hide them and render the graphs. Something like:
$.ajax({
beforeSend. function() {
aFunctionToShowLoadingGIF();
},
success: function (data) {
aFunctionToHideTheLoadingGIF();
drawGraphs(data);
}
failure: function (result) {
error();
}
});
Just create a div with loader. Don't initially hide it.
<div id='loader'><img src="images/loader.gif"/></div>
Then hide the loader once the data is loaded by d3.
// load the d3 data
d3.json("json/data.json", function(treeData) {
$("#loader").hide();
//rest of code
}
Show the loader div again if you need to reload the data elsewhere.
Related
I have following javascript code which loads information from multiple json files and appends them in HTML table if "info" parameter in URL is true.
$(document).ready(function(){
var appList=["app1","app2","app3"];
//function to get url parameters
var parameters = new URL(window.location).searchParams;
var info=parameters.get('info');
if (info=="true"){
for (var i=0;i<appList.length;i++){
setInfoAndDateUtil(app)
}
}
function setInfoAndDateUtil(app){
$.ajax({
url:'server_name/'+ app + '/info.json';
method: 'GET',
dataType: 'json',
contentType:'application/json',
success: function(jsonData){
var info=jsonData.info;
td=$("#" + app);
td.text(info).css("text-align", "center");
}
})
}
The ajax requests are taking some time since they are loading about 16 json files. So I want to add loading screen while this function executes.
I have tried few methods like this but none of them are working.
$(document).ajaxStart(function(){
$("#wait").css("display", "block");
});
$(document).ajaxComplete(function(){
$("#wait").css("display", "none");
});
Can anyone tell me how to do it exactly?
Use this approach using JQuery:
// Add Loader on ajax calls
$("body").prepend("<div id='spinner'><img src='/images/spinner.gif'></div>");
$(document).ajaxSend(function(){
$('#spinner').show();
});
$(document).ajaxComplete(function(){
$('#spinner').hide();
});
On my website (MVC and web API) I have added a preloader for a better user experience purpose.
I have added the preloader at two points:
After Login, between the user is authenticated and the redirection to the homepage.
In every page that loads data from the server.
I did it with an image that I show when the page/data loads and I hide when the data is fully loaded.
<div id="dvReqSpinner" style="display: none;">
<br />
<center><img src="~/images/loading_spinner.gif" /></center>
<br />
</div>
And with jquery I show and hide it:
$("#dvReqSpinner").show();
$("#dvReqSpinner").hide();
It's a little bit anoying to keep showing and hiding an image every time I need to load data (using an AJAX call to web API, authenticating the user etc.. - Every action that takes time and I want to show the user that something is "happening"), isn't there any "automatic" option to have a preloader on a website?
I don't know if its the case, but if you use jquery ajax to handle your requests, you can do something like this:
$(document).ajaxStart(function() {
// every time a request starts
$("#dvReqSpinner").show();
}).ajaxStop(function() {
// every time a request ends
$("#dvReqSpinner").hide();
});
EDIT:
If you want to avoid showing the spinner for fast requests, i think this can make it work:
var delayms = 3000; // 3 seconds
var spinnerTimeOut = null;
$(document).ajaxStart(function() {
// for every request, wait for {delayms}, then show spinner
if(spinnerTimeOut!=null){
clearTimeout(spinnerTimeOut);
}
spinnerTimeOut = setTimeout(function(){
$("#dvReqSpinner").show();
}, delayms);
}).ajaxStop(function() {
// every time a request ends
clearTimeout(spinnerTimeOut); // cancel timeout execution
$("#dvReqSpinner").hide();
});
Give it a try. i couldn't test it -.-'
To show or hide a loading indicator in a single page app, I would add and remove a CSS class from the body:
#dvReqSpinner {
display: none;
}
body.loading #dvReqSpinner {
display: block;
}
and
$("body").addClass("loading");
$("body").removeClass("loading");
Primarily this would make the JS code independent on the actual page layout, so it's "nicer" but not really "less work".
To do it "automatically", I recommend abstracting your Ajax layer into a helper object:
var API = {
runningCalls: 0,
// basic function that is responsible for all Ajax calls and housekeeping
ajax: function (options) {
var self = this;
self.runningCalls++;
$("body").addClass("loading");
return $.ajax(options).always(function () {
self.runningCalls--;
if (self.runningCalls === 0) $("body").removeClass("loading");
}).fail(function (jqXhr, status, error) {
console.log(error);
});
},
// generic GET to be used by more specialized functions
get: function (url, params) {
return this.ajax({
method: 'GET',
url: url,
data: params
});
},
// generic POST to be used by more specialized functions
post: function (url, params) {
return this.ajax({
method: 'POST',
url: url,
data: params
});
},
// generic POST JSON to be used by more specialized functions
postJson: function (url, params) {
return this.ajax({
method: 'POST',
url: url,
data: JSON.stringify(params),
dataType: 'json'
});
},
// specialized function to return That Thing with a certain ID
getThatThing: function (id) {
return this.get("/api/thatThing", {id: id});
}
// and so on ...
};
so that later, in your application code, you can call it very simply like this:
API.getThatThing(5).done(function (result) {
// show result on your page
});
and be sure that the low-level stuff like showing the spinner has been taken care of.
You can use global ajax handlers for this.
This code will execute whenever you make an ajax request. all you have to do here is enable your spinner.
$( document ).ajaxSend(function() {
$("#dvReqSpinner").show();
});
This code will execute once your ajax request succeeded. all you have to do here is enable your spinner.
$( document ).ajaxSuccess(function( event, request, settings ) {
$("#dvReqSpinner").hide();
});
You can also use other global ajax function to handle things like showing a popup when a ajax request fails using ".ajaxError()"
Below link will have details of all the other functions
https://api.jquery.com/category/ajax/global-ajax-event-handlers/
I'm using angularJS and need to apply a watermark programatelly in images by calling an JS function. What I have is:
<figure><img class="watermark" ng-src="{{applyWatermark(img.url)}}"></figure>
So, I need to call that function applyWatermark (not implemented yet) and return a img with the watermark, but I'm not sure how can I build this function. Should it return the image? Can someone provide me some example how can I do this?
EDIT:
I did this, but it's not working:
$(function applyWatermark(image) {
watermark([image, 'watermark.png'])
.image(watermark.image.lowerRight())
.then(function (img) {
return img
});
})
Any idea?
Using watermark.js:
watermark(['/img/forest.jpg', '/img/logo.png'])
.image(watermark.image.lowerRight(0.5)) // Or lowerRight() for no opacity
.then(function (img) {
document.getElementById('alpha-image').appendChild(img);
});
If this doesn't work for you, maybe try this:
$.ajax({
url: 'http://www.example.com/your-image.jpg',
type: 'HEAD',
error: function() {
// File isn't found
},
success: function() {
// File is found! Do the watermarkage.
}
});
to test if the image exists before processing.
I am using redips plugin(http://www.redips.net/javascript/drag-and-drop-table-content/) for drag and drop. It is working on static data, but when data comes dynamic through java, the drag and drop stops. I am using the following functions to pick up data on drag and drop:
droppedBefore: function() {}
, finish: function() {}
The plugin is written on pure javascript, so jquery is not working otherwise we could use $(document).live for picking dynamic data
Please suggest something so that drag and drop can work on dynamic data also
Whenever table layout inside drag container is changed, then is needed to call init() or initTables() method. Please see example0 where new table is dynamically appended with jQuery.
http://www.redips.net/my/preview/REDIPS_drag/example00/index2.html
... and here is JavaScript code used in script.js file:
// new table using AJAX/jQuery to the drag container
redips.load_table = function (button) {
// parameter (example for ajax request)
var id = 1;
// disable button (it can be clicked only once)
button.style.backgroundColor = '#c0c0c0';
button.disabled = true;
// AJAX request
$.ajax({
type: 'get',
url: 'ajax.php',
data: 'id=' + id,
cache: false,
success: function (result) {
// load new table
$('#load_content').html(result);
// rescan tables
REDIPS.drag.initTables();
}
});
};
after post request change in table then call
REDIPS.drag.init();
$.ajax({
type: "post",
url: "/recipe/sliderData",
dataType: "json",
data: dataForSlider,
success: function (data) {
//table change
REDIPS.drag.init();//
},
error: function (data) {
alert("Error")
}
});
I am building a mobile app with Jquery mobile. What you need to know is that I am also working with a content renderer. So I only have one with data-role page. This is what I do in the content renderer. with <%= incBody %> I get the content of my pages.
<body <%=incBodyAttr%>>
<div data-role="page" class="type-index" data-theme="g">
<%=incBody%>
</div>
</body>
I think that was somewhat that you needed to know. Now the real problem.
At the moment I have a function load() You can see it over here.
function load(){
var userId = $("#userId").val();
$.ajax({
url: "~SYSTEM.URL~~CAMPAIGN.URL~/SelligentMobile/Webservice/WebService.asmx/getNieuwtjes",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{'userId':'" + userId + "'}",
success: function (response) {
var nieuwtjes = response.d;
if (nieuwtjes.length > 0) {
$.each(nieuwtjes, function (i, entity) {
$('#nieuwtjesList').append(
$("<li/>").append($("<a/>")
.attr("href",'~PROBE(239)~&NEWSID=' + entity.nieuwtjeId)
.text(entity.nieuwtjeOnderwerp)
)
);
$('#nieuwtjesList').trigger("create");
$('#nieuwtjesList').listview('refresh');
});
}
}
});
}
Now this load is triggered by a button at the moment. But what I want to do is that each time the page loads, its executing this function.
Can anybody help ?
kind regards
Call it from a document ready handler:
$(document).ready(function() {
load();
});
Or, given that you're not passing parameters to load():
$(document).ready(load);
The first way allows you to do other stuff before or after calling load(), should you need to: just add more code into the anonymous function.
See the .ready() doco.
You should use jQuery DOM ready:
$(function() {
// call load() after DOM ready
load();
});
You can also use as
$(document).ready(function() {
load();
})