Compare getValue with map.layers[i].name - extjs

As part of a xtype combo, I would like to know if the layer I choose in my simple data store (represented by this.getValue()) is present in the map layers. So if it does, A should occur, and B if it does not. The problem is that myLayer variable seems to be unrecognized, even though Opera Dragonify throws no error at all. Where would be the error?
listeners: {
'select': function(combo, record) {
for(var i = 0; i < mapPanel.map.length; i++) {
var myLayer = mapPanel.map.layers[i].name;
if (myLayer == this.getValue()) {
// do A here...
} else {
// do B here...
}
}
}
}
Thanks for any pointers,

I think the problem is that you are using this.getValue() instead of using combo.getValue().
I don't know how your app is set but it's usually a better idea to use the first parameter of your listener instead of the keywork this in order to avoid scope issues.
Hope this helps

#Guilherme Lopes Thanks for that, but the solution was this: mapPanel.map.layers.length instead of mapPanel.map.length.

Related

modifying object in componentDidMount() [duplicate]

I’ll start with the code:
var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);
Simple, right? In response to this, the Firefox console says:
[ "hi" ]
[ "bye" ]
Wonderful, but Chrome’s JavaScript console (7.0.517.41 beta) says:
[ "bye" ]
[ "bye" ]
Have I done something wrong, or is Chrome’s JavaScript console being exceptionally lazy about evaluating my array?
Thanks for the comment, tec. I was able to find an existing unconfirmed Webkit bug that explains this issue: https://bugs.webkit.org/show_bug.cgi?id=35801 (EDIT: now fixed!)
There appears to be some debate regarding just how much of a bug it is and whether it's fixable. It does seem like bad behavior to me. It was especially troubling to me because, in Chrome at least, it occurs when the code resides in scripts that are executed immediately (before the page is loaded), even when the console is open, whenever the page is refreshed. Calling console.log when the console is not yet active only results in a reference to the object being queued, not the output the console will contain. Therefore, the array (or any object), will not be evaluated until the console is ready. It really is a case of lazy evaluation.
However, there is a simple way to avoid this in your code:
var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());
By calling toString, you create a representation in memory that will not be altered by following statements, which the console will read when it is ready. The console output is slightly different from passing the object directly, but it seems acceptable:
hi
bye
From Eric's explanation, it is due to console.log() being queued up, and it prints a later value of the array (or object).
There can be 5 solutions:
1. arr.toString() // not well for [1,[2,3]] as it shows 1,2,3
2. arr.join() // same as above
3. arr.slice(0) // a new array is created, but if arr is [1, 2, arr2, 3]
// and arr2 changes, then later value might be shown
4. arr.concat() // a new array is created, but same issue as slice(0)
5. JSON.stringify(arr) // works well as it takes a snapshot of the whole array
// or object, and the format shows the exact structure
You can clone an array with Array#slice:
console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct
A function that you can use instead of console.log that doesn't have this problem is as follows:
console.logShallowCopy = function () {
function slicedIfArray(arg) {
return Array.isArray(arg) ? arg.slice() : arg;
}
var argsSnapshot = Array.prototype.map.call(arguments, slicedIfArray);
return console.log.apply(console, argsSnapshot);
};
For the case of objects, unfortunately, the best method appears to be to debug first with a non-WebKit browser, or to write a complicated function to clone. If you are only working with simple objects, where order of keys doesn't matter and there are no functions, you could always do:
console.logSanitizedCopy = function () {
var args = Array.prototype.slice.call(arguments);
var sanitizedArgs = JSON.parse(JSON.stringify(args));
return console.log.apply(console, sanitizedArgs);
};
All of these methods are obviously very slow, so even more so than with normal console.logs, you have to strip them off after you're done debugging.
This has been patched in Webkit, however when using the React framework this happens for me in some circumstances, if you have such problems just use as others suggest:
console.log(JSON.stringify(the_array));
Looks like Chrome is replacing in its "pre compile" phase any instance of "s" with pointer to the actual array.
One way around is by cloning the array, logging fresh copy instead:
var s = ["hi"];
console.log(CloneArray(s));
s[0] = "bye";
console.log(CloneArray(s));
function CloneArray(array)
{
var clone = new Array();
for (var i = 0; i < array.length; i++)
clone[clone.length] = array[i];
return clone;
}
the shortest solution so far is to use array or object spread syntax to get a clone of values to be preserved as in time of logging, ie:
console.log({...myObject});
console.log([...myArray]);
however be warned as it does a shallow copy, so any deep nested non-primitive values will not be cloned and thus shown in their modified state in the console
This is already answered, but I'll drop my answer anyway. I implemented a simple console wrapper which doesn't suffer from this issue. Requires jQuery.
It implements only log, warn and error methods, you will have to add some more in order for it to be interchangeable with a regular console.
var fixedConsole;
(function($) {
var _freezeOne = function(arg) {
if (typeof arg === 'object') {
return $.extend(true, {}, arg);
} else {
return arg;
}
};
var _freezeAll = function(args) {
var frozen = [];
for (var i=0; i<args.length; i++) {
frozen.push(_freezeOne(args[i]));
}
return frozen;
};
fixedConsole = {
log: function() { console.log.apply(console, _freezeAll(arguments)); },
warn: function() { console.warn.apply(console, _freezeAll(arguments)); },
error: function() { console.error.apply(console, _freezeAll(arguments)); }
};
})(jQuery);

Using arrays and hitTest - AS3

From what my friend has told me, this should be working but it is not.
var P2hb:Array = new Array(P2char1, P2char2, P2char3);
var P2life:Number = 0;
addEventListener(Event.ENTER_FRAME, framecheck)
function framecheck(event:Event):void
{
if (P2hb.hitTestObject(P1attack)) { P2life-=2; }
}
This is a generic code but it is the same as what I have. Basically,
all elements in the P2hb are movieclips on the stage.
I want to say that, if P1attack hits any of the objects in the array, then P2life will drop by 2, without having to type hitTestObject() for each individual object.
I can't seem to get it to work. Can anyone tell me what I am doing wrong?
Thank you in advance.
Simply, loop through each individual "movieClip" in the array (using a for loop, for example) and check for the collision against your other object:
function framecheck(event:Event):void
{
for each (var enemy in P2hb) {
if (enemy.hitTestObject(P1attack)) {
P2life-=2;
trace("hit occurred! P2life: "+P2life);
}
}
}

valid object property in javascript

how can i check if any javaScript object's property exists and if it exists then it has a valid value?
actually,i am a beginner and trying to solve this-
Check if the second argument is truthy on all objects of the first argument(which is an array of objects).i.e.
check if the second argument exists in all the objects in first argument(an array) as a property.
if it exists, it should not be-
invalid, as age can't be 0
null
undefined
empty string('')
NaN
till now i have this-
function truthCheck(collection, pre) {
for(var i=0;i<collection.length;i++){
if(!(pre in collection[i])||collection[i]
[pre]===undefined||isNaN(collection[i]
[pre])||collection[i][pre]===""||
collection[i][pre]===null||collection[i]
[pre]===0)
{
return false;
}
}
return true;
}
i know this is not the best wayto solve .Is there a better way to do this?i don't like that long if statement in my code.i have seen other SO links-link1,link2 but none of them seemed to solve my query. any kind of help is highly appreciated.
P.S. this code is not working for some true cases even.
o = new Object();
o.prop = 'exist';
if(o.hasOwnProperty('prop')){
if(o['prop']){
alert('good value')
}
}
https://stackoverflow.com/a/6003920/1074179
this is what i was looking for and absolutely logical-
for(var i in array){
if((prop in array[i])&& Boolean(array[i][prop]))
{
//do something
}
}
the Boolean() function is something which made my day. Learn more at this link.
Look at the below example.
let the json object be
var a = { obj1:"a",obj2:"b"}
to check if an object exists,you can use hasOwnProperty() method.
a.hasOwnProperty("obj2") //this will return true
a.hasOwnProperty("obj3") // this will return false
to check the value of an object
if(a["obj1"] && a["obj1"]!="" && a["obj"]!=0){
//place your logic here
}

Variable array/object in one file changes when you change it in a callback in another file

I have two files in Node.js where one requires the other one.
variable_test.js:
TEST = require('./variable_test_external.js');
TEST.get(function(myVariable) {
var changeMeVariable;
console.log(myVariable);
changeMeVariable = myVariable.epicVariable;
changeMeVariable.evenEpicerVariable = "test3";
TEST.get(function(myVariable2) {
console.log(myVariable2);
});
});
variable_test_external.js:
var testVariable = new Array({epicVariable: {evenEpicerVariable: "test1"}}, {epicVariable: {evenEpicerVariable: "test2"}});
exports.get = function(callback) {
callback(testVariable[1]); // I know that the return is unnecessary in this example but in my real application I have return there for compactness.
}
This is the output when run in Node.js with node variable_test.js:
{ epicVariable: { evenEpicerVariable: 'test2' } }
{ epicVariable: { evenEpicerVariable: 'test3' } }
The console.log(myVariable) changes in the two TEST.get's. Why does this happen?
This is a reference copy, not a value copy. You got the object from the array, NOT a copy of them.
changeMeVariable = myVariable.epicVariable;
This would have to fix yout problem
// PSEUDO CODE, i don't know the correct syntax
changeMeVariable = {
epicVariable = myVariable.epicVariable
};
The answer in my case is the following based on the links at the bottom:
changeMeVariable = JSON.parse(JSON.stringify(myVariable.epicVariable));
But, it's much better to manually copy it like the bottom most link like this:
changeMeVariable = {
evenEpicerVariable: myVariable.epicVariable.evenEpicerVariable
}
n0m's answer is similar but if the epicVariable.evenEpicerVariable contained an object that object's reference would still be linked! (I tested it)
References:
What is the most efficient way to deep clone an object in JavaScript?
http://jsperf.com/cloning-an-object/3

AS3: Creating and accessing movieclips from an array

I know there are quite similar questions here, but I haven't found the proper details. What would be helpful is definitely an explanation of the problems, and perhaps a base example, that anyone who searches later may be able to apply. (Not asking that you write it for me, I just find the examples helpful) I don't want to upset anyone and am kind of worried to post in a forum...
I am wondering alternatives to creating a screen based off tiles created from an array. I have been having an issue myself trying to access the movieclips that have been placed on screen, and trying to trace to find a way to reference them hasn't been working.
Anyway, take something basic like an array, and connecting it to movieclips, then how to access the movieclip itself once done. So I have been working on this, and used many different online resources, so I'm sure a lot of this is going to look familiar, just in a much messier way.
This takes the array to make the movieclips appear (Im sure at least one part in here is unnecessary, and I'm thinking I'm doing something wrong here that makes it not work out later) So this works, but feels pretty bulky.
Both are from the same main class file.
function makeWorld (anyMap, tileW, tileH) {
var worldWidth = anyMap[0].length;
var worldHeight = anyMap.length;
var MAP = this.addChild(new mapHolder());
function tiler(MAP, i, j, tileW, tileH, tile)
{
MAP.addChild(tile);
tile.x = (j * tileW);
tile.y = (i * tileH);
}
for (var i = 0; i < worldWidth; ++i) {
for (var j = 0; j < worldHeight; ++j) {
var curTile:int = anyMap[i][j];
if (curTile == 101) {
var tile1 = new tileGround();
tiler (MAP, i, j, tileW, tileH, tile1);
...
else {
var tile3 = new empty();
tiler (MAP, i, j, tileW, tileH, tile3);
}
}}}
Then there is attempting to reference it, where I'm having the issue. I don't know what to call this.MAP.tileGround by, and I have tried many things. I've read it's not such a good idea to reference by name when not very advanced so I wanted to avoid that sort of thing too.
addEventListener (Event.ENTER_FRAME, hits);
function hits (event:Event) {
var tileCatchG:MovieClip = this.MAP.tileGround;
if(tileCatchG.hitTestPoint(this.MAP.Char.x + leftBumpPoint.x, this.MAP.Char.y + leftBumpPoint.y, true)){
leftBumping = true;
} else {
leftBumping = false;
}
...
}
Thank you!
In looking over what you're doing a second time it would appear that you should have a reference to the 2-indexed array that represents the map.
You can create a regular (single indexed) Array at the top of the file like
public var tileArray:Array = [];
Then where you create them push them into the array
var tile1 = new tileGround();
tileArray.push(tile1);
then to reference them all you can just run a simple loop
for each(var tile:MovieClip in tileArray)
{
//Do stuff
if(tile instanceof tileGround)
{
//Do stuff specific to tileGround
}
}

Resources