Trying to simulate double buffering with javascript - javascript

I have a complex HTML element with huge numbers of divs inside. It is something like a calendar view. Now I want to refresh this view in the background e.g if some entries have changed on the server. For this, I started an EventSource which is asking the server if some data update has been done.
If so, I call the following function to load the new data
function calendarReplaceContent()
{
if(calendarDisplayFEList)
{
console.log("Start Replace");
loadJobs(false, calendarReplaceJobs, false); // load the new data
}
}
}
and if the loading is done this function is called
function calendarReplaceJobs()
{
console.log("Do Replace");
var oldContent = $('#calendarContentJobs'); // Get old Element
var calendarContentJob = oldContent.clone(); // Clone element
calendarContentJob.find('[id^="calendarjob_"]').remove(); // Remove old entries from cloned element
showJobs(false, calendarContentJob); // Draw new entries to cloned element
$('.rightTable').append(calendarContentJob); // Add new element to parent
oldContent.remove(); // Remove old element
}
This works fine, but each time the new element is added and the old one removed, this display is empty for a part of a second.
What I expected was that I will have now flickering on the display because I first append the new element (which in that case should be visible about the old one) and after that remove the old one.
Is there another way to replace the element with the new one without a flicker?
On further debugging I found out, that the find().remove is not working as expected. I thought this will only remove the children of the clone element. But in fact it also removes the elements starting with the id 'cleandarjob_' in the old existing element.
So how can I only remove all elements from the clone where the id ist starting with 'calendar job_'?

Double buffering in action
Here is how I do it on 2 canvas.
step1();
setTimeout(function () {
step2();
setTimeout(function () {
step3();
}, 1000);
}, 1000);
function step1() {
clearCanvas('myCanvas1');
drawShape('myCanvas1'
,{type:"circle", strokeStyle:"#000000", fillStyle:"#000000", radious:40, x:50, y:50});
};
function step2() {
clearCanvas('myCanvas2');
showOtherCanvas('myCanvas2', 'myCanvas1');
};
function step3() {
clearCanvas('myCanvas1');
drawShape('myCanvas1'
,{type:"circle", strokeStyle:"#000000", fillStyle:"#000000", radious:40, x:50, y:50});
showOtherCanvas('myCanvas1', 'myCanvas2');
};
function drawCircle (canvasID, info) {
var canvas = document.getElementById(canvasID);
var ctx = canvas.getContext('2d');
ctx.fillStyle=info.fillStyle;
ctx.strokeStyle=info.strokeStyle;
ctx.beginPath();
ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI);
ctx.stroke();
}
function showOtherCanvas(cnv1, cnv2) {
var c1 = document.getElementById(cnv1);
var c2 = document.getElementById(cnv2);
c1.style['z-index'] = 3;
c2.style['z-index'] = 1;
c1.style['z-index'] = 2;
}
function clearCanvas(canvasID) {
var canvas = document.getElementById(canvasID);
var ctx = canvas.getContext('2d');
ctx.fillStyle="#FFFFFF";
ctx.strokeStyle="#FFFFFF";
ctx.fillRect(0,0,640,400);
}
function drawShape (canvasID, info) {
switch (info.type) {
case "circle" : drawCircle(canvasID, info);
}
}
<canvas id="myCanvas2" width="640" height="400"
style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:1">
</canvas>
<canvas id="myCanvas1" width="640" height="400"
style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:2">
</canvas>
The change is so fast you won't see any flicker.

Related

Trying to refresh specific canvas element

I'm simply trying to refresh a canvas element.
I've tried doing this
function reload(){
var container = document.querySelectorAll('[canvas]');
var content = container.innerHTML;
container.innerHTML= content;
console.log("Refreshed"); //Watches console.
}
But it simply doesn't refresh the canvas element? I can use Jquery on the site if it's easier.
Here is the HTML of the canvas element.
<canvas width="800" height="500" style="position: absolute; top: 39px; left: 136px; background-color: transparent; z-index: 10;"></canvas>
If you can help me find a solution please.
You should get the container using querySelector
var container = document.querySelector('canvas');
or querySelectorAll
var container = document.querySelectorAll('canvas')[0];
Now, you attempt to refresh the canvas by changing its inner HTML to the formerly known HTML value:
var content = container.innerHTML;
container.innerHTML= content;
console.log("Refreshed"); //Watches console.
if changing the inner HTML of the canvas would refresh it, then it is a hacky approach and it should only work according to my opinion if the HTML actually changes. Instead, it would be better to just store the content of the canvas somewhere, then clear it:
ctx.clearRect(0, 0, canvas.width, canvas.height);
and draw it again.
Currently theres a few issues. First, [canvas] should be just canvas. Second, you are using querySelectorAll which returns a NodeList of all canvas objects. So either, use that but then loop over it to update all canvases, or change to querySelector which returns just one. And I would recommend using an ID in that case.
Also, this might seem silly but are you calling the function? Or just defining it?
Here it is with querySelectorAll and canvas:
function reload(){
var canvases = document.querySelectorAll('canvas');
for(let canvas of canvases) {
var ctx = canvas.getContext("2d");
var content = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx.putImageData(ctx,0,0)
console.log("Refreshed"); //Watches console.
}
}
<canvas width="800" height="500" style="position: absolute; top: 39px; left: 136px; background-color: transparent; z-index: 10;"></canvas>
You are wrong in using document.querySelectorAll(). Since you are selecting a single target, you should use document.querySelector(). Try this.
function reload(){
var container = document.querySelector('canvas');
var content = container.innerHTML;
container.innerHTML = content;
console.log("Refreshed");
}

HTML Canvas - passing a background image to Canvas while it's also passing base64 data

I'm currently trying to do some Javascript work in Laserfiche forms which requires me to save the base64 data for an image in a separate text area, and feed that data back into the image to allow the canvas to be turned into an image in which I can save into the system.
The issue is I'm trying to have a background image in which the user can draw on (in this case, a vehicle that they can draw a circle on to indicate where the damage is). I am using sketch.js to allow the drawing part of the task.
From what I've read is that the background CSS cannot be saved into the canvas. That's fine but how do I pass the background image when I'm already grabbing the base64 data and passing that back into my canvas?
The saveimage class belongs to the text area and the imagefinish belong to the checkbox that they mark when the image is ready
html
<div class="demo" id="colors_demo">
<div class="tools">
Marker
Eraser
Download
</div>
<canvas id="colors_sketch" width="750" height="500" style="border:2px solid #000000 ; background: url(http://localhost/forms/img/vanImage.jpg"></canvas>
</div>
<input name="Field11" id="Field11-0" type="checkbox" value="isLocked" vo="e" data-parsley-class-handler="#Field11" data-parsley-errors-container="#Field11" data-parsley-multiple="Field11">
<textarea id="Field13" name="Field13" aria-labelledby="Field13" class="cf-medium" rows="3" vo="e" data-parsley-id="28"></textarea>
Javascript
//submitted form
if ($('[name=IsLocked]').val() == 'True') {
var myCanvas = document.getElementById('colors_sketch');
var ctx = myCanvas.getContext('2d');
var img = new Image;
img.onload = function() {
ctx.drawImage(this, 0, 0, myCanvas.width, myCanvas.height);
}
img.src = $('.saveimage .cf-field').text();
}
else {
//fill form
//$.getScript('http://localhost/Forms/js/sketch.js', function() {
$.getScript('https://rawgit.com/intridea/sketch.js/gh-pages/lib/sketch.js', function() {
//script is loaded and executed put your dependent JS here
$.each(['#f00', '#ff0', '#0f0', '#0ff', '#00f', '#f0f', '#000', '#fff'], function() {
$('#colors_demo .tools').append("<a href='#colors_sketch' data-color='" + this + "' style='width: 10px; background: " + this + ";'></a> ");
});
$.each([3, 5, 10, 15], function() {
$('#colors_demo .tools').append("<a href='#colors_sketch' data-size='" + this + "' style='background: #ccc'>" + this + "</a> ");
});
//$('#colors_sketch').sketch();
$('#colors_sketch').sketch({defaultColor: "#000"});
});
$('.imagefinish input').change(function(){
if(this.checked) {
var myCanvas = document.getElementById('colors_sketch');
$('.saveimage textarea').val(myCanvas.toDataURL());
}
});
}
I was able to add an image by adding a variable for my image path
var image = 'http://localhost/forms/img/vanImage.jpg'
and I also added the two lines to my onload for the style of "myCanvas". I have a feeling that this solution will only work because of how Laserfiches forms software works but the marked answer is also correct.
img.onload = function() {
ctx.drawImage(this, 0, 0, myCanvas.width, myCanvas.height);
myCanvas.style.backgroundRepeat = "no-repeat";
myCanvas.style.backgroundImage = 'url('+image+')'
}
img.src = $('.saveimage .cf-field').text();
}
Load the background image on page load, or an appropriate time and when the client is ready, draw the background onto the canvas behind the user content using ctx.globalCompositeOperation = "destination-over";
Create an image to hold the background.
const backgroundImage = new Image();
backgroundImage.src = "http://localhost/forms/img/vanImage.jpg";
You need to ensure that the image has loaded when the client clicks ready, incase it has not loaded you can set a callback that will call back the ready function if needed.
var backgroundLoadedCallback = null;
backgroundImage.onload = function(){
if( typeof backgroundLoadedCallback === "function"){
backgroundLoadedCallback();
}
}
Then create the canvas -> textarea function
function canvasToTextarea(){
const myCanvas = document.getElementById('colors_sketch');
const ctx = myCanvas.getContext("2d");
ctx.globalCompositeOperation = "destination-over"; // make sure the background go under the drawn pixels
// draw and fit background to the canvas
ctx.drawImage(backgroundImage,0,0,ctx.canvas.width,ctx.canvas.height);
// then convert to URL for textarea
$('.saveimage textarea').val(myCanvas.toDataURL());
}
In the checked function
$('.imagefinish input').change(function(){
if(this.checked) {
if(backgroundImage.complete) { // image has loaded so all good
canvasToTextarea(); // put canvas data URL to textarea
} else { // background has not yet loaded (or could be an error you will have to deal with that as well
// set the callback to the canvasToTextarea function
backgroundLoadedCallback = canvasToTextarea;
// when the background has loaded the canvas and background
// will be moved to the textarea as a data URL
}
}
});
Or modify sketch.js
Below is the draw function from sketch.js (and it`s very old school)
Sketch.prototype.redraw = function() {
var sketch;
this.el.width = this.canvas.width();
this.context = this.el.getContext('2d');
sketch = this;
$.each(this.actions, function() {
if (this.tool) {
return $.sketch.tools[this.tool].draw.call(sketch, this);
}
});
if (this.painting && this.action) {
return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
}
};
Just replace it with the following. You dont need to modify the sketch.js file justy overwrite the redraw Prototype
In your code load the background and set the new redraw
const backgroundImage = new Image();
backgroundImage.src = "http://localhost/forms/img/vanImage.jpg";
// replace Sketch.js redraw function
Sketch.prototype.redraw = function(){
var sketch;
// dont need the next line use clear instead
// this.el.width = this.canvas.width();
const ctx = this.context = this.el.getContext('2d');
// clear canvas
this.context.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// If backgroundimage complete draw it first
if(backgroundImage && backgroundImage.complete){
ctx.drawImage(backgroundImage,0,0,ctx.canvas.width,ctx.canvas.height);
}
// back to the original code. :P
sketch = this;
$.each(this.actions, function() {
if (this.tool) {
return $.sketch.tools[this.tool].draw.call(sketch, this);
}
});
if (this.painting && this.action) {
return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
}
}

Images on first load don't show on canvas

I want to pass a list of images and draw them each one for canvas.
My view.py:
def myview(request):
...
lista=Myobject.objects.filter(tipo=mytipo)
numero_oggetti = range(len(lista))
lista_formattata=[]
for elem in lista:
lista_formattata.append('/media/'+str(elem.myfield))
context_dict['lista']=lista_formattata
context_dict['numero_oggetti']=numero_oggetti
return render(request, 'mytemplate.html', context_dict)
My template.html:
<script>
<!--
window.onpageshow = function() {
myfunction({{lista|safe}});
};
-->
</script>
{% for c in numero_oggetti %}
<canvas id='componenti_canvas{{ c }}' width='60' height='75' style="border:1px solid #000000;">
Your browser does not support the HTML5 canvas tag.
</canvas>
{% endfor %}
My script.js:
function myfunction(lista) {
lista=lista
for (i=0; i<lista.length; i++) {
var canvas = document.getElementById('componenti_canvas'+i);
var ctx = canvas.getContext("2d");
var base = new Image();
base.src = lista[i];
ctx.scale(0.5,0.5);
ctx.drawImage(base, 0, 0);
};
};
This code works but sometimes the images show, sometimes don't (all of them or no one). When I load the page they don't show, when I re-load the page they show up. If I wait some minutes and re-load they don't show again.
I'm using firefox and in the console log when say GET image_name.png HTTP/1.0 200 they don't show (sometimes they are in cache, sometimes not... it don't make difference), when it don't say nothing they show.
I tried:
-setTimeout
-call the list with an ajax request with cache: false, async: false
-base.onload, like that:
base.onload = function(){
ctx.scale(0.5,0.5);
ctx.drawImage(base, 0, 0);
}
but or the images don't show never or they show in this way. I can give details, of course I can have done errors.
Edit: in the comment say to use onload.
My script.js:
function myfunction(lista) {
lista=lista
for (i=0; i<lista.length; i++) {
var canvas = document.getElementById('componenti_canvas'+i);
var ctx = canvas.getContext("2d");
var base = new Image();
base.onload = function() {
ctx.drawImage(base, 0, 0);
};
base.src = lista[i];
ctx.scale(0.5,0.5);
};
};
It draws only the last image on the last canvas (I have many canvas and I draw an image for each).
This will not work because you keep overwriting the image for every iteration of the loop. There is only one variable called base, it can only hold one image so all the ones before it are lost.
function myfunction(lista) {
lista=lista
for (i=0; i<lista.length; i++) {
var canvas = document.getElementById('componenti_canvas'+i);
var ctx = canvas.getContext("2d");
var base = new Image(); // second and more loops you over write base
base.onload = function() {
ctx.drawImage(base, 0, 0); // when it load only the last image is in base
// there is only one var called base so it
// can not hold more than one image
};
base.src = lista[i];
ctx.scale(0.5,0.5);
};
};
Use a function to wrap all the required vars so that you create a unique set for each image.
function myfunction(lista) {
lista.forEach((name,i)=>{ // each time the call back is called a
// new set of variables are created to
// store each unique image.
var base = new Image();
base.src = name;
base.onload = function() { ctx.drawImage(base, 0, 0); };
var canvas = document.getElementById('componenti_canvas'+i);
var ctx = canvas.getContext("2d");
ctx.scale(0.5,0.5);
});
}

Duplicating a canvas many times: clone the canvas or copy the image data?

One of my interface elements is being rendered using the HTML5 <canvas> element and associated JavaScript API. This element is used in several places on the same screen and on multiple screens throughout the app. What is the most efficient way to display this everywhere it's required?
My first idea is to draw to a master canvas, which I then clone and insert where needed in the page. The master canvas might be something like:
var master = $('<canvas>').attr({
width: 100,
height: 100
}),
c = master[0],
ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
Let's say I want to duplicate the canvas in these div containers:
<div class="square-container" id="square_header"></div>
...
<div class="square-container" id="square_dataTable"></div>
...
<div class="square-container" id="square_gallery"></div>
....
When the page loads, I'll do this to insert a duplicate canvas element into each container:
$(document).ready(function() {
$('.square-container').each(function() {
master.clone().appendTo($(this));
});
});
The content being rendered on the canvas is going to be more complex than the simple square used in this example but will still end up being just a static image. It is possible, though, that there could be dozens of different images each cloned dozens of times per page.
The other approach I had in mind was to create an image using the toDataURL() method and set that as the appropriate images' sources:
var master = $('<canvas>').attr({
width: 100,
height: 100
}),
c = master[0],
ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,150,75);
var square = c.toDataURL('image/png');
I would add image tags where necessary:
<img src="" id="square_header" class="square" alt="" />
...
<img src="" id="square_dataTable1" class="square" alt="" />
...
<img src="" id="square_gallery" class="square" alt="" />
....
And then set all of their SRCs to that newly created image:
$(document).ready(function() {
$('img.square').attr('src', square);
});
To me, it pretty much looks like six of one, half dozen of the other. But I'm wondering if one way is considered better practice than the other? If the content being rendered on the <canvas> were more complex, would one way be more efficient than the other?
In that same spirit, when I need to use that element on subsequent pages, is it best to execute all the javascript (from whatever solution is deemed best above) on each page or would saving the value of CANVAS_ELEMENT.toDataURL() in a cookie and then using that on subsequent pages be any more efficient?
Cloning a canvas will duplicate its dimensions and styling, but not its image data. You can copy the image data by calling drawImage on the context. To paint the contents of originalCanvas onto duplicateCanvas, write:
duplicateCanvas.getContext('2d').drawImage(originalCanvas, 0, 0);
As a demonstration, the following snippet generates four canvases:
an original canvas with a small scene painted onto it
a copy made by calling cloneNode only
a copy made by calling cloneNode and drawImage
a copy made by creating a new image and setting its source to the data URI
function message(s) {
document.getElementById('message').innerHTML += s + '<br />';
}
function timeIt(action, description, initializer) {
var totalTime = 0,
initializer = initializer || function () {};
initializer();
var startTime = performance.now();
action();
var elapsed = performance.now() - startTime;
message('<span class="time"><span class="number">' +
Math.round(elapsed * 1000) + ' μs</span></span> ' + description);
}
function makeCanvas() {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = 100;
canvas.height = 100;
timeIt(function () {
context.fillStyle = '#a63d3d';
context.fillRect(10, 10, 80, 40); // Paint a small scene.
context.fillStyle = '#3b618c';
context.beginPath();
context.arc(60, 60, 25, 0, 2*Math.PI);
context.closePath();
context.fill();
}, '(millionths of a second) to draw original scene', function () {
context.clearRect(0, 0, canvas.width, canvas.height);
});
return canvas;
}
// copyCanvas returns a canvas containing the same image as the given canvas.
function copyCanvas(original) {
var copy;
timeIt(function () {
copy = original.cloneNode(); // Copy the canvas dimensions.
copy.getContext('2d').drawImage(original, 0, 0); // Copy the image.
}, 'to copy canvas with cloneNode and drawImage');
return copy;
}
// imageFromStorage extracts the image data from a canvas, stores the image data
// in a browser session, then retrieves the image data from the session and
// makes a new image element out of it. We measure the total time to retrieve
// the data and make the image.
function imageFromStorage(original) {
var image,
dataURI = original.toDataURL();
timeIt(function () {
image = document.createElement('img');
image.src = dataURI;
}, 'to make image from a dataURI');
return image;
}
function pageLoad() {
var target = document.getElementById('canvases'),
containers = {}, // We'll put the canvases inside divs.
names = ['original', 'cloneNode', 'drawImage', 'dataURI'];
for (var i = 0; i < names.length; ++i) {
var name = names[i], // Use the name as an ID and a visible header.
container = document.createElement('div'),
header = document.createElement('div');
container.className = 'container';
header.className = 'header';
header.innerHTML = container.id = name;
container.appendChild(header);
target.appendChild(container);
containers[name] = container; // The canvas container is ready.
}
var canvas = makeCanvas();
containers.original.appendChild(canvas); // Original canvas.
containers.cloneNode.appendChild(canvas.cloneNode()); // cloneNode
containers.drawImage.appendChild(copyCanvas(canvas)); // cloneNode + drawImage
containers.dataURI.appendChild(imageFromStorage(canvas)); // localStorage
}
pageLoad();
body {
font-family: sans-serif;
}
.header {
font-size: 18px;
}
.container {
margin: 10px;
display: inline-block;
}
canvas, img {
border: 1px solid #eee;
}
#message {
color: #666;
font-size: 16px;
line-height: 28px;
}
#message .time {
display: inline-block;
text-align: right;
width: 100px;
}
#message .number {
font-weight: bold;
padding: 1px 3px;
color: #222;
background: #efedd4;
}
<div id="canvases"></div>
<div id="message"></div>
If you call toDataURL to copy the image data into a string for use in other pages, don't put the string into a cookie. Cookies are meant to store small amounts of data. Instead, use the HTML5 Web Storage API to store the image data in the browser. Alternatively, if the image doesn't change between user sessions, you can render it to a PNG image on a server and use the Cache-Control header to encourage the browser to cache the image file for fast retrieval.
When it comes to the performance of client-side image rendering, it may be faster to draw the scene anew than to paint the stringified image data onto the canvas. Decoding the string and painting the pixels is a relatively expensive operation. To find out if it makes sense to redraw the scene on each page, you can time your drawing operations with performance.now, as demonstrated in the snippet.

javascript push() failing

I'm trying to add cards to an array in a Deck object but for some reason push() is failing. I had this working earlier but after making some changes, I have effectively messed it up.
(The "testX" writes are there for debugging purposes)
<!DOCTYPE HTML>
<html>
<head>
<style>
#myCanvas {
border: 1px solid #9C9898;
}
body {
margin: 0px;
padding: 0px;
}
</style>
<script type="text/javascript">
<!--
//draws the game
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
//draws the rectangles that will be the card
var cardHeight = 125,
cardWidth = 80;
context.beginPath();
//draws the top row of 5 cards
for(var x=0;x<5;x++){
context.rect(10+(x*(cardWidth+10)),10,cardWidth,cardHeight);
}
//draws the bottom row of 5 cards
for(x=0;x<5;x++){
context.rect(10+(x*(cardWidth+10)),150,cardWidth,cardHeight);
}
//draws the deck
context.rect(10+5*cardWidth+65,(150-10)/2,cardWidth,cardHeight);
context.fillStyle = 'white';
context.fill();
context.lineWidth = 2;
context.strokeStyle = 'black';
context.stroke();
};
function Deck(){
//creates the unshuffled deck (loadedDeck) once to make the shuffling process faster
var loadedDeck = new Array(),
realDeck;
this.loadTheDeck = function(){ //method
for(x=1;x<=13;x++){
this.loadedDeck.push(x+" Spades"); //<---issue line (all 4 are failing though this is the first)
this.loadedDeck.push(x+" Clubs");
this.loadedDeck.push(x+" Hearts");
this.loadedDeck.push(x+" Diamonds");
}
document.write(this.loadedDeck);
};
this.loadTheDeck(); //creates the unshuffled deck when the Deck is instantiated
//resets the deck and randomizes
this.shuffle = function(){ //method
//creates the real deck
this.realDeck = this.loadedDeck;
//write shuffle function
};
this.shuffle(); //shuffles the Deck when instantiated
}
document.write("test-1");
var myDeck = new Deck();
document.write("test0");
document.write(this.realDeck);
document.write("test1");
-->
</script>
</head>
<body>
<canvas id="myCanvas" height="300" width="600"></canvas>
</body>
</html>
Here is a demo of the code: http://jsfiddle.net/NfmsR/2/
When you run this line:
this.loadedDeck.push(x+" Spades");
You are using the this.loadedDeck array. Have you defined it as part of the Deck object? Nope:
var loadedDeck = new Array(),
realDeck;
Change the declaration to this and it should work:
this.loadedDeck = []; // I'd use [] instead of new Array().
this.realDeck = [];
As #j08691 pointed out, you need to change realDeck to this.realDeck as well because you're calling it similarly here:
this.shuffle = function(){ //method
//creates the real deck
this.realDeck = this.loadedDeck;
//write shuffle function
};
You're referring to "loadedDeck" as if it's a property of your "Deck" object. It's not; it's just a local variable to the constructor closure.
Just call it "loadedDeck" and see if that helps. Same goes for "realDeck".
this.loadTheDeck = function(){ //method
for(var x=1;x<=13;x++){
loadedDeck.push(x+" Spades"); //<---issue line (all 4 are failing though this is the first)
loadedDeck.push(x+" Clubs");
loadedDeck.push(x+" Hearts");
loadedDeck.push(x+" Diamonds");
}
Also it'd be a good idea to get out of the habit of abusing document.write for debugging. Also don't forget to declare things like "x" with var!!
Your Deck object, which is accessed with this, has no "loadedDeck"-property. loadedDeck is a local variable. Just remove the "this.".

Categories

Resources