AIM: I would like to set the below function to call every 5 seconds. Using qtip.
The variable ALARM_POPUP changes every minute via a shellscript which replaces the contents on the variable.
CODE:
function popupTXT()
{
var ALARM_POPUP="Alarm Warning warning ";
$('#telecom_1').qtip({content:ALARM_POPUP,style: {name: 'dark', tip: 'topLeft'} });
};
I am using the below to call on a timer.
setInterval("popupTXT()",5000);
OUTCOME: This will only work when I refresh the browser. Any suggestions would be appreciated
The variable ALARM_POPUP changes every minute via a shellscript which replaces the contents on the variable.
That means that in order to see that change on the page, you have to call the server to get an updated value. You're not doing that.
You could do that via ajax. Create a server-side page that outputs the new value for ALARM_POPUP as raw text (using Content-Type: text/plain) or as JSON (using Content-Type: application/json), and trigger an ajax call to get the contents of that page, then update the qtip with it. You wouldn't want setInterval for that because with the indeterminate length of time the ajax call would take, things would very quickly become chaotic. Instead, just initiate a setTimeout upon completion of the previous cycle.
Assuming you create an updatealarm.xyz page (PHP, JSP, ASP.Net, whatever) that outputs the current ALARM_POPUP value as plain text, that would look something like this:
(function()
{
var ALARM_POPUP="Alarm Warning warning ";
function updateQtip(popupText)
{
$('#telecom_1').qtip({content:popupText,style: {name: 'dark', tip: 'topLeft'} });
setTimeout(nextUpdate, 5000);
}
function nextUpdate()
{
$.ajax({
url: "updatealarm.xyz",
success: function(data)
{
ALARM_POPUP = data; // Although you don't actually need to update it
updateQtip(data);
},
error: function()
{
// Do error handling
}
});
}
updateQtip();
})();
About your original setInterval call: It's best not to pass strings into setInterval or setTimeout; that's basically doing an eval, and it's neither necessary nor a good idea. Instead, pass in a function reference (e.g., the function's name, without () calling it), as above.
Re your comment below:
I am having problems with this and I was wondering if you provide an example of what the php file would look like
I've only done a little PHP, but I believe it would look like this:
<?php
header('Content-Type: text/plain');
echo 'This is the message that will end up in \'data\' in the ajax success handler.';
?>
Or if you prefer to use a variable to make it easier for your sed script:
<?php
header('Content-Type: text/plain');
$alarm_popup = 'This is the message that will end up in \'data\' in the ajax success handler.';
echo $alarm_popup;
?>
Try this:
setInterval(popupTXT,5000);
Just a sample
Read more about .setInterval()
Related
Mid development I decided to switch to server-side rendering for a better control amongst other benefits. My web application is completely AJAX based, no url redirecting, so the idea here is a website that builds itself up
I just couldn't figure out the proper way to send javascript events/functions along with the html string, or should all the necessary javascript always be preloaded in the static files?
Let's say client clicks a pre-rendered button 'open table'
The server will make a query, build the html table and send it back, but this table also needs javascript triggers and functions to work properly, how are these sent, received and executed?
There are a couple of articles that mention to not use eval() in Javascript, is there any way around this? I don't want to have to preload unnecessary events for elements that don't yet exist
The server is Python and the Client is Javascript/JQuery
Theoretical example :
Client Base Javascript :
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
eval(response.javascript()); //??
}
});
Python Server(views.py) :
def get_table(request):
data = {}
#String containing rendered html
data['html'] = get_render_table()
#String containing Javascript code?
data['javascript'] = TABLE_EVENTS_JAVASCRIPT
return HttpResponse(json.dumps(data),content_type='json')
Worth noting my question comes from an experimental/learning perspective
Update:
You can use jQuery.getScript() to lazy load JS. I think this solution is as close as you can get to run JS without using eval().
See this example:
jQuery.getScript("/path/to/script.js", function(data, textStatus, jqxhr) {
/* Code has been loaded and executed. */
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
});
and "/path/to/script.js" could be a string returned from $.getJOSN response.
Also, the documentation for getScrippt() has examples on how to handle errors and cache files.
Old Answer:
Using .on() attaches events to current and future DOM elements.
You can either attache events prior to DOM insertion or attache event after DOM insertion.
So in your example you can do something like:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
var code = $(response.html);
code.find(".elementToFind").on("click", function (){
// Code to be executed on click event
});
$("#table_div").append(code);
}
});
I did not test the code but I think it should work.
Assuming you can't just set up an event-binding function and then call it from the main script (the JavaScript you need can't be guessed ahead of time, for example) then one really easy way is just to append the JavaScript to the bottom of the returned HTML content within script tags. When it's appended along with the HTML, the script should simply execute, with no eval() required.
I can't swear that this would work in old browsers, but it's a trick I've used a couple of times, and I've had no problems with it in Firefox, Chrome, or any of the later IE versions.
I think I see what you're asking here, from my understanding you want to send the new "page" asynchorously, and render the new javascript and html. It looks like you already got your request/response down, so i'm not gonna go and talk about sending JSON objects, and the whole "how-to" of sending html and javascript because it looks like you got that part. To do what you want and to dynamically add your javascript in, this stackoverflow question looks like it has what you need
Is there a way to create a function from a string with javascript?
So pertaining to your example, here is how it would look when you recieve the JSON string from your python script:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
/* Create function from string */
var newFunction = Function(response.javascript['param_1'], response.javascript['param_2'], response.javascript['function']);
/* Execute our new function to test it */
newFunction();
}
});
*Your actual function contents would be the string: response.javascript['function']
*Your parameter names if any would be in separate strings ex: response.javascript['param_1']
That is almost a direct copy of the "String to function" code that you can see in the linked question, just replaced it with your relevant code. This code is also assuming that your object is sent with the response.javascript object containing an array with your actual function content and parameter names. I'm sure you could change the actual name of the var too, or maybe put it in an associative array or something that you can keep track of and rename. All just suggestions, but hopefully this works for you, and helps you with your problem.
I am also doing similar work in my project where I had to load partial html using ajax calls and then this partial HTML has elements which requires events to be attached. So my solution is to create a common method to make ajax calls and keep a js method name to be executed post ajax call in html response itself. For example my server returns below html
<input type="hidden" data-act="onPartialLoad" value="createTableEvents" />
<div>.........rest of html response.....<div>
Now in common method, look for input[type='hidden'][data-act='onPartialLoad'] and for each run the method name provided in value attribute (value="createTableEvents")
Dont Use Eval() method as it is not recommended due to security
issues. Check here.
you can run js method using window["method name"]...so here is a part of code that I use.
$.ajax(options).done(function (data) {
var $target = $("#table_div");
$target.fadeOut(function () {
$target.html(data);
$target.fadeIn(function () {
try {
$('input[data-act="onPartialLoad"]', $target).each(function () {
try {
//you can pass parameters in json format from server to be passed into your js method
var params = $(this).attr('params');
if (params == undefined) {
window[$(this).val()]();
}
else {
window[$(this).val()]($.parseJSON(htmlutil.htmlDecode(params)));
}
} catch (e) {
if (console && console.log) {
console.log(e.stack);
console.log($(this).val());
}
}
});
}
catch (e) {
console.log(e.stack);
}
});
});
});
use jQuery.getScript() (as suggested by Kalimah Apps) to load the required js files first.
I have the following function called HowTo that is executed with a onclick event, a function within it requires the JQuery plugin jquery.cookie which is: "A simple, lightweight jQuery plugin for reading, writing and deleting cookies." :
function HowTo(){
$largeAmountOfHTML = document.getElementById("element").innerHTML;
$.cookie("nameOfCookie", $largeAmountOfHTML);
$.ajax({
type: "GET",
url: "path/to/serverside/script.php",
async:false,
});
window.location.href='anotherPage.php';
};
The function firstly retrieves a substantial amount of HTML and assigns it to the variable $largeAmountOfHTML. Then using the JQuery function $.cookie() declared in jquery.cookie's library the function saves the value of $largeAmountOfHTML to the cookie nameOfCookie. Then the function makes an AJAX call that executes a serverside php script which retrieve the cookie data and saves the content to a MYSQL database. Once complete the function directs the current window to anotherPage.php.
The function runs smoothly with no console errors declared. However, when $largeAmountOfHTML reaches a certain size jquery.cookie cannot assign the cookie fast enough before the serverside script attempts to retrieve it. jquery.cookie does not list any methods I can use to prevent this from happening.
Once $largeAmountOfHTML is large enough and cannot be saved to the cookie in time the severside script declares the this error:
<br />
<b>Notice</b>: Undefined index: nameOfCookie in <b>localhost/path/to/serverside/script.php</b> on line <b>4</b><br />
What is the best way to get around this?
Wont deferred.done work? Then just call the serverside code in the callback deferred.done
From what I have read JQuery's getScript function loads the script file in a global context using a function called 'global eval'. Is there a particular setting or method to change this so it will instead load within the function I am calling it from?
If I do the following code name returns undefined as its not loading the script in the local context.
function callscript(){
var name='fred';
getScript(abc.js);
}
//abc.js:
alert(name);
I believe I have found the solution using a regular JQuery ajax call. The trick is you set the datatype to 'text' as otherwise if its script or if use getScript or the alternative .get() it will auto run the script inside and place it in the global context.
function abc(){
var msg="ciao";
$.ajax({
url: 'themes/_default/system/message.js',
success: function(data){
eval(data);
},
dataType: "text"
});
}
//message.js
(function() {
alert(msg);
})();
This alerts 'ciao' as expected :)
Before anyone says anything yes I'm using eval but its perfectly fine in this situation.
As you already noticed, there's nothing in the docs regarding this. I double checked the source code and found that the underlying call has no options for you to pass to override this behavior.
// http://code.jquery.com/jquery-1.9.1.js
...
getScript: function( url, callback ) {
return jQuery.get( url, undefined, callback, "script" );
},
...
As far as I can tell, loading a script asynchronously into a local scope is not possible with jQuery. jQuery's API doesn't give you any other means to configure its usage like this.
I am still investigating how it might be possible using some other technique.
Ok i know this is 2017, 4 years later, but it seems jQuery team never bothered to address this issue, well sort of. I had the same problem and i think this is the solution, the actual intended way of using getScript in a local context. What I noticed was that there is no way that code could be easily eval'd in a local context against your code, which jQuery has no idea how it is going. I haven't gone deeper, but if you look at the jQuery source, how it is injecting the script into the document, it's genius, it avoids eval altogether. The script it therefore ran as if it's a file that was imported through script tag. Without further ado...
I have decided to do the vice-versa of the situation, it better explains what's going on. You can then reverse it to that example in question.
If you noticed getScript actually sends a unique ID to the server in the query string. I don't know why they didn't mention this in documentation. Use that to identify returned scripts. But you have to do something in the backend...
let imports;
$.getScript("scripts.php?file=abc.js", (data, textStatus, jqXHR) => {
window[jqXHR.getResponseHeader('X-scriptID')](imports);
alert (imports.name);
});
abc.js:
imports.name = 'fred';
backend wraps whatever script we are getting scripts.php:
// code that gets the file from file system into var $output
$output = file_get_contents($_REQUEST['file']);
// generate a unique script function name, sort of a namespace
$scriptID = "__script" . $_REQUEST['_'];
// wrap the script in a function a pass the imports variable
// (remember it was defined in js before this request) we will attach
// things we want to become local on to this object in script file
$output = "window.".$scriptID."=function(imports) { ".$output." };";
// set the script id so we can find this script in js
header ("X-scriptID: " . $scriptID);
// return the output
echo $output;
What going is that the js requests a script through getScript, but it doesn't request directly to the file it uses a php script to fetch the contents of the file. I am doing this so that i can modify the returned data and attach headers that are used to id the returned script (this is large app in mind here where a lot of scripts are requested this way).
When getScript runs the returned script in the browser as usual, the actual content of the script are not ran, just a declaration of the wrapper function with a unique name __script1237863498 or something like (the number was given by getScript upon requisition of that script earlier), attached to the global window object.
Then js uses that response to run the wrapper function and inject properties into the imports object... which become local to the requesting whatever's scope.
I don't know jQuery implementation, but the reason name is returning undefined is because name is a private property of the callscript object. To negate this, you could declare the variable outside of the function call:
var name = ''; //Declare name outside of the function
function callscript(){
name='fred';
getScript('abc.js'); //Shouldn't it be $.getScript? and argument should be passed as a string
}
//abc.js:
console.log(name) //Returns undefined
callscript(); //Call the script
console.log(name); //Returns "fred"
// global.js
var global1 = "I'm a global!";
// other js-file
function testGlobal () {
alert(global1);
}
Can I add javascript code that logs every time the user is executing an AJAX call or changing the URL(exiting my page)
I want this piece of code to identify the ajax call automatically, I don't want to do it manually wherever there is an ajax call
if you are willing to use jQuery than try this one:
create a common function for all ajax requests
function ajxCall(url,data,method)
{
$('#logDiv').html(url+'<br>'); // Placing all request URLs in a debug div
$.ajax({url : url,
method : method ,
data : data , // data will be a jason object or you can set it by changing dataType
dataType:'JSON'})
}
function someEvent() // assign this handler to your event
{
ajaxCall('http::localhost/login.php',
{username:'my_user',password:my_password,
'POST'});
}
You can also create it with out jQuery. I have just described the idea. Hope It helps :) regards.
I have a PHP function that queries a MySQL database and outputs an html table. This works fine with following PHP code:
<?php
showTable();
?>
But if I use the javascript code:
form.onsubmit = function() {
document.getElementById("php_code").innerHTML="<?PHP showTable(); ?>";
};
the browser does not show the table. There seems to be a problem with the (innerHTML) html string. I noticed for example that a carriage return inside a MySQL parameter causes problem with the innerHTML, but not with the PHP-only code.
Is there a way to fix this?
(the reason I wish to use the javascript bit is to be able to have a form with two buttons with different PHP functions depending on the form buttons clicked).
Php runs on the server, it generates the html page, and returns it to the browser for rendering. Javascript runs in the browser -- which happens after the php has finished running. It is not possible to invoke a php function directly from within a javascript function.
In order to do what you're trying to do, you'll need to move your php code into its own PHP file, and use something like jQuery's load() function to invoke your php via a separate http request. Something like this:
form.onsubmit = function() {
jQuery("#php_code").load('show_table.php');
};
where "show_table.php" contained something like this:
<?php
/** remember to include the function showTable()
* here, so you can call it below.
*/
function showTable() {
/* your function source here */
}
showTable();
Hope this helps. You might also want to do some research on web applications in general -- specifically, read up on the roles that are played by PHP and Javascript respectively.
edit
If you understand the distinction I've outlined above, and your actual intention really is to have the php function run when the page is initially loaded, rather than waiting till the javascript function is called, then you can modify your code as follows:
form.onsubmit = function() {
document.getElementById("php_code").innerHTML="<?PHP echo(addcslashes(showTable(), "\0..\37\\'\"/\177..\377")); ?>";
};
In order to use this approach, you will also need to make your function showTable() return the string rather than printing it out directly. One way to accomplish this is with php's output buffering functions. Just take your existing showTable() function, and wrap it like this:
function showTable() {
ob_start();
/* existing showTable logic goes here */
return ob_get_clean();
}
You need to escape the output of showTable() properly if you want to do it in a variable like that.
However, I propose a different method for you. Include the HTML like this:
<script type="text/html" id="showTable">
<?php showTable(); ?>
</script>
<script type="text/javascript">
form.onsubmit = function() {
document.getElementById("php_code").innerHTML= document.getElementById('showTable').innerHTML;
};
</script>
Notice the use of type="text/html" in the previous script tag. This will cause the table not to be shown to the browser, but retrievable by javascript.
Good luck.
Two things:
Be sure that no characters come out of showTable() that would interfere with the JavaScript code (like quotes)
Convert new lines to break characters (nl2br()) in your showTable() function.