How do I compare Application.windows[x] to Application.activeWindow? - javascript

I'm creating a Firefox extension, in which I want to iterate through the Application.windows array and check if one of its elements is the same as Application.activeWindow.
The mentioned excerpt from my code looks like this:
for (var i in Application.windows) {
if (Application.windows[i]==Application.activeWindow) alert('debug');
// there was some more complex code than alert('debug'),
// but since it didn't work, I decided to try with an alert
}
Unfortunately, the 'debug' alert is never viewed. Thus I decided to try this code (with only one window opened):
// the following code runs in an event listener for window.onload
alert(Application.windows[0]);
alert(Application.activeWindow);
alert(Application.windows[0]==Application.activeWindow);
Firefox displayed 3 alerts: the first one was [object Object], the second one - [xpconnect wrapped fuelIWindow], and the last one (which didn't surprise me) said false. So it seems the objects I'm trying to compare have different types. How can I deal with this? Thanks in advance.

You have two problems.
The first is that XPConnect doesn't support array-valued properties, so when FUEL (or STEEL or SMILE) return an array, they're actually returning an nsIVariant of internal objects! On the other hand, single-valued objects return an XPConnect wrapper which hides the internal object.
The second is that each time you access windows or activeWindow, new internal objects are created, so even two calls to activeWindow return different objects.
The way around this is to avoid FUEL and enumerate the windows directly using the window mediator.

Related

No array operations work on getLangs() from ngx-translate/core TranslateService

I work on an Angular (v13) project which uses ngx-translate/core for i18n. There are multiple languages (15 currently) configured. I find the following very strange behaviour (TranslateService is injected as this.translateService):
Calling this.translateService.getLangs() returns an array with the 15 language codes as expected. I can log this value or e.g. configure a dropdown select with these values.
However, I can do absolutely no array operations on this value, including indexing [0] (says undefined), .length (returns 0), or for-in or for-of. No ... operator to create a new array or object with the values, no Object.assign([], langs), no Array.from() - they just return empty arrays. Let alone .map(), .forEach(), etc.
typeof says object, Array.isArray() says true.
Some basic example code:
ngOnInit(): void {
console.log(
this.translateService.getLangs(),
this.translateService.getLangs().length,
this.translateService.getLangs()[0],
this.translateService.getLangs().includes('en'),
this.translateService.getLangs().includes('aa')
);
}
shows in the console:
[] 0 undefined false false
and if I expand the [] it shows the 15 codes (including 'en'), and length: 15.
Questions
Am I reading the ngx-translate documentation wrong (that what is there)?
Am I using it wrong somehow due to not understanding something?
Is this a bug in ngx-translate?
Is this a bug in JavaScript?
Is there any workaround?
Thank you to Amer for his comment pointing me in the right direction.
The problem occurs because this.translateService.getLangs() is called before languages have been loaded via this.translateService.addLangs(). The language values are obtained via a HttpClient.get() request, which returns an Observable and calls addLangs() once the results are received (refer Observable.subscribe(...)). (So no funny happenings, just a wrong understanding.)
The simple solution is to only do any operations on the array of languages in the complete callback of the Observable returned by HttpClient.get() (or use one of the other synchronization mechanisms available). This was a bug in the original code and has now been fixed.
The browser (Chrome) logging [] (which could then be expanded to the full array) was a confusion on my part. When the array is available at logging time, it is logged as expanded, e.g. [ "ar", "en", .... ]. (By the time I clicked on the expansion widget in the console, the array had obviously been loaded in the mean time, which enables it to be shown on expansion.)
I strongly advise against synchronization via timeouts as someone may wrongly read from Amer's comment, where it is suggested only for problem detection. One should always use one of the synchronization methods (Promises, Observables, events, etc. etc.) in final code to synchronize between asynchronous processes.

How to get count object in javascript? [duplicate]

I have an array filled with objects. It contains 23 items in total, however when I perform a .length on it, it returns 20.
// Get the new routes
var array = PostStore.getPostList();
console.log(array.objects);
console.log(array.objects.length);
Image of what my console returns:
What's going wrong here?
The problem is probably that the array changed between the time you logged it and the time you opened it in the console.
To get the array at the logging time, clone it:
console.log(array.objects.slice());
console.log(array.objects.length);
Note that this won't protect against the array element properties changing. If you want to freeze them too, you need a deep cloning, which is most often possible with
console.log(JSON.parse(JSON.stringify(array.objects.slice()));
This won't work if the objects aren't stringifyable, though (cyclic objects, very deep objects, properties throwing exceptions at reading, etc.). In that case you'll need a specific cloning, like my own JSON.prune.log.
A alternative to logging is also, in such a case, to debug. Set a breakpoint and look at the objects while the code is stopped.

JavaScript items disappearing from Array

I have an array called objs that holds all of my application objects. Objects get added and removed from this list depending upon what happens in the application.
I am having this problem where some objects disappear (or are overwritten) only sometimes. If I step through the add and remove functions, the app always runs as it should, however many times when it is run without the debugger, one or two objects that were added to the end of the list disappear from the list.
objects are added to the array like this:
this.objs[this.objs.length]=obj;
and are removed from the array like this:
for(var i=0;i<this.objs.length;i++)
if(this.objs[i]==obj)
return this.objs.splice(i,1);
I put this code at the end of my add and remove functions:
console.log("add! ");
console.log(this.objs);
Linked is an image of a console log during a session where an object dissapeared: http://ilujin.com/error.png
The first 4 objects in the list shown at the top should remain in the list throughout the session, but the object at index 3 (highlighted in red), gets overwritten by the next object that gets added (highlighted in blue).
The other weird thing is that the second list shown already has all of the changes (4 objects removed and 1 added), even though the remove function has only been called once and the add function not at all.
This makes me conclude that the problem is timing - if one add hasn't finished before the next add is called, the first one will be overwritten. And all of the console prints are the same because they all happen before the console can read and print.
Does this makes sense? For some reason I thought JS never ran parallel code and only moved on to a new function when the last function finished. Is the problem that I'm using the length of the objs list as the new index when I add to the list?
How can I fix this issue? I can't figure it out, and the debugger and console have proven useless.
Here is the app: http://iioengine.com/neuro/study2.htm
you only need to enter an id and see if the instructions pop up. If they do, than its working and refresh. If they don't, that means that the Text Object got overwritten.
You would really be better served by using Javascript's array methods.
Add to array:
this.objs.push(obj);
Remove from array:
this.objs.splice(this.objs.indexOf(obj), 1);
Also, note that splice edits the original array and returns the elements that have been removed. It's hard to tell from your limited code sample, but that might also be causing issues.

how to print a javascript object with nested properties using developer tools without the nested properties pointing to the wrong references

Example:
var o = {
a: 12,
gg: {
mm: {
a: 15
}
}
}
console.log(o, _.copy(o))
o.gg.mm.a = 44
in this case, in the developer tools, it would print "o" twice and the value of o.gg.mm.a would be different
In the first one, the value is 44
In the second one, the value is 15 -- thanks to the jquery copy function or underscore clone function
When printing Backbone models which are much more complex, it is constantly printing the object pointing to the wrong reference i.e 44 instead of 15 (regardless if clone/copy is used)
There are several options to display these properties (even with Backbone models) but they are all terrible:
use a wrapper with known limitations i.e clone/copy/extend to handle nested properties
copy/clone/extend specific properties to get to the nested objects i.e console.log(_.copy(o.gg.mm))
using console.log on the values directly i.e console.log(o.gg.mm.a) to get the right value
launch the debugger and inspect the values
Is there something simpler? I want to view the object and its properties without the console.log deceiving me with a misread
Unfortunately the console is lazily evaluated – that is to say that values for the object's properties are only fetched after you click to view the object.
If you're using Chrome you might want to consider setting a breakpoint which will halt code execution so you can view the object before it's modified.
More info on breakpoints can be found here: https://developers.google.com/chrome-developer-tools/docs/scripts-breakpoints

How come setting value in one array key is setting in another key?

I have an array of objects with various objects within to hold UI values. I wanted to have a button so that element 0's values are replicated through the whole array. However I noticed that setting one set them all. Here is an example without using any looping:
console.log('manual 3: ', lis[3].spacer.divider.type); // prints 'none'
lis[1].spacer.divider.type = 'bananas';
console.log('manual 3: ', lis[3].spacer.divider.type); // prints 'bananas'
I am completely baffled how setting lis[1] also set lis[3]
They must both be references to the same object.
If they're DOM nodes, you can copy them using cloneNode().
Watch out for IE bugs - it has a habit of not cloning properly (for example cloning a <select> doesn't maintain the selectedIndex).
See also What is the most efficent way to clone a JavaScript object? for cloning objects.
Because the variables are reference variables and they all reference the same object and as a result it looks like changing one changes all of them, really they are all the same underlying object.
If you want lots of unique arrays they should all be created as a fresh or be clones of each other.
It turns out I was referencing the same object. Thanks. It didn't click to me since all the other objects above (spacer,lis) were unique. I accidentally was setting divider to a member default of spacer instead of a function returning the default.
Thanks!

Categories

Resources