Python and reading JavaScript variable value - javascript

I am very new to Python programming, so please bear with me.
I have an HTML file with several div layers. This file is opened in a webkit.WebView object. Each div layer saves a value in a global variable (JavaScript) when clicked upon.
How can I read the value of that global JavaScript variable from my Python script?
I found some answers but they don't seem to fit my situation (but I can be wrong, of course):
Passing JavaScript variable to Python
Parse JavaScript variable with Python
[EDIT]
I'm using webkit.WebView because I have to show this in an existing glade (libglade) application.

try this out. It uses the addToJavaScriptWindowObject method to add a QObject into the QWebView. This will enable communication between your python script and the HMTL/Javascript in your webview. The example below will let you change the value of the javascript global variable message to whatever value you want through a JavaScript prompt, then whenever you click on the Python Print Message link it will execute your python code that will take the javascript value and just print it to the console.
import sys
from PyQt4 import QtCore, QtGui, QtWebKit
HTML = """
<html><body onload="broker.print_msg(message)">
<script>var message = 'print_msg message'</script>
Change Message<br/>
Python Print Message
</body></html>
"""
class Broker(QtCore.QObject):
#QtCore.pyqtSlot(str)
def print_msg(self, data):
print data
app = QtGui.QApplication(sys.argv)
view = QtWebKit.QWebView()
view.page().mainFrame().addToJavaScriptWindowObject('broker', Broker(view))
view.setHtml(HTML)
window = QtGui.QMainWindow()
window.setCentralWidget(view)
window.show()
sys.exit(app.exec_())

I know this is old question, but still answering it with the hope that it will be useful to someone.
You can use alert handler and read the value in python side. http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#WebKitWebView-script-alert
Example on button click you can have action that says
alert("Button Clicked");
On python side you will get the alert notification and you can parse the string. If the object is not a simple object, you will have to convert it to string format that can be parsed on python side. I have seen few examples of alert handler. https://github.com/nhrdl/notesMD/blob/master/notesmd.py is one that I wrote and uses alert handlers to pass lot of data between javascript and python

Related

UI page (jelly) - how to use dynamic data in g:evaluate

TLDR: How to access i.e. variables or say values in a input field - within the evaluate?
Hello :)
The short of it, is that I have a UI page (modal opened by UI action) with an input field. Onchange, this field needs to run some serverside code that validates the field. The main issue is actually accessing the input data within the evaluate. It doesn't seem posssible to access variables or HTML fields. I can fetch variables set in the modal via setpreferences using RP, but the input data is created within the page, not the UI action.
Is there a way to pass data to an evaluate, or at least have it fetch it itself? I'm seriously considering just creating a script include called via glideajax to do the job.
Help would be much appreciated. Brgds.
Tried fetching variables within g:evaluate, both from client script and HTML id's.
HTML/Jelly code:
<g:cs_ui_text_field class="p" name="input_field_value" id="input_field_value" value="" onchange="validateRequest();" /> <!-- Dont mind the macro name, its just a text field (input). -->
<g2:evaluate var="jvar_gr" jelly="true">
var return_value = '${input_field_value}'; // Attempting to fetch field value wont work.
return_value ;
</g2:evaluate>
Client script:
function validateRequest() {
// ValidateRequest calls evaluate jvar_gr, and alerts the return value.
alert('$[jvar_gr]');
}
As far as I know, you'd need to do this via a GlideAjax call like you mentioned within your client script. Jelly code is used to perform server-side rendering. That means that when your browser requests the UI page from ServiceNow, ServiceNow's servers will run the jelly code. That involves running code within the g2:evaluate tags, and also substituting your macro with raw HTML that your browser can understand (browser don't understand jelly, it only understands how to render HTML). This raw HTML is then sent to your browser to show your UI page.
So the code within your <g2:evaluate></g2:evaluate> tags run before the user even sees your page and has a chance to start interacting with it. So you'll need to perform your server-side calls within your client script component of your UI page. To access an input value using a client script, you can use gel:
function validateRequest() {
var gr = gel("input_field_value").value; // read the value from the input
var ga = new GlideAjax(/* your script include */);
ga.addParam('sysparm_name', /* method name */);
ga.addParam(/* param name */, gr);
ga.getXMLAnswer(function(answer) {
// do what you need to do to update your UI.
});
}
Keep in mind that a UI page's processing script can also run server-side code, and can access input variables. But this usually only comes in handy if you're submitting a form (created with <g:form>), and not trying to run code on change. However, this might be useful depending on when you need to make your server-side calls and your actual use case.

How to display a global javascript variable in typo3 using typoscript?

I would like to output a global variable "elemenId" that is created by a javascript in typo3.
The javascript writes the ID of the touched html element in the global variable elementId:
document.addEventListener("touchstart", (e) => {
// get elementId of touched element and save as global variable elementId for further processing
window.elementId = e.target.id;
});
I would like to display the elementId value in typo3.
Is there any chance to access this variable in typo3 using typoscript? Something like:
lib.global_variable = COA_INT
lib.global_variable {
20 = TEXT
20.data = GP : elementId
}
Is there any other way to achieve that?
Thanks a lot for your help!
What do you mean with global variable elementId?
global in what context? PHP? javascript? TYPO3?
You need to distinguish between server(webserver with PHP/TYPO3) and client(Browser with javascript).
How can data be exchanged?
Anything in PHP can be written in the rendering process. The output is HTML, including CSS and javascript. Alternatively TYPO3/PHP can generate other formats like JSON, XML, PDF or CSV.
In this way PHP can transfer some information to Javascript by generating a piece of javascript which assigns the value to a (global) javascript variable:
$output = '<script>js_var = "' . $php_var . '";</script>';
echo $output;
Now the client/browser can use the value by executing this javascript code.
On the other hand any value from your client/browser can only be transferred to the server/PHP by doing a new server request. This can be done with a new page request with arguments (either POST or GET) and the server can respond with a appropriate reaction.
Or you do an AJAX call and you will get a appropriate response and some javascript can insert the response in the current document.
Another option would be that javascript only acts locally in the browser and used the information available to generate or modify the current HTML-document. that might be showing the ID of any clicked HTML element in a special HTML object.

Set Session value using Javascript and retrieving the same using razor umbraco

I have written following code let say in Page 1
<a Onclick="setSessionValue()" href="page2"></a>
<script type="text/javascript">
function setSessionValue()
{
var selectedCarNoideId = "1026";
'<%Session["BannerNoideID"] = "'+ selectedCarNoideId +'";%>'
alert('<%=Session["BannerNoideID"]%>');
}
</script>
And now retrieving session value on other page (Scripting File .chtml) using following code.
<h2>Session-:#Session["BannerNoideID"] </h2>;
In the Page 1 alert PopUp displays "1026" as session value
But In Page 2 tag display following value as a output of session .
"Session-:'+ selectedCarNoideId +'"
Am I missing any thing ?
You're mixing javascript and server-side code in such a way that the javascript isn't being evaluatd as you expect.
The Server side session variable is literally being set to '+ selectedCarNoideId +' as the page is being rendered. Javascript in this case is doing nothing to set the session value.
Although why you're getting the alert message to display 1026 is anyone's guess - is the BannerNoideID session variable being set elsewhere as well perhaps?
If you're trying to save a variable generated client-side with Javascript in the session on the server, you will need to submit it.
One way to do it would be to create a simple MVC Controller (WebAPI by default is sessionless) and then POST the value to it using Ajax or a form post.
Alternatively, you could pass the id through on the QueryString to the next page or something like that - that approach is probably the simplest.
Without knowing more about your setup, workflow and business logic I can't really suggest much more.

"Expression does not produce a value" in javascript, vb.net

In the Create View of the "Deal" model, I've defined a javascript function that creates a new object in a List Property when clicking a button.
I get the error "expression does not produce a value". I'm not expecting a value, I only need to create a new empty object in the list, so I don't understand this error.
javascript in my view, the line that adds the new Period to the list throws the error:
<script type="text/javascript">
function addRow() {
#Model.Periods.Add(New DealPeriod());
...
}
</script>
"Deal" Model:
Public MustInherit Class Deal
...
<Display(name:="Periodos")>
Public Property Periods As New List(Of DealPeriod)
There are two issues here - to cover the issue in the question "expression does not produce a value":
The #symbol here means "output the result of the following to the http response stream".
As List.Add() returns void, there is nothing to send to the response stream, so it gives you that error message.
Put another way, the # needs a value and List.Add() does not generate a value.
The second issue is that it appears you are mixing server-side execute with client-side execution (note I don't say server-side/client-side code, that's allowed in a similar way to how you have it). It appears you want to add a new "DealPeriod" when "addRow" is called - that's simply not how it works. The VB.Net code runs on the server and the javascript code runs on the client, in the browser. They are not linked together.
There are ways to link them such as an ajax call or signalr.
You are expecting #Model.Periods.Add(New DealPeriod()); to run when that javascript function is called, but that is not what is happening. The inline VB code is run server-side before sending HTML to the client.
With your webpage open, view source of the page and observe the code that gets rendered in that javascript function. You will not see that line of code.
What you want to do is make an ajax call to a controller that will perform the logic you want.

MVC 5 - How to send an Excel file to the client?

I have a Bootstrap application that shows a list of data. I have a button at the bottom of the page that, when clicked, creates an Excel file and sends it back to the client.
The link (button) the user clicks to start the process is as follows:
<li>Export list to Excel</li>
The JavaScript function that gets called looks like this:
function ExportToExcel() {
var Url = "/UserLocation/ExportToExcel";
$.get(Url);
}
I know this probably isn't right, but it does correctly call my C# function that creates the Excel spreadsheet.
My C# function looks like this:
public ActionResult ExportToExcel()
{
var locationList = this.UserLocationData.GetList(this.AccountRowId).AsEnumerable();
ExcelPackage package = Common.Excel.CreateExcelFile(locationList);
var cd = new System.Net.Mime.ContentDisposition
{
// for example foo.bak
FileName = "ExcelTest.xlsx",
// Always prompt the user for downloading, set to true if you want the browser to try to show the file inline
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(package.GetAsByteArray(), "application/force-download");
}
At the moment, when the user clicks the button, my C# function is called, but nothing is returned to the client. I suspect my JS function is not correct, but I don't really know what to do to make it correct. I also don't know what MIME type to use in my C# method (the last line in my C# method). Is there a better way to do all this? I am fairly new to JavaScript.
With $.get() you're getting the data through ajax. The browser will get the file content in the ajax response, but there is no way to offer the user to save this data as a file. (Well, technically is possible in most browsers, but not in all of them, although some more are supported with this js. But obviously it's overkill for this case. Thanks to zerkms for his comment).
The solution is much simpler, use the old good window.open(url), so the file is opened in a new browser window, and the user will be invited to open or save it (that depends on the browser configuration).
Or use directly a link like this:
<li><a href ="/UserLocation/ExportToExcel" class="btn btn-info btn-sm">
Export list to Excel</a></li>
(unless your js function does some extra processing).

Categories

Resources