Function undefined for onclick event -HTML5 canvas - javascript

I'm just starting out working with the HTML5 canvas and I want to use onclick to call as js function in my document.
However, despite declaring the function in my JS, I still get [function name] is not defined when clicking.
The function is defined as such:
function draw_b() {
var b_canvas = document.getElementById("b"); // finds the canvas in the DOM
var b_context = b_canvas.getContext("2d"); // context for drawing. No 3D option yet
b_context.fillRect(50, 25, 150, 100);
}
The click event is included as such:
onclick="draw_b();return false"
Yet when I click the element, I get:
draw_b is not defined
JSFiddle

In JSfiddle you need to use the No Wrap - In <head> option so the function is defined when used inline for the HTML elements. Also var b_canvas = document.getElementById("b"); should be var b_canvas = document.getElementById("a");
jsFiddle

You are using the wrong ID
var b_canvas = document.getElementById("a");// Use `a` not `b`

Jsfiddle doesn't like onclick="" so you need to use addEventListener from JavaScript.
var a_canvas = document.getElementById("a");
a_canvas.addEventListener("click",draw_b);
function draw_b() {
var b_canvas = document.getElementById("b"); // finds the canvas in the DOM
var b_context = b_canvas.getContext("2d"); // context for drawing. No 3D option yet
b_context.fillRect(50, 25, 150, 100);
}
canvas {
border: 1px dotted;
}
<canvas id="a" width="300" height="225"></canvas>
<canvas id="b" width="300" height="225"></canvas>

Related

Making a print of a canvas img

I am trying to create a button that when clicked:
opens a canvas img in a new window;
starts the print function;
closes the new page after using JS.
This is what I have so far:
function printCanvas() {
var canvas = document.getElementById("sidstemoned");
var img = canvas.toDataURL("image/png");
var newWin = window.open("");
newWin.document.write('<img src="' + img + '" />');
newWin.print();
newWin.close();
}
$(document).ready(function () {
$('#print_canvas').on('click', printCanvas);
});
Canvas:
<canvas
class='costumor_statistic col-lg-12 col-md-12 col-sm-12'
style='height:350px;'
id='sidstemoned'></canvas>
Button:
<button
class="btn btn-default hidden-print"
id="print_canvas">Print <span class="fa fa-print "></span></button>
The console prints this when I press the button:
Uncaught TypeError: Cannot read property toDataURL of null
at printCanvas
at HTMLButtonElement.
at HTMLButtonElement.dispatch (jquery.min.js:4)
at HTMLButtonElement.r.handle (jquery.min.js:4)
Does it work correct?
function printCanvas() {
var canvas = document.getElementById("canvasname");
var img = canvas.toDataURL("image/png");
var newWin = window.open("");
newWin.document.write('<img src="' + img + '" />');
newWin.print();
newWin.close();
}
UPD: Maybe you try find canvas before it was added to DOM. Try to wrap your onClick handler to $(document).ready
$(document).ready(function(){
$('#print_canvas').on('click', printCanvas);
});
The current problem is that the variable canvas you are using in the printCanvas function is null, which means that when you tried to fetch the element with:
document.getElementById("sidstemoned");
Nothing was found, and therefore in the second line, instead of accessing an element from the DOM, this is happening:
null.toDataURL("image/png");
null does not have a toDataURL property (or function), that is why you get that error. So just make sure that your variable canvas has an element associated to it, i.e. the id sidstemoned you are referencing exists in the document. You can verify that canvas has something by simply consulting its length property:
if(canvas.length !== 0) { /* remaining code goes here */ }
Also, non-directly related, you may want to delete the extra class attribute in the button (the one with a single costumor_statistic).

How to programmatically ng-bind a property on an svg element?

I'd like to bind a background color to an svg element. I have an external svg file that I'm referencing, myfile.svg, inside of this file there's a circle with the id 'mycircle'.
So my html looks like:
<div ng-controller="MyCtrl">
<embed src="myfile.svg" id="mySvg"/>
</div>
I have a controller that looks like:
function MyCtrl($scope) {
$scope.myfill = 'yellow';
}
Now I'd like to set up the binding programmatically, this is what I do:
var mySvg = document.getElementById("mySvg");
mySvg.addEventListener("load", function() {
var svg = mySvg.getSVGDocument();
var mycircle = svg.getElementById("mycircle");
//this works:
//mycircle.setAttribute("fill", "yellow");
$(mycircle).attr('ng-bind','myfill');
});
However, this doesn't set the fill. I'm thinking I might need to use angular "compile" or something in order to get this to work (?) can anyone clue me in on how to do this?
Yes you need to compile. Should bind as an exp and compile against the scope. Below snippet should work.
var mySvg = document.getElementById("mySvg");
mySvg.addEventListener("load", function() {
var svg = mySvg.getSVGDocument();
var mycircle = angular.element(svg.getElementById("mycircle"));
mycircle.attr('fill', '{{myfill}}');
$compile(mycircle)($scope);
});

Rollover will not swap

Hey im having trouble with my javascript rollover. The image does not change. Ive had a look at some tutorials and i cant see where im going wrong.
Here is my code:
Home.xhtml
<img src="images/Weights.png" width="900" height="300" border="0" alt="Gym Equipment" name="gym"
onMouseOver="swapImage('gym','treadmill');" onmouseout="swapImage('gym','weights');"/>
newjs.js
// Pre load images for rollover
if (document.images)
{
treadmill = new Image
weights = new Image
treadmill.src = "images/Treadmill.png"
weights.src = "images/Weights.png"
}
function swapImage(thisImage,newImage)
{
if (document.images)
{
document[thisImage].src = eval(newImage + ".src")
}
}
How i tell the app where the js is:
document[thisImage].src = eval(newImage + ".src")
should be
document[thisImage].src = eval(newImage ).src
Please avoid using eval() as it is generally the slowest way to evaluate code and there are some circumstances where it introduces security risks depending upon where the data comes from that you're calling eval on.
You should be able to make this work:
HTML:
<img src="images/Weights.png" width="900" height="300" border="0" alt="Gym Equipment" name="gym"
onMouseOver="swapImage(this,'treadmill');" onmouseout="swapImage(this,'weights');"/>
Javascript:
// Pre load images for rollover
window.treadmill = new Image();
window.weights = new Image();
treadmill.src = "images/Treadmill.png"
weights.src = "images/Weights.png"
// this function must be defined globally
// (e.g. not defined inside any other function)
function swapImage(thisImage,newImageName) {
thisImage.src = window[newImageName].src;
}
Working demo here: http://jsfiddle.net/jfriend00/cv8tT/
Changes I made:
Removed the use of eval() and use window[name] to access global variables.
Changed the way swapImage() is called in the HTML to pass this so you can directly access the desired image.
Remove the if (document.images) checks since it is no longer used by the code.
FYI, all this could be done with CSS and background images with no javascript at all.
I would take a slightly different approach by taking the mouseover and mouseout attributes out of your image tag. This will help keep your code more maintainable.
I made a DEMO jsfiddle here
Note that I am using 3 images from Flickr, the default, one on mouseover, and one on mouseout. I hope this helps.
** Also note that the img tag now has an ID which is referenced in the bindings.
// Pre Load Images
var img1 = new Image();
var img2 = new Image();
img1.src = "http://farm4.staticflickr.com/3230/2953035318_b54956e7df_q.jpg";
img2.src = "http://farm4.staticflickr.com/3026/2992860864_aa9e8b0818_q.jpg";
// Event binding function
var bindEvent = function (el, eventName, eventHandler) {
if (el.addEventListener != null) {
return el.addEventListener(eventName, eventHandler, false);
} else if (el.attachEvent != null) {
return el.attachEvent('on' + eventName, eventHandler);
}
}
// Mouseover binding
bindEvent(document.getElementById('surfer'), "mouseover", function (e) {
this.setAttribute("src", img1.src);
});
// Mouseout Binding
bindEvent(document.getElementById('surfer'), "mouseout", function (e) {
this.setAttribute("src", img2.src);
});

JavaScript windows.onload or referencing new elements?

I'm trying to create a lightbox and I'm having trouble.
I think the problem is either because I have 2 window.onloads or because I'm trying to reference a newly created DOM element. I added some comments in the code below that explain what I'm trying to do.
//open lightbox
window.onload = showLargeImage;
function showLargeImage() {
var enlargeButton = document.getElementById("thumb1"); // thumb1 is a thumbnail you click to get the lightbox
enlargeButton.onclick = handleClick;
}
function handleClick() {
var lightboxContainerId = document.getElementById("lightboxContainer");
lightboxContainerId.innerHTML = '<div class="lightbox"><a class="reduceButton" href="#" ><img id="imageButton" class="largeImage" src="2012/images/web/web1.jpg" width="500" height="500" alt="Web Thumb 1"></a></div>';
} // the inner HTML creates the lightbox.
//close lightbox
window.onload = reduceImage; // i'm pretty sure that this windo.onload is the problem... or, that I'm referencing "imageButton" which is new to the DOM
function reduceImage() {
var reduceButton = document.getElementById("imageButton"); // you're supposed to click the big image in the lightbox to get close it.
reduceButton.onclick = handleReduceClick;
}
function handleReduceClick() {
var shadeId = document.getElementById("lightboxContainer");
shadeId.innerHTML = "say what"; // closing the lightbox simply strips everything out of the lightboxContainer
alert("oh yeah");
}
Here are a few reasons why your code is not working:
showLargeImage and reduceImage are missing invocation parentheses in the places where they are being assigned to window.onload. Without parentheses, window.onload is being assigned a function, but that function is not getting called. You should, for instance, have window.onload = showLargeImage();
As you suspected, the second window.onload is overwriting the first.
reduceButton is (as you also suspected) being assigned before it exists, causing an error.
Here is one solution that may work for you.
HTML:
<!DOCTYPE html>
<html><head><title></title>
</head><body>
View
<div id="lightboxcontainer"></div>
</body></html>
JavaScript:
window.onload = function() {
// click link to show
var enlargeButton = document.getElementById('thumb');
enlargeButton.onclick = function() {
var lightboxContainerId = document.getElementById('lightboxcontainer');
lightboxContainerId.innerHTML = '<img src="http://placehold.it/350x150"' +
'width="350" height="150 alt="Thumb 1">' +
'<p>Click image to hide.</p>';
};
// click image to hide
var reduceButton = document.getElementById('lightboxcontainer');
reduceButton.onclick = function() {
reduceButton.innerHTML = ''; // removes lightbox contents
};
};
Live demo: http://jsfiddle.net/ericmathison/BxwYY/7/
If the code is placed at the end of the <body> (or anywhere after your lightbox elements), just use this:
document.getElementById("thumb1").onclick = function () {
document.getElementById("lightboxContainer").innerHTML = '<div class="lightbox"><a class="reduceButton" href="#" ><img id="imageButton" class="largeImage" src="2012/images/web/web1.jpg" width="500" height="500" alt="Web Thumb 1"></a></div>';
document.getElementById("imageButton").onclick = function () {
document.getElementById("lightboxContainer").innerHTML = "say what";
alert("oh yeah");
};
}
This will do everything you want.

Having problems scripting SVGs

I'm having some trouble with manipulating SVGs through javascript. I'd like to increase the length of a line through clicking a button. I've included this code in the head tag:
<script type="text/javascript">
x=135;
y=135;
var container = document.getElementById("svgbox");
var mySvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
function svg() {
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute("height","300px");
mySvg.setAttribute("width","300px");
container.appendChild(mySvg);
}
function line() {
x=x-10;
y=y-10;
var L1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
L1.setAttribute("x1", "100"); L1.setAttribute("y1", "100");
L1.setAttribute("x2", x); L1.setAttribute("y2", y);
L1.setAttribute("stroke", "#05adc7");
L1.setAttribute("stroke-width", "2px");
mySvg.appendChild(L1);
}
</script>
This is the body text:
<body onload="svg()">
<form>
<input type="button" onClick="line()" />
</form>
<div id="svgbox">
</div>
</body>
But when I click on the button, I get an error telling me that the variable "container" is null. Does anyone know what the problem is?
It works if you put the line var container = document.getElementById("svgbox"); in the svg function.
function svg() {
var container = document.getElementById("svgbox");
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute("height","300px");
mySvg.setAttribute("width","300px");
container.appendChild(mySvg);
}
The reason container is null in your code is because the DOM has not loaded yet when the line var container = document.getElementById("svgbox"); gets executed.
You need to declare container after either the DOMContentLoaded event or window.onload event is fired.
This is a common gotcha in DOM scripting, for both SVG and HTML. The problem is that the svgbox element is not yet loaded when the JavaScript executes. The easiest solution is to simply move your script tag so that it is the last element in the document. This is a bit ugly, though, so most JavaScript libraries include a method that accepts a callback to execute after the document has been loaded. For example, if you were using jQuery, then your script tag would look like the following:
<script type="text/javascript">
$(document).ready(function(){
x=135;
y=135;
var container = document.getElementById("svgbox");
var mySvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg = function() {
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute("height","300px");
mySvg.setAttribute("width","300px");
container.appendChild(mySvg);
}
line = function() {
x=x-10;
y=y-10;
var L1 = document.createElementNS("http://www.w3.org/2000/svg", "line");
L1.setAttribute("x1", "100"); L1.setAttribute("y1", "100");
L1.setAttribute("x2", x); L1.setAttribute("y2", y);
L1.setAttribute("stroke", "#05adc7");
L1.setAttribute("stroke-width", "2px");
mySvg.appendChild(L1);
}
})
</script>

Categories

Resources