Calling function inside function - raphael

I'm trying to learn (develop) some game using HTML5 and TypeScript. I write this part of code:
class GameMap {
private sheet: RaphaelPaper;
private tiles: Tile[];
constructor() {
this.tiles = [];
this.sheet = Raphael(document.getElementById('canvas_container'), 500, 500);
}
render() {
var tileWidth = 20;
var tileHeight = 20;
for (var i = 0; i < 30; i++) {
for (var j = 0; j < 30; j++) {
this.tiles.push(new Tile(i, j));
var rectangle = this.sheet.rect(i * tileWidth, j * tileHeight, tileWidth, tileHeight);
rectangle.hover(this.tileMouseOn(), this.tileMouseOut(), rectangle, rectangle);
}
}
}
tileMouseOn() {
this.attr({ 'stroke-width': 1 });
}
tileMouseOut() {
this.attr({ 'stroke-width': 0 });
}
}
The problem is with rectangle.hover() function. I recieve following error:
Supplied parameters do not match any signature of call target:
Could not apply type 'Function' to argument 1 which is of type 'void'.
What is wrong with this function?

hover() is expecting to have function reference as 2 first arguments. Try with this :
rectangle.hover(this.tileMouseOn, this.tileMouseOut, rectangle, rectangle);

Related

chartjs how to apply after animation

trying to extend a chart, so that i can draw lines up to the data point, but this is happening before the default animation. it would look smoother if it applied after.
i have got most of it to work.. but how do i get this to apply after chart animation.
var originalLineDraw = Chart.controllers.line.prototype.draw;
Chart.helpers.extend(Chart.controllers.line.prototype, {
draw: function () {
originalLineDraw.apply(this, arguments);
var chart = this.chart;
var ctx = chart.chart.ctx;
var index = chart.config.data.lineAtIndex;
if (index) {
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-1']
var points = this.chart.getDatasetMeta(this.index).data;
for (var i = 0; i < points.length; i++) {
// var point_x = points[i]._model.x;
var point_y = points[i]._model.y;
ctx.beginPath();
ctx.setLineDash([5, 5]);/*dashes are 5px and spaces are 3px*/
ctx.moveTo(xaxis.getPixelForValue(undefined, i), point_y);
ctx.strokeStyle = '#fff';
ctx.lineTo(xaxis.getPixelForValue(undefined, i), yaxis.bottom);
ctx.stroke();
}
}
}
});
Update...
altho the darw is incorrect it still is playing after animation
var verticalLinePlugin = {
renderVerticalLine: function (chartInstance) {
var chart = chartInstance;
var ctx = chart.chart.ctx;
var maxpoint = [];
//loop the datasets
for (var y = 0; y < chart.config.data.datasets.length; y++) {
var dataset = chart.config.data.datasets[y];
if (dataset.hidden)
continue;
var points = chart.getDatasetMeta(y).data;
for (var i = 0; i < points.length; i++) {
var point_y = points[i]._model.y;
if (point_y < 0)
continue;
var point = maxpoint[i];
if (point == undefined) {
maxpoint.push({ id: i, y: point_y });
} else {
if (point.y > point_y) {
point.y = point_y;
}
}
}
}
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-1']
chart.data.datasets.forEach(function (dataset, i) {
var ds = dataset;
var meta = chart.getDatasetMeta(i);
meta.data.forEach(function (element, index) {
var value = maxpoint[i];
ctx.beginPath();
ctx.setLineDash([5, 5]);
ctx.moveTo(xaxis.getPixelForValue(undefined, i), value.y);
ctx.strokeStyle = '#fff';
ctx.lineTo(xaxis.getPixelForValue(undefined, i), yaxis.bottom);
ctx.stroke();
});
});
},
afterRender: function (chart) {
this.renderVerticalLine(chart);
}
};
Chart.plugins.register(verticalLinePlugin);
I made some small changes (non-intuitive!), and the vertical lines now appear after the animation.
Get the x values from the metadata instead of the data.
Either:
var x_point = element._model.x;
or:
var position = element.tooltipPosition();
var x_point = position.x;
Wrap the drawing in if(!hidden){}, then the vertical lines will disapear and reappear with the data. (The ternary assignment fixes a clash if the data starts hidden)
Do you need the value=max[i]? If just drawing the line up to the points, can get the y_point the same as for x.
var xaxis = chart.scales['x-axis-0'];
var yaxis = chart.scales['y-axis-1'];
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.getDatasetMeta(i);
var hidden = (meta.hidden != undefined) ? meta.hidden : dataset.hidden
if(!hidden){
meta.data.forEach(function (element, index) {
//var value = maxpoint[i];
var x_point = element._model.x;
var y_point = element._model.y;
ctx.beginPath();
ctx.save();
ctx.setLineDash([5, 5])
ctx.strokeStyle = '#fff';
ctx.moveTo(x_point, y_point); // or value.y
ctx.lineTo(x_point, yaxis.bottom)
ctx.stroke();
ctx.restore();
});
}
});

Ember view doesn't update after ArrayController is sorted

I have an Ember Array Controller that is binded to Ember select view that gets sorted by the user if they choose to. Once everything runs through my sort and I reset the array with the now sorted array the view doesn't change but if I loop through the array that I just set, it shows that it is sorted. So the view isn't updating with the array controller, I believe. I was looking at other posts with similar problems but none of the solutions from them worked for me.
dmp: Ember.ArrayController.create(),
tempArray: new Array(),
sort: function() {
debugger;
var self = this;
var textA, textB, i, t, pos, temp;
this.set('tempArray', self.dmp.get('content'));
var nxt;
for(t = 0; t < (self.get('tempArray').length) - 1; t++) {
nxt = this.get('tempArray')[t];
for(i = t; i < self.get('tempArray').length; i++) {
if(self.get('tempArray')[i].name.toUpperCase() <= nxt.name.toUpperCase()) {
nxt = self.get('tempArray')[i];
pos = i;
}
}
temp = self.get('tempArray')[t];
self.get('tempArray')[t] = nxt;
self.get('tempArray')[pos] = temp;
}
//App.defRouteSearch.dmpName.set('content', self.get('tempArray'));
//App.defRouteSearch.dmp.set('content', self.get('tempArray'));
self.setArray();
},
setArray: function() {
debugger;
var a = 0, b = 1;
var self = this;
while(a < this.get('tempArray').length) {
self.get('dmp').toArray[b] = self.get('tempArray')[a];
a++;
b++;
}
}
I switch everything over to a normal js array because it's quicker to manipulate data than compared to the Array Controller, I do this throughout the rest of my code when filling the 6 other arrays I have so that's not causing any problems. The commented code was what I was doing before to set the array.
Thanks for any help.
No need to do all of this. This should do the trick:
App.MyArrayController = Ember.ArrayController.create({
content: songs,
sortProperties: ['name'],
sortAscending: true
});
I was able to get it to work after a while. Here's my sort now
sortName: function() {
var self = this;
var i, t, pos, temp;
this.set('tempArray', new Array());
this.set('tempArray', self.dmp.get('content'));
var nxt;
for(t = 0; t < (self.get('tempArray').length) - 1; t++) {
nxt = this.get('tempArray')[t];
for(i = t; i < self.get('tempArray').length; i++) {
if(self.get('tempArray')[i].name.toUpperCase() <= nxt.name.toUpperCase()) {
nxt = self.get('tempArray')[i];
pos = i;
}
}
temp = self.get('tempArray')[t];
self.get('tempArray')[t] = nxt;
self.get('tempArray')[pos] = temp;
}
self.dmp.set('content', self.tempArray.clone());
},
Array.prototype.clone = function () {
var newObj = [];
for (i in this) {
if (this[i]) {
if ($.isPlainObject(this[i])) {
newObj[i] = $.extend(true, {}, this[i]);
}
else if ($.isArray(this[i])) {
this[i].clone();
}
else {
newObj[i] = this[i];
}
}
}
return newObj;
};
I'm not entirely sure why it works but it does. The small bit of reasoning I was able to come up with is that in js when you copy an array it's only referenced and not actually copied. But then I shouldn't need the clone() at the end since the referenced array was modified. Feel free to correct me if I'm wrong.

Optimizing Set Drag and Drop in RaphaelJS

So I tried to use translate and call the drag event on the set when certain elements in the set have the drag event intiated on them. But it's a little slow. Does anyone know how to optimize to make it faster?
Here's the function im using
function dragsymbolsoncanvas(foo){//foo is the set passed.
function dragger(){
this.dx = this.dy = 0;
};
function mover(s){
return function(dx, dy){
(s||this).translate(dx-this.dx,dy-this.dy);
this.dx = dx;
this.dy = dy;
}
};
foo.forEach(function(herp){//set.forEach function from raphaeljs
if(herp.data("candrag")=="true"){
foo.drag(mover(foo), dragger);
}
});
};
Is there a way to make this faster without drawing an invisible element over the pieces that I want to make draggable and attaching the handlers to those?
var position;
var rect = paper.rect(20, 20, 40, 40).attr({
cursor: "move",
fill: "#f00",
stroke: "#000"
});
t = paper.text(70,70, 'test').attr({
"font-size":16,
"font-family":
"Arial, Helvetica, sans-serif"
});
var st = paper.set();
st.push(rect, t);
rect.mySet = st;
rect.drag(onMove, onStart, onEnd);
onStart = function () {
positions = new Array();
this.mySet.forEach(function(e) {
var ox = e.attr("x");
var oy = e.attr("y");
positions.push([e, ox, oy]);
});
}
onMove = function (dx, dy) {
for (var i = 0; i < positions.length; i++) {//you can use foreach but I want to show that is a simple array
positions[i][0].attr({x: positions[i][1] + dx, y: positions[i][2] + dy});
}
}
onEnd = function() {}

cocos2d-html5 can't make a basic ccmenu work

Sorry if this is a newbie question but I have just started using cocos2d-html and I am having some issues creating a ccmenu with an image. Here is my code:
var ActionLayer = cc.Layer.extend({
getTexture: function (name) {
return cc.TextureCache.getInstance()
.addImage('./images/' + name + '.png');
},
addObject: function (desc) {
var sprite = cc.Sprite.createWithTexture(this.getTexture(desc.name));
sprite.setAnchorPoint(desc.anchor || cc.p(0.5, 0.5));
sprite.setScaleX(desc.scaleX || desc.scale || 1);
sprite.setScaleY(desc.scaleY || desc.scale || 1);
sprite.setRotation(desc.rotation || 0);
sprite.setPosition(cc.p(desc.x || 0, desc.y || 0));
this.addChild(sprite, desc.z || 0);
return sprite;
},
checkAnswer:function(){
alert('yay');
},
init: function () {
this._super();
this.removeAllChildrenWithCleanup(true);
this.setTouchEnabled(true);
var layer1 = cc.LayerColor.create(
new cc.Color4B(00, 185, 214, 255), 1024, 768);
layer1.setPosition(new cc.Point(0.0,0.0));
this.addChild(layer1,-2);
var director = cc.Director.getInstance(),
self = this,
winSize = director.getWinSize();
var bgSprite = this.addObject({
name: "GenericBG",
scaleY: 1,
anchor: cc.p(0, 0),
z: 0
});
var closeItem = cc.MenuItemImage.create('./images/sign.png','./images/sign.png',this,'checkAnswer');
closeItem.setAnchorPoint(cc.p(0.5, 0.5));
var menu = cc.Menu.create(closeItem);
menu.setPosition(500,300);
this.addChild(menu, 5);
}
}); //end ActionLayer
//--------------------- Scene ---------------------
var ActionLayerScene = cc.Scene.extend({
onEnter: function () {
this._super();
var layer = new ActionLayer();
layer.init();
this.addChild(layer);
}
});
The menu is displayed on the screen but when I click on the menuitem, nothing happens
There is no javascript error on the console so I really don't know how to debug this.
Thanks
Cyril
Your parameter for cc.MenuItemImage.create() is wrong. Instead of:
var closeItem = cc.MenuItemImage.create('./images/sign.png','./images/sign.png',this,'checkAnswer');
it should be:
var closeItem = cc.MenuItemImage.create('./images/sign.png','./images/sign.png','checkAnswer', this);
for(var i=0; i<5; i++){
var colorImg = cc.MenuItemImage.create(color_list[i], color_list[i], "colorAction", this);
colorImg.setPosition(new cc.Point(40+i*70, 38));
colorImg.tag = i+100;
this.colorImageArray.push(colorImg);
colorMenu.addChild(colorImg);
}
colorAction:function(event)
{
var colorTag = event.tag;
switch(colorTag)
{
case 1:
break;
case 2:
break;
case 3:
break;
}
}

Raphael.js onmouseover onmouseout event

I've made 4 rectangles in raphael.js using the for loop. When I apply events such as onmouseover or onmouseout it applies only to the last rectangle created. I know something is wrong in my code. Please provide a solution and is there a way to simplify the code?
JS Fiddle Link
window.onload = function(){
var paper = Raphael(0,0,640,540);
for (i=0;i<2;i++){
for (j=0;j<2;j++){
var boxes = paper.rect(0+(j*320),0+(i*270),320,270).attr({fill:'#303030',stroke:'white'});
boxes.node.onmouseover = function () {
boxes.attr("fill", "blue");
};
boxes.node.onmouseout = function () {
boxes.attr("fill", "#303030");
};
}
}
}​
This is an extremely common mistake in javascript. You reuse the boxes variable, so when any of the handlers are executed, it points to the last value it had.
The common way of overcoming this is to wrap the code inside the loop in a function call:
window.onload = function() {
var paper = Raphael(0, 0, 640, 540);
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
(function(i, j) {
var boxes = paper.rect(0 + (j * 320), 0 + (i * 270), 320, 270).attr({
fill: '#303030',
stroke: 'white'
});
boxes.node.onmouseover = function() {
boxes.attr("fill", "blue");
};
boxes.node.onmouseout = function() {
boxes.attr("fill", "#303030");
};
})(i, j);
}
}
}
​