Getting textbox values from a CefSharp browser using javascript - javascript

I've got a winforms app that has a ChromiumWebBrowser control and some basic windows controls. I want to be able to click a button, call javascript to get the value of a textbox in the browser, and copy the returned value to a textbox in the winforms app. Here is my code:
string script = "(function() {return document.getElementById('Email');})();";
string returnValue = "";
var task = browser.EvaluateScriptAsync(script, new { });
await task.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
if (response.Success && response.Result != null)
{
returnValue = (string)response.Result;
}
}
});
txtTarget.Text = returnValue;
The result that comes back however is just "{ }". I've loaded the same web page in Chrome and executed the same javascript in the dev tools and I get the textbox value as expected.
The demo I looked at had sample code, simply "return 1+1;", and when I tried that I was getting the value "2" returned instead of "{ }". Interestingly, when I tried
string script = "(function() {return 'hello';})()";
I was still getting "{ }", almost as though this doesn't work with strings.
I've been scratching my head at this for a while and haven't been able to figure out how to solve this. Am I making a very basic syntax error or is there something more complicated going on?

So I think I've figured it out:
string script = "(function() {return document.getElementById('Email').value;})();";
string returnValue = "";
var task = browser.EvaluateScriptAsync(script);
await task.ContinueWith(t =>
{
if (!t.IsFaulted)
{
var response = t.Result;
if (response.Success && response.Result != null)
{
returnValue = response.Result.ToString();
}
}
});
txtTarget.Text = returnValue;
Removing the args object from EvaluateScriptAsync seemed to fix the issue. Not sure what the problem was - perhaps it was trying to run the javascript function with an empty args object when it shouldn't take any parameters?
Either way, it's resolved now.

public void SetElementValueById(ChromiumWebBrowser myCwb, string eltId, string setValue)
{
string script = string.Format("(function() {{document.getElementById('{0}').value='{1}';}})()", eltId, setValue);
myCwb.ExecuteScriptAsync(script);
}
public string GetElementValueById(ChromiumWebBrowser myCwb, string eltId)
{
string script = string.Format("(function() {{return document.getElementById('{0}').value;}})();",
eltId);
JavascriptResponse jr = myCwb.EvaluateScriptAsync(script).Result;
return jr.Result.ToString();
}

Related

JSON.parse(...).forEach is an error on published website

i'm currently working with rendering some graphs on a web mvc project. The graphs already render on my machine when i'm debugging the code, but the moment I publish it on the IIS of my QA server, I get the following error on console
TypeError: JSON.parse(...).forEach is not a function
Here's the a snippet of the code I'm currently working
ajaxPostConstancy.done(function (html) {
Utils.Alerts.HideGif();
var data = {};
var category = [];
var colors = [];
JSON.parse(html).forEach(function (e) {
category .push(e.date);
colors.push(e.color);
data[e.date] = e.data1;
})
....
any ideas of what's going on?
Edit: the html var inside the JSON.parse is te string returned by this code
public async Task<string> GetCompositionGraph(string contract, string methodName)
{
string preFormat = null;
try
{
string method = _configuration["Position:method:" + methodName];
PositionBL _bl = new PositionBL(Request, Response, _baseUri, method);
object model = await _bl.PostCompositionGraph(contract);
preFormat = JsonConvert.SerializeObject(model);
}
catch(Exception ex)
{
ViewBag.error = ex.Message;
}
return preFormat;
}
edit 2: the content of html variable which is generated by the code on the first edit:
html content:
[{"color":"#162ECB","date":"20","data1":1122954.8708},{"color":"#E03473","date":"00","data1":1323061.6168},{"color":"#CE029D","date":"26","data1":29982.2271}]
and this picture is the result I get from the JSON.parse when I debug my website
Edit 3: Visual input
The explorer console when the sites is deployed on my localhost for debugging
The explorer console while checking the site published on QA server
Edit 4: So i narrowed it down to the fact that the error comes when I debug the websit in Release mode, so that's kind of a step foward
If preformat returns null or an object forEach() will throw an error.
ajaxPostConstancy.done(function (html) {
Utils.Alerts.HideGif();
var data = {};
var category = [];
var colors = [];
var parsedDatas = JSON.parse(html)
if (Array.isArray(parsedDatas)) {
parsedDatas.forEach(function (e) {
// logic here
});
} else {
console.warn('This is not an array : ', html)
}
...
The forEach() method calls a function once for each element in an array while the JSON.parse() makes the html an object.

JavaScript chaining functions, last methods returns 'undefined'

My app receives a base64 encoded value that is also encrypted. The data can come in a few different ways so I wanted to create chain-able methods to keep the code clean and modular.
I want to be able write: decryptionChain.decodeBase64(b64Value).stringToBuffer().finallyDecrypt();
When I run the code, the last property method "finallyDecrypt" returns as undefined.
Why is the "finallyDecrypt" method coming back as undefined? The rest all works and if I run ecryptionChain.decodeBase64(b64Value).stringToBuffer() I get back the Buffer I expect. It is only when the finallyDecrypt is chained in that I error out.
Here is the code:
function decrypt(encrypted) {
var decipher = crypto.createDecipheriv(algorithm, password, iv);
decipher.setAuthTag(encrypted.tag);
var dec = decipher.update(encrypted.content, 'hex', 'utf8');
dec += decipher.final('utf8');
return dec;
}
var decryptionChain = {
currentValue:"",
decodeBase64: function (encryptedValue){
this.currentValue = new Buffer(encryptedValue.toString(), "base64");
return this;
},
stringToBuffer: function() {
if (this.currentValue) {
myBuffer = JSON.parse(this.currentValue, function (key, value) {
return value && value.type === 'Buffer'
? new Buffer(value.data)
: value;
});
}
return myBuffer;
},
finallyDecrypt : function(myBuffer){
if(myBuffer){
decrypt(myBuffer);
}
return this;
}
};
From the code shown, I have spotted some issues.First:
decryptionChain != decryptChain If its just a typo in the question, then disregard, if its not, please reffer to that.
Please, use the var to decrease possibilities of scope errors, or "scoped variables" being left behind.
Second, dont use a string as a Boolean.
Third, you seem to have an issue with the return value && value.type === 'Buffer' ? new Buffer(value.data) : value;, please assign before returning (not necessary, but simpler)

Why does my dojo xhrPost request's response always end up in error handler?

My javascript:
var params = {};
params.selectedCurrency = 'USD';
params.orderIdForTax = '500001';
var xhrArgs1 = {
url : 'UpdateCurrencyCmd',
handleAs : 'text',
content : params,
preventCache:false,
load:function(data){
alert('success!');
},
error: function(error){
alert(error);
//the alert says 'SyntaxError: syntax error'
},
timeout:100000
};
dojo.xhrPost(xhrArgs1);
I tried debugging with firebug, i do get the appropriate response (i think). Here it is;
/*
{
"orderIdForTax": ["500001"],
"selectedCurrency": ["USD"]
}
*/
The comments /* and */ are somehow embedded automatically cuz the url im hitting with xhrPost is actually a command class on ibm's websphere commerce environment. Can anyone tell me what am i doing wrong here?
Server code
public void performExecute() throws ECException {
try{
super.performExecute();
double taxTotal;
System.out.println("Updating currency in UpdateCurrencyCmd...");
GlobalizationContext cntxt = (GlobalizationContext) getCommandContext().getContext(GlobalizationContext.CONTEXT_NAME);
if(requestProperties.containsKey("selectedCurrency"))
selectedCurrency = requestProperties.getString("selectedCurrency");
else
selectedCurrency = cntxt.getCurrency();
if(requestProperties.containsKey("orderIdForTax"))
orderId = requestProperties.getString("orderIdForTax");
OrderAccessBean orderBean = new OrderAccessBean();
cntxt.setCurrency(selectedCurrency.toUpperCase());
orderBean.setInitKey_orderId(orderId);
orderBean.refreshCopyHelper();
orderBean.setCurrency(selectedCurrency.toUpperCase());
orderBean.commitCopyHelper();
TypedProperty rspProp = new TypedProperty();
rspProp.put(ECConstants.EC_VIEWTASKNAME, "AjaxActionResponse");
setResponseProperties(rspProp);
}catch(Exception e){
System.out.println("Error: " + e.getMessage() );
}
}
The problem was with my client side code, weirdly.
load:function(data){
data = data.replace("/*", "");
data = data.replace("*/", "");
var obj = eval('(' + data + ')');
alert('Success');
}
Its weird but this worked. Lol.
I guess the problem is with coment-filtering option of handle as method.
The response should be comment filered as below.
See tha AjaxActionResponse.jsp (WCS)
vailable Handlers
There are several pre-defined contentHandlers available to use. The value represents the key in the handlers map.
text (default) - Simply returns the response text
json - Converts response text into a JSON object
xml - Returns a XML document
javascript - Evaluates the response text
json-comment-filtered - A (arguably unsafe) handler to preventing JavaScript hijacking
json-comment-optional - A handler which detects the presence of a filtered response and toggles between json or json-comment-filtered appropriately.
Examples

Appending to External Browser Window

I have a Windows app that contains a browser control that loads pages from my website. However, due to the Windows app, I cannot debug Javascript in the usual ways (Firebug, console, alerts, etc).
I was hoping to write a jQuery plug-in to log to an external browser window such that I can simply do something like:
$.log('test');
So far, with the following, I am able to create the window and display the templateContent, but cannot write messages to it:
var consoleWindow;
function getConsoleWindow() {
if (typeof (consoleWindow) === 'undefined') {
consoleWindow = createConsoleWindow();
}
return consoleWindow;
}
function createConsoleWindow() {
var newConsoleWindow = window.open('consoleLog', '', 'status,height=200,width=300');
var templateContent = '<html><head><title>Console</title></head>' +
'<body><h1>Console</h1><div id="console">' +
'<span id="consoleText"></span></div></body></html>';
newConsoleWindow.document.write(templateContent);
newConsoleWindow.document.close();
return newConsoleWindow;
}
function writeToConsole(message) {
var console = getConsoleWindow();
var consoleDoc = console.document.open();
var consoleMessage = document.createElement('span');
consoleMessage.innerHTML = message;
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
consoleDoc.close();
}
jQuery.log = function (message) {
if (window.console) {
console.log(message);
} else {
writeToConsole(message);
}
};
Currently, getElementById('consoleText') is failing. Is what I'm after possible, and if so, what am I missing?
Try adding
consoleDoc.getElementById('consoleText');
right before
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
If the line you added is the one that fails, then that means consoleDoc is not right, if the next line is the only one that fails then ..ById('consoleText') is not matching up
If I don't close() the document, it appears to work as I hoped.

Posting data into JavaScript from an URL

I have a javascript on my server, and i need to set a value / calling a function inside the javascript when calling a URL. Is there anyway of doing that ?
UPDATE:
<script type="application/x-javascript" src="test-test.js"></script>
Thats how it its loaded on the HTML site. And I want to call the function test(e,e) inside test-test.js, by putting in the URL in a browser with some values for e,e..
Unless you are using one of the few web servers that employs server-side JavaScript, your script is going to run in the browser after the page is loaded. If you want to include information from the URL in your script (and this assumes that you can use a query string without changing the server's behavior), you can use window.location.search to get everything from the question mark onwards.
This function will return either the entire query string (without the question mark) or a semicolon-delimited list of values matching the name value you feed it:
function getUrlQueryString(param) {
var outObj = {};
var qs = window.location.search;
if (qs != "") {
qs = decodeURIComponent(qs.replace(/\?/, ""));
var paramsArray = qs.split("&");
var length = paramsArray.length;
for (var i=0; i<length; ++i) {
var nameValArray = paramsArray[i].split("=");
nameValArray[0] = nameValArray[0].toLowerCase();
if (outObj[nameValArray[0]]) {
outObj[nameValArray[0]] = outObj[nameValArray[0]] + ";" + nameValArray[1];
}
else {
if (nameValArray.length > 1) {
outObj[nameValArray[0]] = nameValArray[1];
}
else {
outObj[nameValArray[0]] = true;
}
}
}
}
var retVal = param ? outObj[param.toLowerCase()] : qs;
return retVal ? retVal : ""
}
So if the URL was, say:
http://www.yoursite.com/somepage.html?name=John%20Doe&occupation=layabout
if you call getUrlQueryString() you would get back name=John Doe&occupation=layabout. If you call getUrlQueryString("name"), you would get back John Doe.
(And yes, I like banner-style indents. So sue me.)
You can use address plugin to be able to pass some condition in urls trough # symbol: http://my_site/my_page#your_condition
in the html you can write something like this:
<script>
$(function(){
// Init and change handlers
$.address.init().change(function(event) {
if (event.value == "your_condition")
run_my_finction();
});
)};
<script>
See this exaple for the futher help.
If you want to execute JavaScript from the browsers' address bar, you can use a self-invoking function:
javascript:(function () {
alert('Hello World');
/* Call the JavaScript functions you require */
})();

Categories