Trigger Events Inside Anonymous Object - javascript

I'm trying to create an anonymous object that will append a new canvas element to the DOM. This all works fine, but when I try to register an event with JQuery on the newly appended canvas from within the Object it does not trigger.
I believe it has something to do with the scope, but how would one go about registering these events?
var game_grid;
$(function() {
game_grid = new GameGrid();
});
(function (window) {
function GameGrid() {
this.initialize();
}
GameGrid.prototype.canvas;
GameGrid.prototype.ctx;
GameGrid.prototype.initialize = function() {
// Append Child to DOM element
this.canvas = document.createElement("canvas");
this.canvas.width = $(".game-grid-container").width();
this.canvas.height = $(".game-grid-container").height();
this.canvas.id = "game_grid";
$(".game-grid-container").html(this.canvas);
// Define Canvas' Context
this.ctx = this.canvas.getContext("2d");
// Set Up Touch Listeners
$(this.canvas).on("vmousedown vmousemove vmouseup", function(e) {
alert("Not Triggering!");
});
}
window.GameGrid = GameGrid;
} (window));

So the answer I found was to stray away from JQuery all together and bind the event with the addEventListener function. I'm sure there is a way to do this with JQuery, but I can confirm this works.
(function (window) {
function GameGrid() {
this.initialize();
}
GameGrid.prototype.canvas;
GameGrid.prototype.ctx;
GameGrid.prototype.background_color = '#F0F0F0';
GameGrid.prototype.grid_line_color = '#D9D9D9';
GameGrid.prototype.horizontal_division = 8;
GameGrid.prototype.vertical_division = 8;
/* Public Functions */
GameGrid.prototype.initialize = function() {
// Append Child to DOM
this.canvas = document.createElement('canvas');
this.canvas.width = $('.game-grid-container').width();
this.canvas.height = $('.game-grid-container').height();
this.canvas.id = 'game_grid';
$('.game-grid-container').append(this.canvas);
// Define Canvas' Context
this.ctx = this.canvas.getContext('2d');
// Set Up Touch Listeners
document.getElementById('game_grid').addEventListener('mousedown', function(e) {
alert('triggering!');
});
}
window.GameGrid = GameGrid;
} (window));

Related

Class method breaks after resize event listener

Here is a small example of my problem. I am trying to build a responsive class that will adjust my page when I change the width size.
Upon changing the size the method that was originally called disappears. You can test it yourself by adjusting the page size.
class PageManager {
constructor() {
this.width;
this.isMobile;
}
init() {
this.attachListeners();
this.widthChanges();
this.adjustPage();
}
attachListeners() {
window.addEventListener("resize", this.widthChanges);
}
widthChanges() {
this.width = window.innerWidth;
this.adjustPage();
if (this.width < 491) {
this.isMobile = true
} else {
this.isMobile = false
}
}
adjustPage() {
console.log("fired");
}
}
const pageManager = new PageManager();
pageManager.init();
You're having a scope problem, the function adjustPage doesn't exists under the scope of the function widthChanges.
When you call this.adjustPage() in the function widthChanges, this will be the context of the function widthChanges not the context of the class PageManager, so, the function ajustPage doesn't exist.
You can fix your problem binding the class context into the functions, just like bellow.
You can find a little bit more about this and scrope here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
class PageManager {
constructor() {
this.width;
this.isMobile;
this.attachListeners = this.attachListeners.bind(this);
this.widthChanges = this.widthChanges.bind(this);
}
init() {
this.attachListeners();
this.widthChanges();
this.adjustPage();
}
attachListeners() {
window.addEventListener("resize", this.widthChanges);
}
widthChanges() {
this.width = window.innerWidth;
this.adjustPage();
if (this.width < 491) {
this.isMobile = true
} else {
this.isMobile = false
}
}
adjustPage() {
console.log("fired");
}
}
const pageManager = new PageManager();
pageManager.init();
The callback to addEventListener is called with the object on which the event was added (in this case, the window) bound as this. You can either use an arrow function or bind the this value yourself.
window.addEventListener("resize", this.widthChanges.bind(this));
//or
window.addEventListener("resize", ()=>this.widthChanges());

JavaScript: addEventListener for mousewheel (and other types) not working

Need to implement a zoom in/out (and panning) function for the canvas element. This is my first attempt at JavaScript events, so my non-existent experience could be the issue here. I don't know if I'm using the types correctly. Used what I found online.
function onLoad() {
var canvas;
var context;
var exampleFamilyTrees;
var topPerson;
var previousMousePosition;
var mousePosition
var pan;
var mouseDown;
var zoom;
function initialise() {
canvas = document.getElementById('canvas');
if (!canvas) {
alert('Error: Canvas element not found');
return;
}
context = canvas.getContext('2d');
if (!context) {
alert('Error: Unable to get canvas context');
return;
}
exampleFamilyTrees = new ExampleFamilyTrees();
topPerson = exampleFamilyTrees.getFamilyTree(0);
pan = new Vector(0, 0);
zoom = 1;
//context.translate(canvas.width*0.5, canvas.height*0.5);
}
function draw() {
context.save();
context.translate(pan.getX(), pan.getY());
context.scale(zoom, zoom);
topPerson.draw(context);
context.restore();
}
initialise();
canvas.addEventListener('mousedown', onMouseDown, false);
canvas.addEventListener('mouseup', onMouseUp, false);
canvas.addEventListener('mousemove', onMouseMove, false);
canvas.addEventListener('mousewheel', onMouseWheel, false);
function onMouseDown(event) {
previousMousePosition = new Vector(event.clientX, event.clientY);
mouseDown = true;
}
function onMouseUp(event) {
mouseDown = false;
}
function onMouseMove(event) {
mousePosition = new Vector(event.clientX, event.clientY);
if (mouseDown) {
var difference = mousePosition.subtract(previousMousePosition);
pan.add(difference);
}
previousMousePosition = mousePosition;
}
function onMouseWheel(event) {
var wheelDelta = event.wheelDelta;
if (wheelDelta > 0){
zoom = zoom * 1.1;
}
else {
zoom = zoom * 0.9;
}
}
setInterval(draw, 1000/60);}
None of these functions work. I guess my syntax is wrong. Console doesn't complain at all.
Your events are being bound correctly, iv'e prepared a fiddle to demonstrate it, i've commented all the code regarding to Vector andExampleFamilyTrees objects because I don't have the constructor functions of them (not sure if it's a library or something you've made) and also to make the example a little more simple, since the question is about the event handlers not working.
Before commenting out those lines, I had some errors in my console regarding those objects (Vector, ExampleFamilyTrees). Maybe You are also getting those errors and that's the reason why your events are not being bound.
If you check the console after running the fiddle, you can see the logs being displayed for each of the events you want to bind.

Onload() handler not responding in IE

I'm creating a canvas and using drawImage() to draw an inline svg. Everything works okay but I'm stuck because of the below problem...
My problem is that the onload handler not responding in IE?? Rhis works in FF and chhrome. How do I fix it to work in IE 9 upwards?
img2.onload = function() {
console.log("load");
}
jsFiddle
function createme() {
var test = $('<canvas />', { id : 'mycanvs' })
$('#album').append(test);
var svg2 = document.getElementById('sSource').innerHTML,
vms = test[0], //canvas
ctx2 = vms.getContext('2d');
svgToImage(svg2);
function svgToImage(svg2) {
var nurl = "data:image/svg+xml;utf8," + encodeURIComponent(svg2),
img2 = new Image;
alert("just before onload")
img2.onload = function() {
console.log("load"); // does not show
}
img2.src = nurl;
}
}
I don't have an IE VM running at the moment, but according to their docs the handler has to be defined before the object itself:
To ensure that an event handler receives the onload event for these
objects, place the script object that defines the event handler before
the object and use the onload attribute in the object to set the
handler.
I don't see why your code wouldn't work in IE, but this fiddle tweaks it slightly so your handler is defined before you create the image object... give this a try:
function createme() {
var test = $('<canvas />', { id : 'mycanvs' });
var onloadHandler = function() {
console.log("load");
};
$('#album').append(test);
var svg2 = document.getElementById('sSource').innerHTML,
vms = test[0], //canvas
ctx2 = vms.getContext('2d');
function svgToImage(svg2) {
var nurl = "data:image/svg+xml;utf8," + encodeURIComponent(svg2),
img2 = new Image;
img2.onload = onloadHandler
img2.src = nurl;
}
svgToImage(svg2);
}
createme();
https://jsfiddle.net/z769z7af/10/

Copy/Paste element with jQuery

I have a div that I'm appending to another div when a button is clicked. I'm also calling a bunch of functions on the div that gets created.
HTML
<a onClick="drawRect();">Rect</a>
JS
function drawRect(){
var elemRect = document.createElement('div');
elemRect.className = 'elem elemRect';
elemRect.style.position = "absolute";
elemRect.style.background = "#ecf0f1";
elemRect.style.width = "100%";
elemRect.style.height = "100%";
elemRect.style.opacity = "100";
renderUIObject(elemRect);
$('.elemContainer').draggableParent();
$('.elemContainer').resizableParent();
makeDeselectable();
handleDblClick();
}
var createDefaultElement = function() {
..
..
};
var handleDblClick = function() {
..
..
};
var renderUIObject = function(object) {
..
..
};
var makeDeselectable = function() {
..
..
};
I could clone the element when the browser detects a keydown event
$(window).keydown(function(e) {
if (e.keyCode == 77) {
$('.ui-selected').clone();
return false;
}
});
then append it to #canvas. But the problem is, none of the functions I mentioned above get called with this method.
How can I copy/paste an element (by pressing CMD+C then CMD+V) and call those above functions on the cloned element?
The jQuery.clone method returns the cloned node. So you could adjust your code to do something like this:
var myNodes = $('.ui-selected').clone();
myNodes.each(function () {
createDefaultElement(this);
appendResizeHandles(this);
appendOutline(this);
});

Why doesn't this onload function run?

Why does the onLoad not get triggered?
function FULL_IMAGE(fimage){
document.getElementById("FULL_SRC").onLoad = function(){
offsetTop = document.getElementById("FULL_SRC").height / 2;
offsetLeft = document.getElementById("FULL_SRC").width / 2;
document.getElementById("FULL_SRC").style.marginTop="-"+offsetTop+"px";
document.getElementById("FULL_SRC").style.marginLeft="-"+offsetLeft+"px";
}
document.getElementById("FULL_SRC").src=fimage;
document.getElementById("FULL_VIEW").style.display="block";
}
sometimes when image is retrieved from browser cache, onload event would not be fired, thus you may do a little hack:
function FULL_IMAGE(fimage) {
var loaded = false;
function loadHandler() {
if (loaded) {
return;
}
loaded = true;
/* your code */
}
var img = document.getElementById('FULL_SRC');
img.addEventListener('load', loadHandler);
img.src = fimage;
img.style.display = 'block';
if (img.complete) {
loadHandler();
}
}
In my original code I used onLoad not onload... the second line of code should read
document.getElementById("FULL_SRC").onload = function(){
with a lowercase "l" in onload.
The definition of the event is found inside of a function block. While I have not referenced the ECMAScript specification, I can only guess that the function keyword associates the function body code with the FULL_IMAGE symbol and does not actually enter/execute the code. Therefore, it becomes necessary for the function FULL_IMAGE to be called from the global block in order to register the event. Alternatively, the event registration code can be placed in the global block. This is all of course assuming that a FULL_SRC id has been given to an element on the given HTML document.
Given the comment, the following has been posted:
(Option 1)
document.getElementById("FULL_SRC").onLoad = function(){
offsetTop = document.getElementById("FULL_SRC").height / 2;
offsetLeft = document.getElementById("FULL_SRC").width / 2;
document.getElementById("FULL_SRC").style.marginTop="-"+offsetTop+"px";
document.getElementById("FULL_SRC").style.marginLeft="-"+offsetLeft+"px";
}
function FULL_IMAGE(fimage){
document.getElementById("FULL_SRC").src=fimage;
document.getElementById("FULL_VIEW").style.display="block";
}
(Option 2)
function FULL_IMAGE(fimage){
document.getElementById("FULL_SRC").onLoad = function(){
offsetTop = document.getElementById("FULL_SRC").height / 2;
offsetLeft = document.getElementById("FULL_SRC").width / 2;
document.getElementById("FULL_SRC").style.marginTop="-"+offsetTop+"px";
document.getElementById("FULL_SRC").style.marginLeft="-"+offsetLeft+"px";
}
document.getElementById("FULL_SRC").src=fimage;
document.getElementById("FULL_VIEW").style.display="block";
}
FULL_IMAGE (myParameter);

Categories

Resources