Flex Mobile webView.loadURL() not working - actionscript-3

I have a stageWebView in my flex Mobile app. I am trying to call a javascript function passing along some arguments.
protected function list1_changeHandler(event:IndexChangeEvent):void
{
var list:List = event.target as List;
var selectedString:String = list.selectedItem.label;
webView.loadURL("javascript:doIt("+selectedString+")");
}
Then I have my javascript code trying to use the selectedString I passed. It does not seem to be getting passed to the javascript. If I however pass a raw string like below it does work. Do I have quotes wrong or something else in the above code? Or can you not pass Objects from flexs?
protected function list1_changeHandler(event:IndexChangeEvent):void
{
var list:List = event.target as List;
var selectedString:String = list.selectedItem.label;
webView.loadURL("javascript:doIt('yeah')");
}
EDIT
I had the quotes wrong.Should have been:
webView.loadURL("javascript:doIt('"+selectedString+"')");

Try
protected function list1_changeHandler(event:IndexChangeEvent):void
{
var list:List = event.target as List;
var selectedString:String = list.selectedItem;
var url:String = "javascript:doIt('" + selectedString + "')";
webView.loadURL(url);
}

Related

google.script.run.withSuccessHandler() returns Undefined

I created an array in a separate GS file using the code provided below. I tried calling it in my HTML file. My goal is to compare the contents the array to the parameter email. However, the value returned by google.script.run.withSuccessHandler() is undefined
//in GS
function mailGetter()
{
//open sheet
var sheet = SpreadsheetApp.openByUrl("https://sheet.url").getSheetByName("Email Sheet").activate();
//get size of given row range
var row_data_email = sheet.getRange("C2:C").getValues();
var emailArray = row_data_email.join().split(',').filter(Boolean);
Logger.log(emailArray);
return emailArray;
}
//in HTML
function checkEmail(email)
{
var reg1 = /^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$/;
var arraySize = google.script.run.withSuccessHandler(misc).sizeGetter();
console.log(arraySize);
var emailArray = new Array(arraySize);
emailArray = google.script.run.withSuccessHandler(misc).mailGetter();
console.log(emailArray);
if (reg1.test(email) == false)
{
emails.style.border = "1px solid red";
document.getElementById('submitBtn').disabled = true;
}
else if (reg1.test(email) == true)
{
emails.style.border = "1px solid green";
document.getElementById('submitBtn').disabled = false;
}
for (var row = 0; row < arraySize; row++)
{
if (emailArray[row][0] == email)
{
emails.style.border = "1px solid green";
document.getElementById('submitBtn').disabled = false;
break;
}
else if (emailArray[row][0] != email)
{
emails.style.border = "1px solid red";
document.getElementById('submitBtn').disabled = true;
}
}
}
function misc()
{
console.log("Pass");
}
Issue:
Using a asynchronous function's(google.script.run) return value, which will always be undefined.
Solution:
Use successHandler as mentioned in another answer or We can use promises with async/await.
Snippet:
/*Create a promise around old callback api*/
const p = func =>
new Promise(resolve=>
google.script.run.withSuccessHandler(resolve)[func]()
);
async function checkEmail(email) //modified
{
var arraySize = await p('sizeGetter');//Wait to resolve
console.log(arraySize);
//var emailArray = new Array(arraySize);
var emailArray = await p('mailGetter');//Wait to resolve
console.log(emailArray);
//....
}
Note:
It's better to reduce the number of calls to the server. If you can combine both Getters to a single server function, it'll be better.
The above is a snippet showing how to use async/await. But if you wait for each response from the server as shown above, your front end/UI will be slow. Wait only if absolutely necessary. Calls to server should be non-blocking/asynchronous.
References:
Promises
async
await
Issue is in these lines:
emailArray = google.script.run.withSuccessHandler(misc).mailGetter();
console.log(emailArray);
You're trying to execute mailGetter() and expecting it to return value which you're storing in emailArray but this method is asynchronous and does not return directly
Rather you'll get the value in callback which you have defined as SuccessHandler
Suggested solutions :
Calling Apps Script functions from a template : https://developers.google.com/apps-script/guides/html/templates#apps_script_code_in_scriptlets
Calling Apps Script APIs directly : https://developers.google.com/apps-script/guides/html/templates#calling_apps_script_apis_directly
Pushing variables to templates : https://developers.google.com/apps-script/guides/html/templates#pushing_variables_to_templates
Reference : https://developers.google.com/apps-script/guides/html/reference/run#myFunction(...)

GET request Flex / Actionscript 3

Struggling to find any documentation to do a simple GET request to a URL to return JSON in Actionscript / Flex.
Anyone know
Use the URLLoader API.
var myJSON :Object; //listing as per "key:" with "value"
var str_JSON: String = ""; //if you need text String not data Object
var siteloader :URLLoader = new URLLoader( new URLRequest( your_URL ) );
siteloader.addEventListener(Event.COMPLETE, whenSiteLoaded);
function whenSiteLoaded( evt :Event ) :void
{
myJSON = JSON.parse(evt.target.data); //get into Object
str_JSON = evt.target.data; //get into String
//... any other code
}
You should add to the above the listeners for error conditions (eg: a "file not found" situation)

Inject html/javascript-code into Flex AS3 HTML class

I need to Inject html/javascript-code into every HTML that gets loaded.
The program uses the HTML class.
I disassembled the original Flex3 files and found this.
The important? functions I modified/tested:
public function set htmlText(value:String) : void
{
_htmlText = value;
htmlTextChanged = true;
_location = null;
locationChanged = false;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
dispatchEvent(new Event("htmlTextChanged"));
}
public function set location(value:String) : void
{
_location = value;
locationChanged = true;
_htmlText = null;
htmlTextChanged = false;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
dispatchEvent(new Event("locationChange"));
}
I successfully changed the code of set location and managed that only http://www.example.com/ gets loaded.
However, the htmlText setter seems not to get called when the location is set using location.
This is what I have tried:
public function set htmlText(value:String) : void
{
_htmlText = "<html><h1>test</h1></html>" + value;
htmlTextChanged = true;
_location = null;
locationChanged = false;
invalidateProperties();
invalidateSize();
invalidateDisplayList();
dispatchEvent(new Event("htmlTextChanged"));
}
I need to have a look in flash.net.HTMLloader but I cannot locate the file.
I hope someone can help me and tell me where the HTML-code gets loaded from the location and where it gets rendered so I can modify it before.
Thanks in advance.
I don't know what do you want to inject to your html content, but I think that you can do it when the complete event on the HTMLLoader of your HTML component is fired, using the window object which is :
The global JavaScript object for the content loaded into the HTML control..
So you can use it ( the window object ) as in any JavaSript code.
// for the example, I took the page of your current question
var url:String = 'http://stackoverflow.com/questions/32348824/inject-html-javascript-code-into-flex-as3-html-class';
html_content.location = url;
html_content.htmlLoader.addEventListener(Event.COMPLETE, on_complete);
And
protected function on_complete(e:Event): void
{
var html_loader:HTMLLoader = html_content.htmlLoader;
var document = html_loader.window.document;
var _head = document.getElementsByTagName('head')[0];
// create a new css class
var _class = '.akmozo { background: #ff9900; color: white; padding: 2px; }';
var _style = document.createElement('style');
_style.appendChild(document.createTextNode(_class));
// create a new js function
var _js = 'function click_me(){ alert("Hello, how are you ?"); }';
var _script = document.createElement('script');
_script.appendChild(document.createTextNode(_js));
_head.appendChild(_style);
_head.appendChild(_script);
// change the page's top bar background color to green
if(document.querySelector('.topbar-wrapper'))
{
document.querySelector('.topbar-wrapper').style.backgroundColor = 'green';
}
// edit the title of your question,
// apply the new css class and call the js function
if(document.querySelector('.question-hyperlink'))
{
document.querySelector('.question-hyperlink').innerHTML += ' [ edited by <span class="akmozo" onclick="click_me()">AKMOZO</span> ]';
}
// change the SO logo to my avatar
if(document.getElementById('hlogo'))
{
document.getElementById('hlogo').style.backgroundImage = 'url(https://i.stack.imgur.com/YAKpv.png?s=50)';
document.getElementById('hlogo').style.backgroundRepeat = 'no-repeat';
}
// do some changes in your comment
if(document.querySelector('#comment-52605069'))
{
document.querySelector('#comment-52605069 .comment-copy').style.color = 'green';
document.querySelector('#comment-52605069 .comment-copy').style.fontWeight = 700;
document.querySelector('#comment-52605069 .comment-copy').style.fontSize = '24px';
document.querySelector('#comment-52605069 .comment-user').innerHTML = '<span class="akmozo">akmozo</span>';
}
}
This code will give you something like this :
Of course I tried just to give you an example of what you can do, you have to improve and adapt this code to your needs.
Hope that can help.

Passing state/data to Google Apps Script ServerHandler

I am trying to work out how I can pass some arbitrary state to a ServerHandler in Google Apps Script. The following code illustrates the question - can anybody help?
Thanks.
function myFunc(e) {
// want to get my data object back out here..?
}
function setUp()
{
var data = getMyDataArray();
// ... set up UI...
var h = app.createServerHandler('myFunc');
// How do I passs my data object to the myFunc handler?
flow.add(app.createButton().setText("OK").addClickHandler(h));
app.add(flow);
s.show(app);
}
You can use Hidden elements to store arbitrary data and send it along with a server handler invocation. The issue is that the the element can only store a string. But you can solve this using JSON.
function myFunc(e) {
var yourObj = Utilities.jsonParse(e.parameter.yourObject);
//do what you need
}
function setUp()
{
var data = getMyDataArray();
// ... set up UI...
var hidden = app.createHidden("yourObject", Utilities.jsonStringify(data));
var h = app.createServerHandler('myFunc').addCallbackElement(hidden);
flow.add(app.createButton().setText("OK").addClickHandler(h));
app.add(flow);
s.show(app);
}

Flash hyperlink - changing var name in url

I have trouble with hyperlink in flash on site. As site is in CMS, with different
stages of approval I do not know exact url, so
function piClick(e:MouseEvent):void
{
var url:String = "/cms__Main?name=Target_name";
var request:URLRequest = new URLRequest(url);
try {
navigateToURL(request, '_self');
} catch (e:Error) {
trace("Error occurred!");
}
}
does not work, as cms_Main changes according to stage of site. What I probably need to do is:
grab url (or part after last "/" if that is even possible)
change "name" variable inside String
f.e
https://domain_name/.../status?name=Name_I_need_to_swap&sname=Country_name&..
stage.loaderInfo.url will get you the address of the swf itself so it won't get you the full address, the query or the hash tag. You can, however, grab all this information using Javascript.
import flash.external.ExternalInterface;
function getFullAddress():String {
if (ExternalInterface.available) {
var href:String = ExternalInterface.call('function(){return window.location.href}');
if (href) return href.toString();
}
throw new Error('Make sure JS is enabled.');
}
var fullAddr:String = getFullAddress();
EDIT: Here's how you can get and modify all that you're asking.
import flash.external.ExternalInterface;
import flash.net.URLVariables;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.navigateToURL;
function getFullAddress():String {
if (ExternalInterface.available) {
var href:String = ExternalInterface.call('function(){return window.location.href}');
if (href) return href.toString();
}
throw new Error('Make sure JS is enabled.');
}
function getQuery(fullAddr:String):URLVariables {
if (!fullAddr.match(/\?[^#]/)) return new URLVariables();
var q:String = fullAddr.replace(/^.*?\?([^#]+)(#.*)?$/,'$1');
return new URLVariables(q);
}
function getAddress(fullAddr:String):String {
return fullAddr.replace(/\?.*/,'').replace(/#.*/,'');
}
function getRequest(url:String,query:URLVariables=null,method:String='GET'):URLRequest {
method = URLRequestMethod[method] || 'GET';
var req:URLRequest = new URLRequest(url);
req.method = method;
if (method == 'GET' && query != null) {
req.url += '?' + query.toString().replace(/%5f/gi,'_').replace(/%2d/gi,'-');
// this is because dash and underscore chars are also
// encoded by URLVariables. we want to omit this.
return req;
}
req.data = query;
return req;
}
var fullAddr:String = getFullAddress();
var addr:String = getAddress(fullAddr);
var query:URLVariables = getQuery(fullAddr);
query.name = 'Name_I_need_to_swap';
query.sname = 'Country_name';
// add as many variable-value pairs as you like
// and don't worry, they will be automatically
// encoded by the function called below
var req:URLRequest = getRequest(addr,query);
//navigateToURL(req);
// check the console to see the changed address
ExternalInterface.call('console.log',req);
you can get URL with this.loaderInfo.url