I have homework from university, classic 15 puzzle. I have problem with those two styles. Here is the code that i have problem
function siirra_pala(pala) {
var palaRivi = parseInt(pala.style.top) / palanKoko;
var palaSarake = parseInt(pala.style.left) / palanKoko;
}
Error code is "Uncaught TypeError: Cannot read property 'top' of undefined" and "Uncaught TypeError: Cannot read property 'left' of undefined".
If it helps:
siirra_pala(pala) is move_tile(tile)
palaRivi is tileRow and palaSarake is tileColumn
palanKoko is tileSize.
I have palanKoko set to 100. And style is defined in:
function muodosta_palat(pelialue) {
for (var y = 0; y < 4; y++) {
for (var x = 0; x < 4; x++) {
if (!(x === tyhja_paikka.x && y === tyhja_paikka.y)) {
var pala = document.createElement('div');
pala.id = 'pala' + x + y;
pala.textContent = 4 * y + x + 1;
pala.style.left = x * palanKoko + 'px';
pala.style.top = y * palanKoko + 'px';
pala.className = 'pala';
pelialue.appendChild(pala);
}
}
}
If you need more code, please tell which one. Thank You
#Bergi:
window.onload = function () {
muodosta_palat(document.getElementById('pelialue'));
var palat = document.querySelectorAll(".pala");
document.getElementById('sekoitusnappi').onclick = sekoita;
for (var i = 0; i < palat.length; i++) {
palat[i].addEventListener("click", siirra_pala);
palat[i].addEventListener("mouseover", mouseOver);
palat[i].addEventListener("mouseout", mouseOut);
}
};
From your error it would seem pala is undefined (not set, doesn't exist), at least not in the scope of that function.
Variable pala is created within a function, and it's only known in this function. What you want to do is capture the click event, and pass what was clicked to the function.
If you change call to the function..
palat[i].addEventListener("click", function () { siirra_pala(this) });
the reference should be ok.
Here:
palat[i].addEventListener("click", siirra_pala);
the parameter passed to siirra_pala is the click event, not the clicked element. You should modify your function to either select the clicked element property from the event object or simply use this.
See this:
document.getElementById('x').addEventListener("click", handler);
function handler(e) {
console.log(e); // full event object
console.log(this); // clicked element
this.style.background = "#aaa";
}
#x {
width: 50px;
height: 50px;
background: #eee;
}
<div id="x"></div>
So the fix for your function would be something like this:
function siirra_pala(pala) {
var palaRivi = parseInt(this.style.top) / palanKoko;
var palaSarake = parseInt(this.style.left) / palanKoko;
}
(bear in mind that this function is not very useful)
Related
I have an object set up like so:
let xVal = 0;
const myObj = {
infoText: "The value of x is: " + xVal
}
This infoText is referenced later to display somewhat of a tooltip when hovering over an element.
function showTooltip(obj) {
targetEl = document.getElementById('targetId');
targetEl.innerHTML = obj.infoText;
}
The value of xVal can change. The issue I'm running into is that despite whether or not that value has changed, when I hover over my element, it will always display the initial value of xVal. I assume this is because myObj.infoText is established when it's initiated and pulls the initial value of xVal. How can I get myObj.infoText to show the current xVal and keep up with the changes?
EDIT - Here is a better example of my code, I realize I offered a poor sample originally.
let count = 0;
let clickVal = 1;
const myObj = {
cost: 10,
infoText: `This displays the current value of your click <br />
Current click = ` + clickVal
};
function cardContent(obj) {
targetEl = document.getElementById('targetId');
targetEl.innerHTML = obj.infoText;
}
cardContent(myObj); // initialize card content
function handleClick() {
count += clickVal;
}
function upgradeClick() {
count -= myObj.cost;
clickVal += 1;
cardContent(myObj) // attempting to update the text to reflect new value
}
There is a button that invokes handleClick and one that invokes upgradeClick. Using CSS, the following div is hidden and shows when hovering over the upgradeClick button.
<div id='targetId'></div> This is where the infoText shows.
You can use something like a getter
let xVal = 0;
const myObj = {
get infoText() {return "The value of x is: " + xVal;}
}
function showTooltip(obj) {
console.log(obj.infoText);
}
showTooltip(myObj);
xVal = 29;
showTooltip(myObj);
xVal = 794;
showTooltip(myObj);
Creating the object everytime inside of the showTooltip should work
let xVal = 0;
function showTooltip() {
const myObj = {
infoText: "The value of x is: " + xVal
}
console.log(myObj.infoText);
}
showTooltip();
xVal = 50;
showTooltip();
Good afternoon. Is it possible to add a new object property value to its previous value?
I have tried the following code but browser returns "Maximum call stack size exceeded". The property translate will be used to drag a chart horizontally. It will shift the data range of an array that will be painted on the canvas chart. Kind regards.
function drawChart() {
.
.
.
tickerData = [..., ..., ...];
dataLength = tickerData.length;
barSpace = Number(localStorage.getItem("barspace"));
barWidth = (0.7 * barSpace).toFixed(1);
rightSpan = 3 * barSpace;
barStrokeWidth = 1;
if(!(dataLength - dragCanvas.translate() > dataLength)) {
dataLength = dataLength - dragCanvas.translate();
}
else {
dataLength = dataLength;
}
.
.
.
}
var dragCanvas = {
isTrue : false,
drag : [0, 0],
translate : function() {
return this.translate() + Math.ceil((this.drag[1] - this.drag[0])/barSpace);
}
};
function updateChartPaint(e) {
var pointerX = e.clientX;
var pointerY = e.clientY;
if(!dragCanvas.isTrue) {
dragCanvas.drag[0] = pointerX;
dragCanvas.drag[1] = pointerX;
}
else {
dragCanvas.drag[1] = pointerX;
$("#chartCanvas").empty();
drawChart();
}
}
document.addEventListener("mousemove", updateChartPaint, false);
document.getElementById("chartCanvas").onmousedown = function() {
dragCanvas.isTrue = true;
};
document.getElementById("chartCanvas").onmouseup = function() {
dragCanvas.isTrue = false;
};
You are calling this.translate() inside of the translate function so it goes into an infinite loop calling itself until eventually the call stack is exceeded.
From the way translate is called it looks like the function should be defined like this instead:
translate : function() {
const newTranslate = this.oldTranslate + Math.ceil((this.drag[1] - this.drag[0])/barSpace);
this.oldTranslate = newTranslate;
return newTranslate;
}
oldTranslate: 0
I assume that barSpace is declared outside of the function and will be a valid value. It seems to be set from localStorage but if it does not exist, then Number(localStorage.getItem("barspace")) will be zero and the return value from translate will be Infinity. Is that intended?
Also updateChartPaint sets a variable called pointerY but never uses it. Is it correct that dragging in the Y-axis is ignored and only changes in the X-axis matters?
var canvas = null;
var context = null;
var img = null;
var frames = [];
var assets = [];
var imgLoadCount = 0;
setup = function (fileArray) {
assets = fileArray;
//Loading an image
for(var i = 0; i < assets.length; i++) {
console.log(i);
frames.push(new Image()); // declare image object
frames[i].onload = onImageLoad(assets.length); //declare onload method
frames[i].src = URL.createObjectURL(assets[i]); //set url
}
};
onImageLoad = function (len) {
console.log("IMAGE!!!");
canvas = document.getElementById("my_canvas"); //creates a canvas element
context = canvas.getContext('2d');
canvas.width = window.innerWidth; //for full screen
canvas.height = window.innerHeight;
var x, y, numTilesRow;
numTilesRow = 10;
imgLoadCount++;
console.log("imgLoadCount = " + frames.length + ", length = " + len);
if(imgLoadCount != len) {
return;
}
for(var index = 0; index < len; index++) {
x = Math.floor((index % numTilesRow));
y = Math.floor(index / numTilesRow);
worldX = x * numTilesRow;
worldY = y * numTilesRow;
context.drawImage(frames[index], worldX, worldY);
}
};
I cant tell why drawImage has suddenly stopped working after inserting the code
if(imgLoadCount != len) {return;} that makes sure that all images are properly loaded. Would some one please help me find a solution to this problem.
You'll have to understand the difference between a function reference and a function call. The .onload property expects to be assigned with a function reference, but you assign it with the return value of the immediate(!) call to the function .onImageLoad. The difference is the parentheses ().
If you want to call a function with parameters as a callback to .onload, then you'd have to include it into an anonymous function (which itself is a function reference)
frames[i].onload = function() {onImageLoad(assets.length);};
With this, of course, you create a closure. This means that at the point of execution the onImageLoad() method will have access to the current value of assets.length (and not to the value at the point of assignment!). But in your case this doesn't make any difference, because assets.length never changes.
I'm trying to create multiple instances of a slider on a page. Each slider should know which slide it’s currently viewing. It seems that when I update the slide property, I change it for the class, and not the instance. This suggests to me that I'm not instantiating properly in my public init() function. Where am I going wrong?
var MySlider = (function() {
'use strict';
var animating = 0,
slides = 0, // total slides
slider = null,
slide = 0, // current slide
left = 0;
function slideNext(e) {
if ((slide === slides - 1) || animating) return;
var slider = e.target.parentNode.children[0],
x = parseFloat(slider.style.left);
animate(slider, "left", "px", x, x - 960, 800);
slide++;
}
return {
init: function() {
var sliders = document.querySelectorAll('.my-slider'),
l = sliders.length;
for (var i = 0; i < l; i++) {
sliders[i] = MySlider; // I don't think this is correct.
slider = sliders[i];
buildSlider(slider);
}
}
}
})();
Based on your comment, I think this is more like what you want:
MySlider = (function () {
Slider = function (e) {
this.e = e;
// other per element/per slider specific stuff
}
...
var sliders; // define this out here so we know its local to the module not init
return {
init: function () {
sliders = document.querySelectorAll('.my-slider');
var l = sliders.length;
for (var i = 0; i < l; i++) {
sliders[i] = new Slider(sliders[i]); //except I'd use a different array
slider = sliders[i];
buildSlider(slider);
}
}
})();
This way, you are associating each element with it's own element specific data but you have a containing module within which you can operate on your collection of modules.
It seems that when I update the slide property, I change it for the class, and not the instance.
You are correct. That code is run only when the MySlider class is defined. If you want an instance variable, you need to declare it inside the returned object, ie, part of your return block:
var MySlider = (function(param) {
return {
slider: param,
init: function() {
var sliders = document.querySelectorAll('.my-slider'),
l = sliders.length;
for (var i = 0; i < l; i++) {
sliders[i] = MySlider; // I don't think this is correct.
slider = sliders[i];
buildSlider(slider);
}
}
});
I'm trying to change a position of a image that I have in HTML by using javascript. I can actually get it working if I have the following code:
function main()
{
var catOne = document.getElementById("cat1");
catOne.style.left = cat1.getX().toString() + "px";
catOne.style.top = cat1.getY().toString() + "px";
}
but when I change the code to this:
var catOne = new Cat("cat1", 300, 100);
function main()
{
catOne.setUp();
}
it doesn't work. and I dont know why, but it only gives me an error of "TypeError: Cannot read property 'style' of null"
This is my Cat class in javascript:
function Cat(id, x, y)
{
this.cat = document.getElementById(id);
this.x = x;
this.y = y;
}
Cat.prototype.setUp = function ()
{
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Cat.prototype.getX = function ()
{
return this.x;
};
Cat.prototype.getY = function ()
{
return this.y;
};
TypeError: Cannot read property 'style' of null means your catOne does not exist in the DOM tree.
You should instantiate the Cat class when the DOM is ready (or on window load).
I don't know why you need that main() function but when does it execute? It should also execute when the DOM is ready.
var catOne;
function main() {
catOne.setUp();
}
window.onload = function() {
catOne = new Cat("cat1", 300, 100);
main();
}
I also suggest that you set the position of your cat to absolute if you are positioning it like that in your setUp() function. (I think you are already doing this with your CSS):
Cat.prototype.setUp = function ()
{
this.cat.style.position = 'absolute';
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Here is the fiddle.
Other than that your code should work.
with:
var catOne = new Cat("cat1", 300, 100);
catOne.setUp();
works just fine.
I don't quite get it how You managed to get error You mentioned
link: http://jsfiddle.net/Z74mM/