onCanvasClick(event) does not work on visual studio ultimate - javascript

I am building a puzzle game. And it does work in a browser but I need to make it work on visual studio . It shows the picture and everything but when I click I get this error
0x800a1391 - JavaScript runtime error: 'onCanvasClick' is undefined
I have a prb with this part of the code
<canvas id="myCanvas" width="640" height="480" onclick="onCanvasClick(event);">
it does not accept
onCanvasClick(event);
I cannot find a way to make it work . I would really appreciate it if you can help me out.

Try this:
canvas = document.getElementById("myCanvas");
// Beware, this is "click" not "onclick"
canvas.addEventListener('click', canvasClicked, false);
function canvasClicked(e) {
console.log("Clicked");
}
See it on jsFiddle

As mentioned by Sam Rad you should add the event listener in a <script> tag not inline in HTML. I think that the reason, your function is undeclared is because it is declared in a different scope. When you use it in an inline HTML script it is looking for the function in a global scope.
So if you have something like this:
(funciton() {
function canvasClicked( event ) {
// ...
}
})()
your inline HTML script will fail.
Just avoid using inline HTML scripts and you will make your life easier :D

Related

Remove Attribute-defined `onload` from `<body>`

I've been working on this for a few hours and am at the point where I feel like I might be trying to accomplish something unworkable. Any advice or insight is definitely appreciated!
The use case I'm targeting requires interrupting the browser's DOM parsing before it has a chance to draw the <body> element. To accomplish this, I've used this one-liner as the first script called in my <head> element:
document.replaceChild(document.createElement('html'), document.children[0]);
This successfully prevents the browser from calling any subsequent scripts, and the <body> element remains un-rendered. However, if the markup includes an onload attribute on the <body> element, that function or code is still called by the browser.
As the context which intercepts DOM parsing is in <head>, I can't use document.body.removeEventListener() to drop the event listener, because the body element doesn't exist yet. Setting window.onload to null has no effect, and neither does trying to intercept setting of window.onload using Object.defineProperty(window, 'onload', {...}). In each case, the onload function or statements still get called.
To preempt the obvious question as to why I can't just avoid using <body onload="...">, the use case is for developer tooling, so I'm trying to create contingency for certain absolute conditions. If it can't be done, it isn't killer to my project, but I'd sure like to know why it can't be done.
Thanks in advance!
You can use Document readystate at the interactive state, and overwrite the onload attribute.
document.onreadystatechange = () => {
if (document.readyState === 'interactive')
window.onload = null;
}
(Added your code from your comment for completeness.)

onload function init not found

I'm encountering a strange issue. I am developing a books application and using javascript onload. I read somewhere that its best to include your javascript at the end of the html. This works for most of the html loaded. However some complain that onload init() not found. This gets solved if i include the javascript in the html head. But than other htmls start behaving strangely. onload gets called before the page is fully loaded. i dont get the correct scroll width. Please suggest what could be worng. Whats the best way of including javascripts. Thanks
html is as follows
columizer id use css column-width which i've defined like this.
css style below
#columnizer
{
width:290px;
height:450px;
column-width:290px;
column-gap:10px;
word-wrap:break-word;
}
Javascript onload is defined like this.
function init()
{
docScrollWidth = document.getElementById('columnizer').scrollWidth;
document.getElementsByTagName('body')[0].style.width = docScrollWidth + "px";
window.external.notify(str);
}
Since the actual answer was in my comment, I'll add that to my answer:
My guess is that you're doing something like window.onload = init(); instead of window.onload = init; and the init function will have to be declared before you do that assignment. You assign function references without the parens. Using the parens causes it to get executed immediately.
You say you're using this code:
docScrollWidth = document.getElementsByTagName('body')[0].style.width
The main problem with this is that style.width ONLY reads a style attribute set directly on the body object. It doesn't get the width of the object as calculated by layout or CSS rules.
So, what you should use instead really depends upon what you're trying to do. The body width will nearly always be the same or more than the window width unless your content is entirely fixed width. So, that makes me wonder what you're trying to accomplish here? What you should use instead depends upon what you're really trying to do.
FYI, document.body is a direct reference to the body object so you don't need document.getElementsByTagName('body')[0].
First, let me define the problem. The window.onload event is used by programmers to kick-start their web applications. This could be something trivial like animating a menu or something complex like initialising a mail application. The problem is that the onload event fires after all page content has loaded (including images and other binary content). If your page includes lots of images then you may see a noticeable lag before the page becomes active. What we want is a way to determine when the DOM has fully loaded without waiting for all those pesky images to load also.
Mozilla provides an (undocumented) event tailor-made for this: DOMContentLoaded. The following code will do exactly what we want on Mozilla platforms:
// for Mozilla browsers
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", init, false);
}
So what about Internet Explorer?
IE supports a very handy (but non-standard) attribute for the tag: defer. The presence of this attribute will instruct IE to defer the loading of a script until after the DOM has loaded. This only works for external scripts however. Another important thing to note is that this attribute cannot be set using script. That means you cannot create a script using DOM methods and set the defer attribute – it will be ignored.
Using the handy defer attribute we can create a mini-script that calls our onload handler:
<script defer src="ie_onload.js" type="text/javascript"></script>
The contents of this external script would be a single line of code to call our onload event handler:
init();
There is a small problem with this approach. Other browsers will ignore the defer attribute and load the script immediately. There are several ways round this. My preferred method is to use conditional comments to hide the deferred script from other browsers:
<!--[if IE]><script defer src="ie_onload.js"></script><![endif]-->
IE also supports conditional compilation. The following code is the JavaScript equivalent of the above HTML:
// for Internet Explorer
/*#cc_on #*/
/*#if (#_win32)
document.write("<script defer src=ie_onload.js><\/script>");
/*#end #*/
So far so good? We now need to support the remaining browsers. We have only one choice – the standard window.onload event:
// for other browsers
window.onload = init;
There is one remaining problem (who said this would be easy?). Because we are trapping the onload event for the remaining browsers we will be calling the init function twice for IE and Mozilla. To get around this we should flag the function so that it is executed only once. So our init method will look something like this:
function init() {
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// do stuff
};
I’ve provided a sample page that demonstrates this technique.

Getting a not defined error with scripts embedded in an iFrame

I have a knowledge base for my work. I'm trying to get full html w/scripting setup within a iFrame instance.
Below is a Chrome expansion of my setup. When I click the button in my div/iframe, I get a Uncaught ReferenceError: test is not defined error.
Thoughts?
http://bytes.com/topic/javascript/answers/153274-script-iframe-can-not-call-functions-defined-parent-document
Per link:
Functions are not properties of the document, but of the window.
Try
parent.foo();
or
top.foo();
<button onclick='parent.test();'>test</button> works now... top.test() works too, BUT, I'd like a way to normalize this. Its not very intuitive.
Is there a way to NOT have to prefix top. or parent.?
Make sure the jQuery library is being called before any other script inside your <head> section.
Most of the times I get this error, I just change the order the scripts being called on the page (always under jQuery) and it solves the problem.
This is a late answer, but I'll share my solution.
I needed an iframe as a preview container. So parent.something would be a hassle.
This seems to work:
<iframe id='iframe' sandbox="allow-same-origin allow-scripts"></iframe>
And populate it with this (example using jquery):
$(function() {
let $iframe = $('#iframe');
$iframe.ready(function() {
let ifhead = `
<meta charset="UTF-8"><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"><\/script>`;
let ifbody = `<h1>My Body</h1>`;
let ifscript = `$(function() { $('h1').css('color', 'blue')})`;
let html = `<html><head>${ifhead}</head><body>${ifbody}<script>${ifscript}<\/script></body></html>`;
document.getElementById("iframe").contentWindow.document.open();
document.getElementById("iframe").contentWindow.document.write(html);
document.getElementById("iframe").contentWindow.document.close();
});
});
Now the iframe acts as a stand-alone page.

HTML5 Canvas not working in external JavaScript file

I have written this code in JavaScript and works perfectly fine when I include it on my index.html page:
<canvas id="bannerCanvas" width="960" height="200">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
var canvas = document.getElementById("bannerCanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.moveTo(25,25);
context.lineTo(355,55);
context.lineTo(355,125);
context.lineTo(25,125);
context.moveTo(465,25);
context.fill();
};
</script>
...however when I place it in an external JavaScript file, it won't work! In the head of the index page, I have declared this:
<script type="text/javascript" src="JavaScript/functionality.js">
</script>
And I save this functionality.js file in the JavaScript directory, I've tried doing other JS functions in this file to check the index page and the JS are connected and they are...The answer is probably staring me in the face but for some reason I cannot see it!
Any help is much appreciated, thank you.
EDIT: I've been using Firebug and it is giving me no errors, when I use the code on the index page, I am seeing the shape I want yet when using the external JS file I am just seeing a big black rectangle.
the reason for this is that the script is being run before the canvas element is rendered.
To fix it, add this in your external file.
document.addEventListener('DOMContentLoaded',domloaded,false);
function domloaded(){
// your code here.
}
or with jquery
$(function(){
// your code here.
});
Within functionality.js, try wrapping your code in
window.onload = function() {
// code here
}
so that it won't execute until after the page has loaded.
If it is in the head, you are loading it before the canvas element is rendered. Look at the JavaScript console and you will see a Null or undefined error.
Add the script tag in the same place it works with the inline code. JavaScript does not have to live in the head and some developers will recommend it should always be the last thing in the body.
Other solution is to run the script on document ready or window onload.
Dont put in the head, When you put the code in the head, it run the code when there is no canvas element in page yet.

Calling A Javascript function from Silverlight

I'm attempting to call a javascript function (in our code) from a silverlight control. I'm attempting to call the function via:
HtmlPage.Window.Invoke("showPopup", new string[] { "http://www.example.com" });
and I get the error "Failed to Invoke: showPopup"
I can call HtmlPage.Window.Invoke("alert", new string[]{"test"}); without issue, but not my own function.
I can also open up the page in question in the IE developer tools and manually call showPopup("http://www.example.com") and it works as expected.
So the js function works, and the Silverlight binary can find other js functions. What am I missing here?
Additional Notes:
The function call is in a button click event handler, so it happens after the page (and the script) have been loaded)
Aha! I figured it out. Our app uses an iframe, so the rendered html looks something like this
<html>
<head></head>
<body>
Stuff
<iframe>
<html>
<head></head>
<body>Other Stuff</body>
</html>
</iframe>
<body>
</html>
And the Silverlight control in question is in the iframe. The problem was that the file that contained the showPopup function was referenced in the outer <head> (why I could call the function with the IE toolbar) but not the inner <head>. Adding a reference to the file in the in-the-iframe <head> solved the problem.
Sort of anticlimactic, but thanks for all the help.
Actually referencing the script again from the iframe is not the most efficient way to reference code contained in the parent. If your function is called "showPopup", you can insert this in your iframe:
<script type="text/javascript">
var showPopup = parent.showPopup;
</script>
And voilà. The explanation for this is that all "global" functions and objects are part of this "global namespace"... which is the "window" object. So if you're trying to access "global" functions from a child, you need to either call the function on the parent (e.g parent.showPopup('....')) or declare a local alias for it (which is what we do in the above example).
Cheers!
Is the showPopup javascript function on the same html or aspx page as the Silverlight control? You will normally get the "Failed to Invoke ..." error if the javascript function does not exist:
HtmlPage.Window.Invoke("functionThatDoesNotExist", new [] { "Testing" });
What browser are you using when you are getting this problem?
Are you using the latest version of Silverlight?
Are you using the ScriptableType attrbiute anywhere?
Is it possible to list the code for a short but complete program that causes this problem to happen on your machine...
Make sure your script is fully loaded before trying to invoke functions from it.
Here's how I do it. But I'm creating silverlight without visual studio. I just have raw html, xaml, and js (javascript). Notice MouseLeftButtonUp and it's value "LandOnSpace"
<Canvas x:Name="btnLandOnSpace" Background="LightGreen" MouseLeftButtonUp="LandOnSpace"
Cursor="Hand" Canvas.Top ="0" Width="70" Height="50">
<TextBlock Text="LandOnSpace" />
</Canvas>
function LandOnSpace(sender, e) { //on server
if (!ShipAnimateActive && !blnWaitingOnServer) {
blnWaitingOnServer = true;
RunServerFunction("/sqgame/getJSLLandOnSpace");
ShowWaitingBox();
};
else {
alert('Waiting on server.');
};
}
I had the same problem in VS 2010 with SL 4. I had created a few methods and put them into one single JS file. However this file had not been added to the head section of the ASPX file. Adding it solved the problem. The difference is that though I did not have a separate head section in the iframe, I had the problem and it got solved.

Categories

Resources