Cocos2d-JS 3.0 migration - javascript

I'm moving from cocos2d-html5 version 2.2 to cocos2d-js 3.0 and I have a problem with this code (which works perfectly in version 2.2):
menuButtons = cc.Menu.create();
for (var a = 1; a < 6; a++){
var label = cc.LabelTTF.create("BUTTON " + a, "Arial", 20);
var tmpBtn = cc.MenuItemLabel.create(label, function (e) {
cc.log("TEST TAG: " + e.tag);
//StartSomethingOther(e);
}, this);
tmpBtn.setPosition(50, a * 30);
tmpBtn.tag = a;
menuButtons.addChild(tmpBtn,2,1);
}
menuButtons.setPosition(10, 10);
this.addChild(menuButtons, 1);
Any "button" is pressed the console always output "TEST TAG: 1" instead of putting the correct number.
Any tip to solve the problem?

Change the .tag with .title or even better a ['data-'] identifier like in this example:
menuButtons = cc.Menu.create();
for (var a = 1; a < 6; a++){
var label = cc.LabelTTF.create("BUTTON " + a, "Arial", 20);
var tmpBtn = cc.MenuItemLabel.create(label, function (e) {
cc.log("TEST TAG: " + e['data-tag']);
//StartSomethingOther(e);
}, this);
tmpBtn.setPosition(50, a * 30);
tmpBtn['data-tag'] = a;
menuButtons.addChild(tmpBtn,2,1);
}
menuButtons.setPosition(10, 10);
this.addChild(menuButtons, 1);

You're overwriting tag property here:
menuButtons.addChild(tmpBtn,2,1);
the third parameter sets tmpBtn.tag to 1.
If You want to continue to use tag property simply change:
tmpBtn.tag = a;
menuButtons.addChild(tmpBtn,2,1);
with:
menuButtons.addChild(tmpBtn,2,a);
If You don't want to use tag property, see Francesco's answer

Related

Celsius to Fahrenheit conversion- JavaScript

I'm making Celcius to Farenheit calculater. My codepen is here: https://codepen.io/j9k9/pen/zBZJQL
I'm trying to make it so that if the celcius input is active, the convert to farenheit function is called and vice versa and for the conversion to happen only when the submit button is clicked.
I also tried an if/else statement for the active form id which did not work.
Code is as follows:
HTML:
<html>
<head>
<meta charset="UTF-8">
<title>Temperature Converter - Part 1</title>
</head>
<body>
<h1>Temperature Converter</h1>
<div id="inputs">
<input id="cInput" placeholder="celcius"/>
<input id="fInput" placeholder="farenheit"/>
</div>
<button id="submit">Convert</button>
<h1 id="result">Result:</h1>
<script src="js/index.js"></script>
</body>
</html>
JS:
document.getElementById("cInput").oninput = function() {convertCToF()};
document.getElementById("fInput").oninput = function() {convertFToC()};
function convertCToF() {
var c = document.querySelector("#cInput").value;
var f = c * (9 / 5) + 32;
c = parseInt(c);
f = parseInt(f);
document.querySelector("#result").innerHTML = ("Result: ") + f + (" \u2109");
}
document.querySelector("#submit").onclick = convertCToF;
function convertFToC() {
var f = document.querySelector("#fInput").value;
var c = (f - 32) * 5 / 9;
c = parseInt(c);
f = parseInt(f);
document.querySelector("#result").innerHTML = ("Result: ") + c + (" \u2103");
}
document.querySelector("#submit").onclick = convertFToC;
I had corrected your code-pen and noted as to where, why and what could be improved but someone appears to have deleted my comment. As there isn't a concrete answer yet I'll transfer it here.
Remove these two lines if you don't want it to update on the fly:
document.getElementById("cInput").oninput = function() {convertCToF()};
document.getElementById("fInput").oninput = function() {convertFToC()};
Instead decide which "mode" of conversion the script will run based on the last input box used.
var conversionFn;
document.querySelector('#cInput').onfocus = function(){
conversionFn = convertCToF;
};
document.querySelector('#fInput').onfocus = function(){
conversionFn = convertFToC;
};
Note: that in your conversion functions the following lines are useless (remove them).
c = parseInt(c);
f = parseInt(f);
When used in expressions, variables will be coerced to a Number where appropriate - where you wish to be explicit you should do this conversion before you perform a calculation with the value.
» see also: Javascript Unary Operator as another example of this.
Next setup a listener for your button, note that you cannot simply attach the conversionFn to the event handler itself as this will assign a single unchanging reference (or undefined) immediately which is of no use - instead, encapsulate the variable in the scope of a new function closure.
document.querySelector('#submit').onclick = function(){
conversionFn();
};
Please use these functions instead.
function getFahrenheitFromCelsius(celsius){
return (celsius * (9 / 5)) + 32;
}
function getCelsiusFromFahrenheit(fahrenheit){
return (fahrenheit - 32) * (5 / 9);
}
https://codepen.io/anon/pen/mEvzOV
I have written this just for your demo
function getElm(id){
return document.getElementById(id);
}
function readValue(id){
return getElm(id).value;
}
function updateHtml(text,id){
getElm(id).innerHTML = text;
}
function convertCToF(c) {
var f = c * (9 / 5) + 32;
return f;
}
function convertFToC(f) {
var c = (f - 32) * 5 / 9;
return c;
}
function sequnce(){
var val = readValue(activeId);
var convertedVal = activeFn(val);
updateHtml("Result: "+ convertedVal + activeSuffix,'result')
}
var activeFn = convertCToF;
var activeId = 'cInput';
var activeSuffix = "℉"
getElm('cInput').onfocus = function(){
activeFn = convertCToF;
activeId = 'cInput';
activeSuffix = "℉"
}
getElm('fInput').onfocus = function(){
activeFn = convertCToF;
activeId = 'fInput';
activeSuffix = "℃"
}
getElm("cInput").oninput = sequnce;
getElm("fInput").oninput = sequnce;
getElm("submit").oninput = sequnce;

Error $.get(...).done is not a function

I have code that looks like that:
<head>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript">
function draw(){
var a = 0,
timeC = 0,
timeS = 0,
meanCFf=0,
meanSFf= 0;
$.get('test1.csv').done(function(data) {
var i,
lines = data.split('\n'),
line = lines[0].split(','),
oS = line.indexOf('oS'),
browName = line.indexOf('browName'),
browVer = line.indexOf('browVer'),
timeCanvas = line.indexOf('timeCanvas'),
timeSvg = line.indexOf('timeSvg');
for(i=1; i<lines.length; i++) {
line = lines[i].split(',');
if(line[oS] === 'Windows') {
a++;
timeC += parseFloat(line[timeCanvas], 10);
timeS += parseFloat(line[timeSvg], 10);
}
}
});
meanCFf = timeC/a;
meanSFf = timeC/a;
var os1 = document.getElementById("osInfo1");
os1.innerHTML = "Twoja średnia to: " + meanCFf;
var os2 = document.getElementById("osInfo2");
os2.innerHTML = "Twój sytem operacyjny to: " + meanSFf;
}
</script>
</head>
<body onload="draw()">
<p id="osInfo1"></p>
<p id="osInfo2"></p>
</body>
And I get an error Unhandled Error: '$.get('test1.csv').done' is not a function, I tried to google this error but I don't understand the answer its some kind of name problem?? From what i googled I tried to change $ for jQuery but still got the same error
The .done() was introduced in jQuery 1.5. You seem to be using jquery 1.3. So make sure that you upgrade to jQuery 1.5 if you want to use deferred objects.
If for some reason you cannot upgrade you could use the success callback of the $.get function:
$.get('test1.csv', function(data) {
var i,
lines = data.split('\n'),
line = lines[0].split(','),
oS = line.indexOf('oS'),
browName = line.indexOf('browName'),
browVer = line.indexOf('browVer'),
timeCanvas = line.indexOf('timeCanvas'),
timeSvg = line.indexOf('timeSvg');
for(i = 1; i < lines.length; i++) {
line = lines[i].split(',');
if(line[oS] === 'Windows') {
a++;
timeC += parseFloat(line[timeCanvas], 10);
timeS += parseFloat(line[timeSvg], 10);
}
}
});
You have used old jquery, Try using latest jquery version
The jquery version you used is too low, please use higher jquery version run your code.

Generating a random color not working

I was working on a simple project, to have the background of a webpage change every time you click on it. I succeeded in such, tested it a few times, save, tested again, and then left.
I go home and load it.. And it no longer works. I am using the same browser, I have no idea how anything could have changed.. I must have messed up a few ways almost impossible it feels like.. But alas, I'm sitting here dumb-founded..
Could anyone take a look at my simple program and tell me what is wrong? (Again, the program purpose is to change the webpage's background color to a random color whenever you click on the page.)
Here is the code:
<!DOCTYPE HTML PUBLIC>
<html>
<head>
<title>Random Colors</title>
<script language="javascript">
function randomColor() {
var h0 = Math.floor(Math.random()*99);
var h1 = Math.floor(Math.random()*99);
var h2 = Math.floor(Math.random()*99);
var h3 = Math.floor(Math.random()*99);
var h4 = Math.floor(Math.random()*99);
var h5 = Math.floor(Math.random()*99);
return '#'.toString(16)+h0.toString(16)+h1.toString(16)+h2.toString(16);+h3.toString(16)+h4.toString(16)+h5.toString(16);
}
</script>
</head>
<body onclick="document.bgColor=randomColor();">
</body>
</html>
Thanks in advance if anyone can help.
Having '#'.toString(16) makes no sense, the string '#' can't be converted to a string in hexadecimal form...
You have an extra semicolon after h2.toString(16).
return '#'+h0.toString(16)+h1.toString(16)+h2.toString(16)+h3.toString(16)+h4.toString(16)+h5.toString(16);
I think that you want to keep each digit in the range 0-15 instead of 0-98:
var h0 = Math.floor(Math.random()*16);
Try this out. Built off of what #Guffa did
function randomColor() {
var h0 = Math.floor(Math.random()*16);
var h1 = Math.floor(Math.random()*16);
var h2 = Math.floor(Math.random()*16);
var h3 = Math.floor(Math.random()*16);
var h4 = Math.floor(Math.random()*16);
var h5 = Math.floor(Math.random()*16);
return '#' + h0.toString(16) + h1.toString(16) + h2.toString(16) + h3.toString(16) + h4.toString(16) + h5.toString(16);
}
Here's the fiddle --> http://jsfiddle.net/Jh5ms/1/
Is there a reason you're using Math.random so many times?
function pad6(s) {
s = '' + s;
return '000000'.slice(s.length) + s;
}
function randomColor() {
var rand = Math.floor(Math.random() * 0x1000000);
return '#' + pad6(rand.toString(16)).toUpperCase();
}
randomColor(); // "#7EE83D"
randomColor(); // "#19E771"
As pointed out by Guffa, your first error was attempting to convert '#' to a hexadecimal representation.
This should do the trick:
function randomColor() {
var ret = Math.floor(Math.random() * (0xFFFFFF + 1)).toString(16);
return ('#' + new Array((6 - ret.length) + 1).join('0') + ret);
}
window.onload = function() {
document.querySelector('button').onclick = function() {
document.querySelector('body').style.backgroundColor = randomColor();
};
};
Here is a demonstration.
Here is another demonstration showing how you could implement it into your current page. I also took the liberty of changing your event handler to be unobtrusive.
Adding to Guffa fixing the Math.random()*99 problem, I would put all this in a loop like this:
var theColor = "#";
for (var i = 0; i < 6; i++) {
theColor += Math.floor(Math.random() * 16).toString(16);
}
return theColor;
Here's a jsFiddle
another answer in your format - pass this to whatever you want to change backgroundcolor
http://jsfiddle.net/FpLKW/2/
<div onclick="test(this);">
</div>
function test (ele) {
var h0 = Math.floor(Math.random()*10);
var h1 = Math.floor(Math.random()*10);
var h2 = Math.floor(Math.random()*10);
var h3 = Math.floor(Math.random()*10);
var h4 = Math.floor(Math.random()*10);
var h5 = Math.floor(Math.random()*10);
var x = '#' + h0.toString(16) + h1.toString(16) + h2.toString(16) + h3.toString(16) + h4.toString(16) + h5.toString(16);
ele.style.backgroundColor=x;
}

Looking for thoughts on improvement of my javascript (jquery) code. Recursive function

I have made this code that makes some visual "tiles" that fades in and out.
But at the moment I'm having a little performance problem.
Though most browers are running the code okay (especially firefox), some like safari have problems after a while (a while = like 15 seconds).
I think its due to my recursive function (the function named changeopacity that calls itself forever on a delay)? or is it?
But anyways the problem is that this code is really heavy for most browsers. Is there, or more how can I make this code perform any better? any thoughts? (code examples would be nice) thanks :-)
The actual code:
$(document).ready(function () {
var aniduration = 2000;
var tilesize = 40;
createtable(tilesize);
$(".tile").each(function (index, domEle) {
var randomdelay = Math.floor(Math.random() * 3000);
setTimeout(function () {
changeopacity(aniduration, domEle);
}, randomdelay);
});
$("td").click(function () {
clickanimation(this, 9);
});
$("td").mouseenter(function () {
var element = $(this).find("div");
$(element).clearQueue().stop();
$(element).animate({opacity: "0.6"}, 800);
});
$("td").css("width", tilesize + "px").css("height", tilesize + "px");
});
function createtable(tilesize) {
var winwidth = $(window).width();
var winheight = $(window).height();
var horztiles = winwidth / tilesize;
var verttiles = winheight / tilesize;
for (var y = 0; y < verttiles; y++)
{
var id = "y" + y;
$("#tbl").append("<tr id='" + id + "'></tr>");
for (var x = 0; x < horztiles; x++)
{
$("#" + id).append("<td><div class='tile' style='opacity: 0; width: " + tilesize + "px; height: " + tilesize + "px;'></div></td>");
}
}
}
function changeopacity(duration, element){
var randomnum = Math.floor(Math.random() * 13);
var randomopacity = Math.floor(Math.random() * 7);
var randomdelay = Math.floor(Math.random() * 1000);
if ($(element).css("opacity") < 0.3)
{
if (randomnum != 4)
{
if ($(element).css("opacity") != 0)
animation(element, 0, duration, randomdelay);
}
else
{
animation(element, randomopacity, duration, randomdelay);
}
}
else
{
animation(element, randomopacity, duration, randomdelay);
}
setTimeout(function () {
return changeopacity(duration, element);
}, duration + randomdelay);
}
function animation(element, randomopacity, duration, randomdelay){
$(element).clearQueue().stop().delay(randomdelay).animate({opacity: "0." + randomopacity}, duration);
}
function clickanimation(column, opacitylevel) {
var element = $(column).find("div");
$(element).clearQueue().stop();
$(element).animate({"background-color": "white"}, 200);
$(element).animate({opacity: "0." + opacitylevel}, 200);
$(element).delay(200).animate({opacity: "0.0"}, 500);
//$(element).delay(600).animate({"background-color": "black"}, 500);
}
The number one issue is that you are creating one setTimeout for every single cell on your page. The only browser capable of handling that is Internet Explorer, and then it fails due to the many CSS changes causing slow redraws.
I would strongly suggest programming your own event scheduler. Something like this, which I used in a university project:
var timer = {
length: 0,
stack: {},
timer: null,
id: 0,
add: function(f,d) {
timer.id++;
timer.stack[timer.id] = {f: f, d: d, r: 0};
timer.length++;
if( timer.timer == null) timer.timer = setInterval(timer.run,50);
return timer.id;
},
addInterval: function(f,d) {
timer.id++;
timer.stack[timer.id] = {f: f, d: d, r: d};
timer.length++;
if( timer.timer == null) timer.timer = setInterval(timer.run,50);
return timer.id;
},
remove: function(id) {
if( id && timer.stack[id]) {
delete timer.stack[id];
timer.length--;
if( timer.length == 0) {
clearInterval(timer.timer);
timer.timer = null;
}
}
},
run: function() {
var x;
for( x in timer.stack) {
if( !timer.stack.hasOwnProperty(x)) continue;
timer.stack[x].d -= 50;
if( timer.stack[x].d <= 0) {
timer.stack[x].f();
if( timer.stack[x]) {
if( timer.stack[x].r == 0)
timer.remove(x);
else
timer.stack[x].d = timer.stack[x].r;
}
}
}
}
};
Then, instead of using setTimeout, call timer.add with the same arguments. Similarly, instead of setInterval you can call timer.addInterval.
This will allow you to have as many timers as you like, and they will all run off a single setInterval, causing much less issues for the browser.
Nice animation :-) However, I found some bugs and possible improvements:
Your table is not rebuilt on window resizes. Not sure if bug or feature :-)
Use delegated events. You have a lot of elements, and every event handler is costly. Sadly, this won't work for the non-bubbling mouseenter event.
It would be nice if you would not use inline styles for with and height - those don't change. For the divs, they are superflouos anyway.
I can't see a reason for all those elements to have ids. The html-string building might be more concise.
Cache the elements!!! You are using the jQuery constructor on nearly every variable, building a new instance. Just reuse them!
Your changeopacity function looks a bit odd. If the opacity is lower than 0.3, there is 1-in-13-chance to animate to zero? That might be expressed more stringent. You also might cache the opacity to a variable instead of reading it from the dom each time.
There is no reason to pass the duration and other constants as arguments, they do never change and can be used from the global scope.
Instead of using the timeout, you should use the complete callback of the animate method. Timeouts are never accurate, they may even interfere here causing (minor) problems.
var duration = 2000,
tilesize = 40,
clickopacity = 0.9;
$(document).ready(function () {
filltable($("#tbl"), tilesize)
.on("click", "td", clickanimation);
$(".tile").each(function() {
changeopacity($(this));
});
$("#tbl div").mouseenter(function () {
$(this).clearQueue()
.stop()
.animate({opacity: "0.6"}, 800);
});
});
function filltable(tbl, tilesize) {
var win = $(window).width();
var horztiles = win.width() / tilesize;
var verttiles = win.height() / tilesize;
for (var y = 0; y < verttiles; y++) {
var tr = "<tr>";
for (var x = 0; x < horztiles; x++)
tr += "<td style='width:"+tilesize+"px;height:"+tilesize+"px;'><div class='tile' style='opacity:0;'></div></td>");
tbl.append(tr+"</tr>");
}
return tbl;
}
function changeopacity(element) {
var random = Math.floor(Math.random() * 13);
var opacity = Math.floor(Math.random() * 7);
var delay = Math.floor(Math.random() * 1000);
if (element.css("opacity") < 0.3 && random != 4)
opacity = 0;
element.clearQueue().stop().delay(delay).animate({
opacity: "0." + opacity
}, duration, function() {
changeopacity(element);
});
}
function clickanimation() {
$(this.firstChild)
.clearQueue()
.stop()
.animate({"background-color": "white"}, 200)
.animate({opacity: "0." + clickopacity}, 200)
.delay(200).animate({opacity: "0.0"}, 500);
//.delay(600)
//.animate({"background-color": "black"}, 500);
}

changing background image with a for loop

i have a table with 3 cells the middel 1 in a black image so it will look like there is a line in the middle of the screen.
now in the other cell i want to show pictures, so i tryed to do a loop that changing the images every second with by hiding the cells and then show them.
the script:
$(window).ready(function () {
//the images sits in a div with a hidden property.
var AlumniumPictures = $("#AlumnimPictureHolder").children();
var ShipozimPictures = $("#ShipozimPictureHolder").children();
//var timer = $.timer(yourfunction, 10000);
for (var i = 0; i < 10; i++) {
$(".almoniyomButtonTD").css({
"background-image": "url(" + $(AlumniumPictures[i]).attr('src') + ")"
});
$(".shipozimButtonTD").css({
"background-image": "url(" + $(ShipozimPictures[i]).attr('src') + ")"
});
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
//for some reson the code dosnt work if im not using the setInterval method.
document.setInterval(1000);
}
});
this is not working it only show me the first images and then stop.
is there a batter way to do this?
am im doing this right?
I think you might do this for the background:
$(window).ready(function () {
//the images sits in a div with a hidden property.
var AlumniumPictures = $("#AlumnimPictureHolder").children();
var ShipozimPictures = $("#ShipozimPictureHolder").children();
//var timer = $.timer(yourfunction, 10000);
time = 0;
step = 1000; // One secund
for (var i = 0; i < 10; i++) {
time+= step;
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
//for some reson the code dosnt work if im not using the setInterval method.
document.setInterval("changeBG('" + $(AlumniumPictures[i]).attr('src') + "', '.almoniyomButtonTD')", time);
document.setInterval("changeBG('" + $(AlumniumPictures[i]).attr('src') + "', '.shipozimButtonTD')", time);
}
});
function changeBG(image, obj) {
$(obj).css({
"background-image": "url(" + image + ")"
});
}
But I don't undestand what you want to do with this:
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
See the docs about setInterval. You need to tell it what code you are running.
window.setInterval(code, delay);
You aren't specifying any code for it to run! Try placing your for statement in a function and calling that.
Also, from Mozilla and MS docs setInterval seems to be on the window object, not on the document object. I don't think it will work the way you have it. I imagine if you looked in a debugger you would see an error thrown.
window.setInterval(myFunction, 1000);
function myFunction() {
for (var i = 0; i < 10; i++) {
$(".almoniyomButtonTD").css({
"background-image": "url(" + $(AlumniumPictures[i]).attr('src') + ")"
});
$(".shipozimButtonTD").css({
"background-image": "url(" + $(ShipozimPictures[i]).attr('src') + ")"
});
$(".almoniyomButtonTD").hide();
$(".shipozimButtonTD").hide();
$(".almoniyomButtonTD").show(1100);
$(".shipozimButtonTD").show(1100);
}
}

Categories