Accessing array element of NPAPI plugin from Javascript - javascript

I created a NPAPI plugin and wants to access an array element in the plugin from Javascript. The javascript I used is the following one:
var foo_plug = document.getElementById('foo');
var elem = foo_plug.array_p[index];
What all methods in NPClass gets invoked for accessing an array element for the code shown above ?
How will I return the value at index of the array for an NPAPI
plugin ?
How does the array index gets conveyed from Javascript to the NPAPI
plugin ?
PS:I got the hasProperty and getProperty methods of NPClass invoked when accessing a variable in a plugin and is working fine.

The first thing you need to understand is the calling chain. Let's look at the line in question:
var elem = foo_plug.array_p[index];
What this is going to do is first call NPN_GetProperty on the NPObject for foo_plug with an NPIdentifier that translates to the string "array_p".
What happens next depends on what is returned; if you return a string, index will be the index into that string. if it's an int, it'll give you an error. If, on the other hand, it's an NPObject, the next call will be NPN_GetProperty on that NPObject with an NPIdentifier that will either be an IntIdentifier (use NPN_GetIntIdentifier) or a string identifier with the number as a string (use NPN_IdentifierIsString to determine which).
Now, if the NPObject returned is an actual javascript array, you don't have to worry about that; you can get the NPObject for window and call Invoke on it with the identifier "Array" and no arguments and it will return an NPObject with an empty array; you can work with it to put things in it and return it and that will work fine.
Alternately, you can return an NPObject that supports the "length" property, NPN_Enumerate, and can intelligently handle either a numeric string identifier or an intidentifier (actually you need to handle both because some browsers use each type) and if it acts enough like a javascript array you probably won't know the difference.
FireBreath has excellent support for all of these options.

Related

How do I access the 'str' value in my object?

I am trying to return the value under the key 'str' in an Object but I am having trouble accessing the value.
This is what is returned in the console:
Currently I am using a map function to go over the array and just return the _str value like so:
let idx = currentArray.map(function(x) {
return x._id._str;
});
However it is still returning the value as an object. How can I get just the value of the _str key?
Here is the full array without specifying the id field. This is what is returned if you jsut return 'x' in the map function.
You've clarified that the screenshot is of x._id. So to access _str, you'd use x._id[0]._str: The _str property is in the object referenced by the 0 property (the first entry in the array x._id refers to).
Note that in general, _-prefixed properties are meant not to be accessed by code outside the code responsible for the objects in question. You don't seem to be responsible for them, so accessing those properties is likely to make your code rely on undocumented properties that may change in the next "dot" release of whatever lib you're using. It's just convention, but it's a very common convention.
If you right click on the property, most browser consoles offer the ability to copy property path.
Based on this SO post and the docs, it appears that you can probably use x._id.str.
If I understand correctly, you are receiving the str value but it is an object instead of the string literal. In other words, you are getting _str: "598..." instead of "598....". A possible solution would be to use the mongo javascript function to convert the str value to a string.
In your case, I think something like return x._id.str; may work as _id is a MongoID.ObjectID.
I've also linked the documentation below for reference.
https://docs.mongodb.com/manual/reference/method/ObjectId/
Here's a relevant SO answer as well: Convert ObjectID (Mongodb) to String in JavaScript
I think you should write x[_id]._str because _id is one of the array objects.

Property is faster than method? Need reason for it

As I google this question so one person give answer that property is faster than method and give one example of size() and length.
He said length is faster than size because length is property. Can you please let me know is it correct ? Or If you will give example then it will be great for me.
size internally calls the length
//http://code.jquery.com/jquery-latest.js
// The number of elements contained in the matched element set
size: function() {
return this.length;
},
So if you are using length then you are avoiding one extra method call. The Jquery docs says:
The .size() method is functionally equivalent to the .length property;
however, the .length property is preferred because it does not have
the overhead of a function call.
I am assuming that you want to get the length of a String or the number of elements in an Array.
size() is not a method of the Array or String objects. Thus if it exists some library or you yourself have added this method to the respective prototypes. length on the other hand is a default property and (should) exist in any JS runtime.
Unless you cannot use length, the size function will just add unneeded overhead and I would go for the property.
Check the following to links:
https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/prototype
If you will read length property then only time required to access an object property will be needed.
However if you will call size() then first of all a function will be called, this function will read length property internally and then return that value to the caller.
You can clearly see that you are doing the same thing in both cases. But if you call the function then it will include time for calling a function + returning that value too..
Length returns the same thing and is slightly faster according to the jQuery documentation.
Source: http://api.jquery.com/size/

what is prevObject and context in pushstack in jquery ?

I understand how the pushstack function works and I also understand how to use it for my plugins (I guess that's what its most used for , just for internal use and for end() to function properly and other similar methods) .
now below is the jquery source of pushstack , have a look :
pushStack: function( elems ) {
// Build a new jQuery matched element set
var ret = jQuery.merge( this.constructor(), elems );
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
// Return the newly-formed element set
return ret;
},
theres a lot going on in that function really and I kind of get most part of it , but I have a small problem , understanding the below lines of code :-
ret.prevObject = this;
ret.context = this.context;
what is prevObject and context ? can somebody give me a clue , it definitely does't seem to be a javascript thing ?
Basically prevObject is used to allow flexibility for the jquery selectors chaining syntax.
Most of jQuery's DOM traversal methods operate on a jQuery object instance and produce a new one, matching a different set of DOM elements. When this happens, it is as if the new set of elements is pushed onto a stack that is maintained inside the object. Each successive filtering method pushes a new element set onto the stack
Everytime you make a new filter a new jquery instance is constructed matching your selector and the previous one is stored in it to allow the .end() and the addBack() functions to work (most of the DOM transversal functions use pushStack internally). If this property were not used every selector will forget about the previous one and it will not behave like a stack. Think parent instead of prevObject and it will make it easier to understand.
The context property is deprecated in jQuery 1.10 and only used for supporting live() method but it must be added because the returning object is constructed merging an empty jQuery constructor as first parameter and a set of elements as the second.
var ret = jQuery.merge( this.constructor(), elems );
Because .merge returns the first array modified it's context property might not have the correct value so is overwritten with the correct one this.context
Check this jsfiddle and open the console. You will see that the first value of prevObject is the document as we are making a new selector and then is the ul element since we filter using find. Moreover you can go to the last filter and lookup the whole chain of selectors up to the document again.
I recommend you to use the JQuery API instead of this property as reference in production but this will allow you for example to know the result of all the selectors that have been applied to obtain a given set of DOM elements.

Working with "Out" Parameters in JavaScript

I am working with an ActiveX control in Internet Explorer 8 that is to display a save file dialog which let's the user choose a file name and file type (jpg, gif, etc). These values get passed to code and then are used in a different method to save the file. Unfortunately the method that invokes the dialog has no return value, and the file name and file type are passed in as out parameters.
The signature of the method (expressed in Visual Basic) looks like this:
Public Sub SaveFileDialog( _
ByVal bstrDialogType As Variant, _
ByRef pbstrFileName As String, _
ByRef out_pvType As Long _
)
The two ByRef parameters are the out parameters.
I have written the following JavaScript code:
try
{
var saveFileName, saveFileType; // out variables
gxVideoPlayBack.SaveFileDialog("image", saveFileName, saveFileType);
alert(saveFileName); // displays "undefined"
alert(saveFileType); // displays "undefined"
}
catch(error)
{
if(!error.number === -2147221484) // User clicked cancel.
{
alert(error.message);
}
}
The code works in that the ActiveX control produces its dialog, and I can handle error conditions, but I can't seem to figure out how to capture the values of the out parameters.
In the code gxVideoPlayBack is a reference to the ActiveX control embedded in the DOM via an HTML element.
If JavaScript will not work for this, can it be done in VBScript?
As an alternative I can just implement my own dialog, but would rather use the one provided.
Edit: It seems that it's not possible to have "out" parameters in JavaScript/JScript.
Original:
Perhaps the approach described in this article will work:
var saveFileName={}, saveFileType={}; // Empty "output" objects.
gxVideoPlayBack.SaveFileDialog("image", saveFileName, saveFileType);
alert(saveFileName.value); // The "value" attribute is assigned ...
alert(saveFileType.value); // ... by the "SaveFileDialog" method?
I suppose the idea is that the WSH wrapper for this native call will attempt to assign the "value" property of the given output parameters, so you can either override the value setter or just give it an object with a built-in value setter.
All function arguments in JavaScript are passed by value (even if the value being passed is a reference to an object (which it is)). There is no pass-by-reference.
If SaveFileDialog modifies the objects referenced by saveFileName and saveFileType then you have access to those changes through your existing variables.
Unfortunately, out/ByRef parameters will only work in JScript for objects; not for any other type (numbers, strings).
In this case, you’ll have to use VBScript, which does support ByRef arguments, or like maerics says, write a VB/VBScript wrapper for the SaveFileDialog method, which could return an object containing both file name and type.

Is this right? A jQuery bug that erases the data store?

Fire up your firebug console and try this out.
Compare this:
$('body').data('x',1);
$(thisx).remove();
console.log($('body').data('x'));
to this:
$('body').data('x',1);
$(this.x).remove();
console.log($('body').data('x'));
Notice the difference? If thisx is undefined, it will immediatly throw a reference error. If x is an undefined property of this, jQuery will return the document as it's result set instead. Next jQuery will attempt to remove your document (which it can't), but before doing that it will remove all data attached to any child element of the document. Thus, wiping out your data store.
Note: this can be any element reference or object. You only need to have jQuery attempt to access an undefined property.
(Talk about a pain. It fails silently, and I'm trying to figure out why my data is suddenly missing. I track it down to a special case where an element reference was undefined in a specific situation.)
So on to my questions:
1) Before I submit a bug report, am I analyzing this correctly? Also if someone happens to know that this is a known issue, let me know. I couldn't find it in the bug tracker, but the interface isn't that great (or maybe I have this wrong).
2) Why is there ultimately any difference? I'm guessing thisx is evaluated immediately which causes the exception while this.x is a reference that is passed and evaluated in the called function, right? (where I think the line selector = selector || document; is the culprit.
3) Suggestions for how to handle this? I guess I should be checking that any/every element reference or property of an object (e.g. stored selector strings) is defined before I pass it to jQuery when removing something.
Why is there ultimately any difference?
Both thisx and this.x are evaluated when the function is called. The first one refers to an undefined variable name and this throws a reference error. The second one accesses an undefined property of an object, which results in the value undefined. This is just how javascript behaves in these cases.
Now when JQuery is called in the second case, the call $(this.x) evaluates to $(undefined) which is the same as if you just would have called $(). Since it looks to JQuery as if no argument was provided, it uses a default instead, and in this case the default is document. Then it proceeds trying to delete document, since it was effectively called as $().remove(), in which case this would be expected.
Suggestions for how to handle this?
The difference with the ReferenceError is a fundamental Javascript difference, not much that can be done about that. JQuerys behavior is unfortunate and a consequence of setting defaults by arg = arg||default. One could user arguments.length instead to get the real number of call parameters, but a change like this would surely result in lot's of broken code that relied on the default being used when undefined or 0 is passed, so it's unlikely to happen.
Try typing these into the console too (with no extra variables defined beforehand):
> a
ReferenceError: Can't find variable: a
> b = {}
Object
> b.a
undefined
one is a javascript error, one silently returns undefined (which jQuery will interpret as $() because javascript and jQuery can't tell the functions $() and $(undefined) apart)
this is the way javascript works, bug or feature I leave open to debate, but I don't think that this is jQuery's fault or problem.
edit: why does jQuery have $() defined?
From the docs:
By default, if no context is specified,
$() looks for DOM elements within the
context of the current HTML document.
If you do specify a context, such as a
DOM element or jQuery object, the
expression will be matched against the
contents of that context.
edit: the docs were referring to the context argument passed to $(), not to calling $() without arguments, so it isn't relevant here.
also note that
$().get(0) == $("").get(0)

Categories