Chrome Native Client, errors using onKeyDown event - javascript

I'm trying to get a very basic Chrome Native Client application running. What I'd like to do is respond to keystrokes, for example by displaying "You pressed X" whenever a user presses a key. I've been at it all day, but every time I press a key, I get "Uncaught TypeError: Object # has no method 'postMessage'".
The errors are all in the Javascript; the Native Client C++ module works fine.
Javascript in head of document:
myModule = null; // Global application object.
function moduleDidLoad() {
myModule = document.getElementById('mymodule');
alert("module loaded!") // this works
myModule.postMessage('hello'); // this works, and posts 'hello' to the module
// ERROR
document.body.onkeydown = function() {myModule.postMessage('hi');}
}
In page:
<div id="listener">
<script type="text/javascript">
var listener = document.getElementById('listener');
listener.addEventListener('load', moduleDidLoad, true);
</script>
<embed name="nacl_module"
id="mymodule"
width=0 height=0
src="mymodule.nmf"
type="application/x-nacl" />
</div>
I've tried it about 15 different ways: by adding it to the body tag with addEventListener, by adding it directly to the body tag with onKeyDown... nothing works.
I have experience with C/C++ and PHP but my Javascript is really weak. I think I must be missing something fundamental and obvious.

Solved. Elsewhere on the page, the DIV that contains the game module was having its contents changed, which removed the module from memory.

Related

Javascript reference error but works when I use a bookmarklet

I'm trying to execute some Javascript on a page that's already fully loaded.
To test the javascript, I created a bookmarklet, clicked it while the page was loaded, and it executed properly:
javascript:(array.find('value').__showAllRecords(event))
I wanted to use this Javascript in an AppleScript I'm writing that sends it to chrome, but for some reason, I'm getting this error:
Uncaught ReferenceError: array is not defined
at <anonymous>:1:1
It only happens when I run my script in my AppleScript editor, not when I use the bookmarklet. Here's my AppleScript code:
tell application "Google Chrome"
execute front window's active tab javascript "array.find('value').__showAllRecords(event)"
end tell
The variable array is created at some point in time after your script executes, since you don't know when you could retry until it does exist:
(function(){
function trySomething(){
try{
array.find('value').__showAllRecords(event);
console.log("worked, stop trying");
clearInterval(timer);
}catch(e){
console.log("didn't work, try again",e);
}
}
var timer = setInterval(trySomething,1000);
}())
//create the array object some time in the future (not actually an Array type)
//this is not part of your script but would be created by the page
//at some point
setTimeout(
()=>window.array={find:x=>({__showAllRecords:x=>x})}
,6000
)
Unfortunately, applescript does not have access to the non default globals. See the thread https://bugs.chromium.org/p/chromium/issues/detail?id=543437
But there is a workaround, what you can do is set the array as innerHTML of a div and retrieve the value from applescript. So for e.g. this is my div <div id="test">[1,2,3]</div>, you can execute
tell application "Google Chrome"
execute front window's active tab javascript "console.log(document.getElementById(\"test\").innerHTML)"
end tell
Hope this helps

Does the browser persistently cache compiled versions of script elements?

In a web app that allows users to play with javascript I require them to have a function main() in their "program". There's a "run" button, and an "edit" button. When you press "run" text from a <textarea> is used to create a script block and insert it into the DOM. Then main() is called.
I catch window.onerror to display errors to the user. This generally works OK. If there is no main(), an appropriate error message is shown.
When you press "edit", the script block is set to blank (script.text = '';),and removed from the DOM.
Testing, I noticed that if I had "program" consisting of just:
function main() { printLn('main here'); }
it worked as expected, but when I changed that to:
function moon() { printLn('moon here'); }
instead of getting a message saying main() not defined, it still worked as before, despite the fact that the script block had the "moon" text. This continued to happen if I gave each created script block a distinctive ID, and if I changed the script block type to text/plain before removing it.
The problem occurs in current Firefox, Chrome, and Opera. You can see what happens here
The functions are still defined, even if you remove the script that defined it.
This is in stark contrast to CSS, where removing or modifying a stylesheet will remove or update the styles on the page accordingly.
There's a good reason for that, and that is that CSS is designed to be easily re-evaluated when changes are made. JavaScript on the other hand is far too complex for the browser to be able to understand what "removing a script" actually does.
So, provided you have run one function with main(), it will continue to exist even if you then delete it.
My suggestion would be to create a closure to run your script. You can do this with something like...
var input = "........"; // user's input
var runner = "if( typeof main === 'undefined') {"+
"showErrorMessage('No main() defined');"+ // or whatever your error function is
"} else { main(); }";
var func = new Function("(function() {"+input+runner+"})()");
func();
It's always worth noting that the global scope can still be accessed, such as if the user forgets to var their local variables, or if they outright access window.something. So long as it's only being run on the user's own machine, this isn't much of an issue, but if people can share their codes with others then you will need to be much more careful.

PhoneGap Cloud Build: Correct facebookConnectPlugin installation

I'm sure this is going to be so trivial, but have had a number of tries and being the last thing I need to configure before I can deploy the private test is driving me mad.
This question extends off this question, my config.xml is established in the same way, this part is a no brainer. I have also got in my <head>:
<script type='text/javascript' src="./js/facebookConnectPlugin.js"></script>
I have tried both ./facebookConnectPlugin.js as well as ./js/facebookConnectPlugin.js, so part (a) of my question is, how can I determine what is the correct relative path without seeing the directory? I can't find its install location to verify.
Next part of the question follows the advice I received from somewhere, that instead of using the usual device ready event, to use the window.onload:
window.onload = onDeviceReady;
...
function onDeviceReady() {
onDeviceReadyFacebook();
...
}
...
function onDeviceReadyFacebook() {
// ?
}
window.fbAsyncInit = function () {
if (!window.cordova) {
// Initialize - only executed when testing in the browser.
facebookConnectPlugin.browserInit(<APP_ID>);
}
}
I have tried the window.fbAsyncInit both inside and out of the call I make for onDeviceReadyFacebook, trying to follow the advice from different forums...
So finally the error occurs within the call I have made to login:
function fb_login(){
var login_data = {};
client.cmd = "login";
login_data.userid = user_id;
login_data.cmd = "login";
facebookConnectPlugin.login([
'user_about_me',
'email',
'user_status',
'user_posts',
'user_photos',
'user_videos',
'user_friends'
],function(response) {
// success
...
Saying that the facebookConnectPlugin is undefined. After sligthly modifying different areas and everything else about the app is working, I would generally say that I'm not specifying the right source url for the primary JS file...
One last question on this topic: if I have correctly put in my Content Security Policy, is there any reason I need to use a plugin when I can just use the Facebook all.js they provide as is used in the browser version? I have got my key hash and other properties defined to add the android platform, I would have thought I can specify those attributes to match the platform...
EDIT: The plugin branch in question is located here.
UPDATE 2:
#JesseMonroy650:
Yes; a few things are definitely becoming clearer, but I did switch to cordova-plugin-facebookconnect-orlando, but adding that made the build crash, the log file result saying the message "...-FacebookLib/ant-build does not exist". I found the exact problem happening here, so I've now tried the same npm plugin and preference settings that was used there. It now builds, but I have the same problem (facebookConnectPlugin is undefined).
However, I checked the repo again this morning, specifically the path:
/platforms/android/assets/www/index.html
To see what I am crucially missing :
<div id="fb-root"></div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/facebookConnectPlugin.js">/script>
So hopefully if I copy off this example, I should be alright now. Will be trying again tonight.
Any help is always very appreciated!
The code added to index.html has finally resolved the issue. I tidied up the actual call to the login as demonstrated, but ultimately the variable wasn't found because I hadn't done the script include. Confusion over the scripts to include and what path they would be.
BIG relief!!! Props to you #JesseMonroy650 for steering me in the right direction of a deprecated plugin.

Javascript throws typeerror on ios only

I have a strange problem and I bet it is just a really stupid error somewhere, but I just can't figure out, what's wrong with my code..
I have a website that works perfectly fine on every (common) browser on every common os.
On this page i have a searchbar, which also works perfectly fine on computer. This bar also has a jquery keyup event, to start the search.
This event does not fire on ios (first problem). So I added a button as workaround. But this also doesn't work on ios.
If it would work correctly, it should call a JS-Method that only redirects the user to the search.php page while appending a GET-Variable called query. I loaded the page on pc and the error console says:
TypeError: is not a function (evaluating 'search()')
It somehow does not seem to load this method. For whatever reason. All other JS-Methods work fine. Just this one refuses to work.
The searchbar:
<input placeholder="Search" id="searchbar">
the link looks like this:
start search
The JS-Method looks like this:
var text = document.getElementById('searchbar').value;
window.location.href="./search.php?q="+text;
Any ideas?
Seems global variable search is reserved by iOS. Try to use some another name like mySearch then it works.
BTW, you may consider using namespace or scope to avoid conflict with libraries or system.
Example:
(function() {
function search() {
alert('test');
}
document.getElementById('searchbutton').onclick = search;
})();
Or if you insist to use onclick directly in the element.
start search
<script>
var MyNamespace = (function() {
function search() {
alert('test');
}
return {
search: search
};
})();
</script>

Run greasemonkey script after javascript

I'm trying to modify a variable - which is created in javascript - and run a function to change some visual stuff on a page. But my greasemonkey script is - i guess - running before the javascript, i'm getting an error says function is not defined.
How can I force to run my script after the javascript runs?
Actually what I'm trying to do is very simple. There is a variable called cursort, what I want to do is change that to "data-price" and sort the list again using updateSort(). Here is the code:
var cursort = "data-price";
updateSort();
I had to do something similar, there was a object defined at the end of the page that I wanted to just cancel out, so it's functions wouldn't run (it captured link clicks and ran some stuff).
In the page it was defined like this:
var someObj = { ... }
I made a greasemonkey script (after much trial/error) that looked like this.
window.addEventListener ("load", runAfter, false);
function runAfter() {
unsafeWindow.someObj = null;
}
Now clicking on the links does not trigger all the other actions that were in someObj.
Maybe you can do something like that?

Categories