I have a following code in my php file:
<div id="clockTimestamp" class="hidden"><?=$_SERVER['REQUEST_TIME'];?></div>
<div id="clock"></div>
I am using the jquery countdown plugin from Keith Wood and am calling it like this:
$('#countdown').countdown({until: until, serverSync: getServerTime});
And following code in the js file:
function getServerTime() {
var time = $('#clockTimestamp').html()*1000;
time = new Date(time);
return time;
}
Now, my question is: is this approach with the $_SERVER['REQUEST_TIME'] OK or should I do it like this:
function getServerTime() {
var time = null;
$.ajax(
{
url: '../../_ajax/getServerTime.php',
async: false,
dataType: 'text',
success: function(text) {
time = new Date(text);
},
error: function(http, message, exc) {
time = new Date();
}
});
return time;
}
I'm sure you've solved this now, but for later visitors....
The easiest way to do this would be to use a jQuery server time plugin
Related
I have a page with 2 graphs. I get my data from an API that gives new data every 15 seconds. I want my plots to be updated every minute.
I'm using Flask, plotly for the graphs and ajax for the callback function that updates the graphs every minutes.
I have a working code but my question is why my previous code didn't work ?
Here is the code I use and which WORKS :
monitoring.html
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
const delay = 60*1000; // 1 minute
// This function is called to update the API data every minute
function cb() {
$.getJSON({
url: "/cb_power_graphs", data: { 'data': 'RPM' }, success: function (result) {
Plotly.newPlot('chart_rpm', result, {});;
}
});
$.getJSON({
url: "/cb_power_graphs", data: { 'data': 'power_kw' }, success: function (result) {
Plotly.newPlot('chart_power', result, {});;
}
});
}
var intervalID = setInterval(cb, delay);
</script>
// plots
<div id="chart_rpm" class="chart"></div>
<div id="chart_power" class="chart"></div>
// This always works, initialize the graphs at the start of the page
<script>
d_rpm = {{ graphJSON['RPM'] | safe }};
d_power = {{ graphJSON['power_kw'] | safe }};
Plotly.newPlot('chart_rpm', d_rpm, {});
Plotly.newPlot('chart_power', d_power, {});
</script>
view.py
#app.route('/monitoring')
def monitoring():
return render_template('monitoring.html', graphJSON= power_graphs())
#app.route('/cb_power_graphs', methods=['POST', 'GET'])
def cb_power_graphs() :
data = request.args.get('data')
graphJSONs = power_graphs()
return graphJSONs[data]
def power_graphs() :
# Receive data for this page
data_to_plot = get_data_from_API() # pandas dataframe of the data ('time', 'RPM', 'power_kw')
graphJSONs = {}
for data in ['RPM', 'power_kw'] :
fig = px.line(data_lean_marine, x= "time", y= data)
graphJSONs[data] = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
return graphJSONs
Now here is the code that won't work. I will only show the parts I changed.
monitoring.html
function cb() {
$.getJSON({
url: "/cb_power_graphs", success: function (result) {
Plotly.newPlot('chart_rpm', result.RPM, {});;
Plotly.newPlot('chart_power', result.power_kw, {});;
}
});
}
views.py
#app.route('/cb_power_graphs', methods=['POST', 'GET'])
def cb_power_graphs() :
graphJSONs = power_graphs()
return Response(mimetype="application/json", response=json.dumps(graphJSONs), status=200)
The difference is that the first code sends the graphs individually with a response for each while the second one sends all of the graphs in the same response.
I've followed this solution which seems to have worked for the OP
Sending Plotly charts in a dictionary via jquery (getjson) in a Flask app
Why didn't my second code work ? I can work with the first one but I find the second one much more logical and easier to interpret since I'm going to have many more plots to deal with in the future
Another little question : what is the purpose of the " | safe" here ? It shows an error on my vscode when I put it ("Property assignment expected.javascript") but code will still execute
Thanks a lot
I have following javascript that is using a selection changed to fill in a select list.
$(function () {
$("#bedrijvenauto").each(function () {
var target = $(this);
var dest = target.attr("data-autocomplete-destination");
target.autocomplete({
source: target.attr("data-autocomplete-source"),
select: function (event, ui) {
alert('selected bedrijf');
event.preventDefault();
target.val(ui.item.label);
$(dest).val(ui.item.value);
$("#projectenauto").val("");
alert('selected bedrijf');
alert($('#BEDRIJF_ID').val());
$.getJSON("/Project/GetListViaJson", { bedrijf: $('#BEDRIJF_ID').val() }, function (data) {
alert('selected bedrijf');
alert(data);
$("#PROJECT_ID").empty();
$("#PROJECT_ID").append(new Option("Maak een selectie", 0));
for (var i = 0; i < data.length; ++i) {
alert(data[i].value + ' ' + data[i].label);
$("#PROJECT_ID").append(new Option(data[i].label, data[i].value));
}
});
},
focus: function (event, ui) {
event.preventDefault();
target.val(ui.item.label);
}
});
target.val($("#BEDRIJF_NAAM").val());
});
It works like a charm on my development pc. The alert are all coming out even the data is returning results. That is the difference with the development pc that does not give any results after the call to getJSON
I have the feeling I am missing a detail here.
I am not used to debugging on a webserver because I usually create GUI applications in WPF, and this is a student's work for his vacation and I now got to get it working without him being around anymore. Vacation is done :-(
But not for me.
The 404 error indicated in your comments means the url your creating is incorrect. Always make use of the #Url.Action() method to ensure they are correctly generated. In your script
var url = '#Url.Action("GetListViaJson", "Project")';
$.getJSON(url, { bedrijf: $('#BEDRIJF_ID').val() }, function (data) {
....
}
or if this is an external script, then add the var url = '#Url.Action(...)'; in the main view (razor code is not evaluated in external script files), or add it as a data- attribute to the element your handling
data-url = "#Url.Action(...)"
and get it again using var url = $(someElement).data('url');
I've got the following jQuery:
$("#delete_products").click(function() {
$(":checkbox:checked").each(function() {
var pid = $(this).val();
$.get('delete_product.php',{pid: pid});
});
location.reload();
});
There is a problem with this since the page doesn't wait for the AJAX request to be completed (MULTIPLE AJAX REQUESTS), and refreshes the page immediately and makes the AJAX request to not run and fail.
How can I do that the page will only refresh when it done loading?
I've been given this code:
$("#delete_products").click(function () {
var promises = [];
$(":checkbox:checked").each(function () {
var pid = $(this).val();
promises.push($.get('delete_product.php', {
pid: pid
}));
});
$.when.apply($, promises).done(function () {
location.reload();
});
return false;
});
But this solution just doesn't work.
any suggestions?
your code seems like it should work, but i would recommend to delete all products with one call by passing array of ids.
less work for the browser, less work for the server, faster results.
UPDATED ANSWER
$("#delete_products").click(function () {
var ids = [];
$(":checkbox:checked").each(function () {
ids.push($(this).val());
});
$.post('delete.php', { 'ids': ids } }).done(function() {
alert('hells yeah!');
});
return false;
});
and as for the server side:
$commaSeperatedIds = explode(',', $_POST['ids']);
mysql_query('DELETE FROM products WHERE id IN('.mysql_real_escape_string($commaSeperatedIds).')');
Use "success" parameter of "get"
EDIT: add counter of requests.
total_requests = $(":checkbox:checked").length;
total_success = 0;
...
$.get('delete_product.php',{pid: pid}, function (data, status, xx) {
...
total_success++;
if (total_success >= total_requests) {
location.reload();
}
});
...
Possible Solution #1:
The async parameter could help. Set it to false.
Since you`re using the $.get() function, this is done with:
$.ajaxSetup({
async: false
});
With the $.ajax() function, you'd simply set it like:
$.ajax({
url: ...,
async: false,
success: function(data) {}
});
More info on this can be found here.
Possible Solution #2:
Use the .success() callback hook OR .complete() if you want to refresh the page no mather if the request failed or not.
$.get('delete_product.php',{pid: pid}).success(function(response)
{
location.reload();
});
Happy coding!
Edit:
The questioner seems to prever sUP's answer. I'd like to provide an example of how to achieve the desired functionality with jQuery:
$("#delete_products").click(function()
{
var products = [];
$(":checkbox:checked").each(function()
{
var pid = $(this).val();
products.push(pid);
});
$.post('delete_products.php', {'products': products}).done(function()
{
location.reload();
});
});
If you prefer to use JSON for the post data, try:
$('#delete_products').click(function()
{
var products = [];
$(':checkbox:checked').each(function()
{
products.push($(this).val());
});
// Convert the products array into JSON
products = JSON.stringify(products);
$.post('delete_products.php', {'products': products}).done(function()
{
location.reload();
});
});
In PHP you need to parse the json string as follows:
<?php
// This creates an associative array from the JSON string
$delete_products = json_decode($_POST['products'], true);
// Use explode to make a comma separated string from the array
// for use in a SQL SELECT query:
$delete_products = explode(',', $delete_products);
Info about json_decode can be found in the PHP Manual.
JSON.stringify is not supported in older browsers. Include JSON-js if you need cross browser support.
I too believe that the desired result can probably be achieved best by collecting the product IDs and then sending a single Ajax call to take care of them all.
But since the OP put the interesting question forward of how to handle multiple Ajax requests and wait for them all to be finished I have looked at the when() method again and it seems to me that the original syntax is still faulty.
According to the jQuery manual when() is a method and therefore requires to be called with one or more argument(s) in parentheses. I have not worked with promises yet and I have not tested anything but I assume that something like the following might bring at least a different result:
$("#delete_products").click(function () {
var promises = [];
$(":checkbox:checked").each(function () {
var pid = $(this).val();
promises.push($.get('delete_product.php', {
pid: pid
}));
});
$.when(promises).done(function () {
location.reload();
});
return false;
});
As I said before, I still have not quite grasped the promises mechanisms/syntax yet ...
In the original version $.when does not have any meaningful context to work on, The apply() method does provide context but only after when has done its (unseccessful) work already.
how do I do two xhr.gets one after the other using dojo ?
I have ....
require(["dojo/_base/xhr", "dojo/dom", "dojo/domReady!"],
function(xhr, dom) {
// Using xhr.get, as very little information is being sent
xhr.get({
// The URL of the request
url: "inc/etl2json.php?item=Execs",
// The success callback with result from server
load: function(execContent) {
dom.byId("Execs").innerHTML = execContent;
},
// The error handler
error: function() {
// Do nothing -- keep old content there
}
});
});
I would like to do another xhr.get to "inc/etl2json.php?item=Execs" and assign it to dom.byId("Elapsed").innerHTML = elapsedContent;
just call again xhr.get() inside the load function, well that if the content is supposed to change, else you could just use the same data retrieved the first time:
xhr.get({
load:function(data){
//use the first data you retrieved
xhr.get({
load: function(data2){
//do what you like with the nuew data
}
});
}
});
Although nesting is a straightforward solution it almost always leads to unreadable code, so I would do the same as #Ricardo did, but use the advantage of Dojo's Deferred (+ here) and employ chaining:
var requestUrl = "inc/etl2json.php?item=Execs";
xhr.get({ url: requestUrl})
.then(function(results) {
dom.byId("execs").innerHTML = results;
})
.then(function(results) {
return xhr.get({ url: requestUrl});
})
.then(function(results) {
dom.byId("elapsed").innerHTML = results;
})
See it in action at jsFiddle: http://jsfiddle.net/phusick/73X88/
I think you should add another xhr call for the elapsedContent. I don't see any relation between the two calls so you should make them separate. Nesting one in another is not necessary.
just add
xhr.get({
// The URL of the request
url: "inc/etl2json.php?item=Execs",
// The success callback with result from server
load: function(elapsedContent) {
dom.byId("Elapsed").innerHTML = elapsedContent;
},
// The error handler
error: function() {
// Do nothing -- keep old content there
}
});
I am using jPlayer to play audio files.
If I use the player on content, which is privided, when the page gets loaded, it works without any problems.
I also need it for HTML which is inserted by AJAX. Here it does not work. It seems, that the ready event is not triggered.
I wrote a function, which can be executed by click(). In that way, I can click it manually, when the HTML which contains the player is fully loaded. Here I have the same problem: The ready event is not triggered.
This is my function which works on non ajax inserted players fine:
$('.jp-jplayer').each(function () {
var src = $(this).attr('data-src');
var id = $(this).attr('id');
var post_id = $(this).attr('data-id');
alert('beg');
$('#' + id).jPlayer({
ready: function () {
$(this).jPlayer('setMedia', {
mp3: "/prelisten/_lofidl/change_of_heart_full_lofi.mp3",
});
alert('#' + id);
},
swfPath: "/wp-content/themes/Dark_3Chemical_DE_mit_Pagenavi/Dark_3Chemical_DE/audioplayer/js",
//////ERRRROOOOOR
solution: "flash, html",
supplied: "mp3",
wmode: "window",
cssSelectorAncestor: "#jp_container_" + post_id,
play: function () { // To avoid both jPlayers playing together.
$(this).jPlayer("pauseOthers");
},
repeat: function (event) { // Override the default jPlayer repeat event handler
if(event.jPlayer.options.loop) {
$(this).unbind(".jPlayerRepeat").unbind(".jPlayerNext");
$(this).bind($.jPlayer.event.ended + ".jPlayer.jPlayerRepeat", function () {
$(this).jPlayer("play");
debug($(this));
});
} else {
$(this).unbind(".jPlayerRepeat").unbind(".jPlayerNext");
$(this).bind($.jPlayer.event.ended + ".jPlayer.jPlayerNext", function () {
//$("#jquery_jplayer_4858").jPlayer("play", 0);
});
}
},
});
$("#jplayer_inspector").jPlayerInspector({
jPlayer: $('#' + id)
});
});
Currently I am setting the src manually to exclude any possible errors here.
How can I get this function running on AJAX inserted content?
EDIT:
This is the code, which fetches the html including the players:
$.get('/query_posts.php', {
paged: _page,
cats: cols
}, function(data) {
$('#search-results').append(data).fadeIn(300);
//create_player_scripts();
//set_players();
$('#search-results').find('input[name="cartLink"]').each(function() {
$(this).val($(this).closest('.post1').find('.post_headl a').attr('href'));
});
});
To make an AJAX page reload work I had to first destroy all jplayer instances. So I wrote a little function that grabs all instances of a jplayer on the site (by looking for jp-audio classes) and calls jplayer('destroy'); and jplayer('clearMedia'). This function gets called in the $.ajax({ beforeSend: destroyJplayerInstances(); })
UPDATE:
Here is a statement from the developer of jPlayer, Mark Panaghiston:
https://groups.google.com/forum/#!topic/jplayer/Q_aRhiyYvQo
Hope that helps!