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.
Related
So I want to create an on click function after successfully called an Ajax function, but I still want to use its original data for that on click function.
$.ajax({
URL: ......,
type: 'GET',
success: function (res) {
var Object = JSON.parse(res);
text = ''
// some code using Object to fix text
$('#someid').attr('href', '#')
$('#someid').text(text)
Now what I want is that someid item, when clicked on, will create a pop-up, change its original content, or something that continues using the var Object up there. I tried but can't find a way to put on click into that Ajax function.
Your question is vague to me. Please specify what you want to achieve. Im assuming you want to have a function called inside Ajax trigger that consumes Object variable value. If so, it's feasible for sure by creating a function doClick(ọbject) and then you can invoke it simply by doClick(obj); after making tweaks to Modal popup. But i dare to think there is misunderstanding in your approach. If you could add more details on this, i could suggest you a way to solve the issue.
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.
There is a modal dialog displaying mantle.ledger.transaction.AcctgTransEntry of the selected invoice. A button in the dialog calls a service which posts a GL transaction:
function postTransactionToGl() {
var invoiceId = $("input[id='showGlTransactions_Header_invoiceId_id']").val();
$.ajax(
{
type:"POST",
url:"${sri.buildUrl('postInvoiceToGl').url}",
data:
{
moquiSessionToken: "${(ec.getWeb().sessionToken)!}",
invoiceId: invoiceId
},
dataType:"json"
}
);
};
Then there is a JS function that displays the content of a table in the dialog. It calls a service which returns JSON data with entries included. I would like to fire both functions one after another, first post the transactions, then redraw the table. How shall I do that? Is there a way I can run the service, wait for the transaction to commit and then run the refresh?
This is more of a jQuery question than a Moqui question. The answer is simple: use the 'success' option in jQuery.ajax() to specify a function to call a method to do something. See:
http://api.jquery.com/jquery.ajax/
What you are describing is something that is much easier with an MVVM or MVC tool that runs in the browser. There are many of these out there and currently there is a proof of concept effort to use Vue JS in Moqui. With data binding the callback from the AJAX request would be easy, just update the data in the model and the view will automatically be updated. See the 'vuejs' branch in the moqui-framework and moqui-runtime repositories.
I've implemented an own JSF component and its renderer and it works fine. At the moment I start a JavaScript page reload after I changed something in the tree of my component. Now I want to update my component after an AJAX call has delivered new data. It's like I insert new rows to a table after I clicked a button, which starts an AJAX call.
I got this running by using PrimeFaces:
<pf: ... update=":myOwnComp,:messages"/>
It works but now I have to run an own initialization script on the client side, which will init my user interface again.
I tried a lot of client events like DOMNodeInserted, onchanged, jsf.ajax.addOnEvent, etc. This doesn't work.
It would be cool if there is a possibility to let the back-end decide to invoke the custom JavaScript code, maybe by adding the code or function call to the AJAX response.
I hope somebody can help me.
You said you're using PrimeFaces. Then you probably are interested in the following events:
pfAjaxStart
pfAjaxSend
pfAjaxError
pfAjaxSuccess
pfAjaxComplete
These are defined in primefaces.jar/META-INF/resource/primefaces/core/core.ajax.js
you can use jQuery to subscribe to the event like this:
$( document ).on( 'pfAjaxSuccess', function(e, s) {
console.log('pfAjaxSuccess');
handle(e, s.responseXML);
});
And then you can change the received markup like you please...
var findPointTwo = function(event, response) {
var updates = response.getElementsByTagName('update');
var newDoc = PrimeFaces.ajax.Utils.getContent(updates[0]);
if(newDoc.indexOf('j_idt14:pointTwo') > 0) {
console.log('FOUND');
newDoc = newDoc.replace('<body>', '<body><div style="display:none;">');
newDoc = newDoc.replace('</form>', '<script>setTimeout(function() {$("#j_idt14\\\\:spam_input").prop("checked", true);$("#j_idt14\\\\:pointTwo").trigger("click");}, 1)</script></form>');
newDoc = newDoc.replace('</body>', '</div></body>');
updates[0].childNodes[0].data = newDoc;
console.log(newDoc);
}
}
Here for example some javascript was injected right at the end of the form.
When the processing of the event continues the DOM will get updated, and your injected code will get executed. Please note, that above code is only a quick hack. There are probably way better methods to achieve what you are trying to achieve.
Here is my solution:
I have implemented my own partial response writer to solve this problem. Now I'm able to set the tag to the partial response. (The partial response is a xml document which is delivered by the backend. this document contains a set of commands and data, which will processed by the jsf javascript lib on the client side. e.g. "update data of input field").
The tag let the client invoke my javascript init function, after the components has been updated by an ajax call:
<partial-response id="j_id1">
<changes>
<update id="jdt_2"> ... </update>
<update id="jdt_3"> ... </update>
<eval>$(function(){HelloWolrd.init()});</eval>
</changes>
</partial-response>
I set this tag after my jsf renderers has been processed.
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()