What syntax I should use to declare externs for closure compiler? - google-closure-compiler

I want to declare some externs for closure compiler but not know how to do it?
(function(window) {
window.myapi = window.myapi || {};
var myapi = window.myapi;
myapi.hello = function() {
window.document.write('Hello');
}
}(window));
I am not sure how to do it for window.myapi, window.myapi.hello?

Externs are valid javascript, but they are just type information. They should not contain definitions (or for functions only empty definitions).
Here's a start: How to Write Closure-compiler Extern Files Part 1
A couple of notes on your specific example:
Don't use an anonymous wrapper. Type names must be global.
Properties on the window object are the same as the namespace examples.
Functions shouldn't have implementations
Here's a corrected example:
/** #const */
window.myapi = {};
/** #return {undefined} */
window.myapi.hello = function() {};
In Closure-compiler properties on the window (global) object are seen completely differently than global variables. If you need both, you'll have to declare everything twice.
/** #const */
var myapi = {};
/** #return {undefined} */
myapi.hello = function() {};

Related

Transloco configuration missingHandler.logMissingKey

I have an Angular component that gets a TranslocoService injected into the constructor. The point of this component is to use the key provided as the output of the transform method in the event the key isn't found. This is done to make migrating existing components easier so I don't have to do them all at once.
The problem I'm having is that if I do this in the constructor in my component the config setting doesn't seem to have any affect.
this.translocoService.config.missingHandler.logMissingKey = false;
What am I missing here?
The translate function is as follows:
transform(contentKey: string, l10nBasePath: string): string {
const translatedText: string = this.translocoService.translate(l10nBasePath + '.' + contentKey);
if (translatedText !== null) {
return translatedText;
}
return contentKey;
}

Alfresco media viewer web-preview extensibility

So I followed Will Abson's guide and source code for extending custom media viewers in Alfresco.
I have a couple of issues though.
I'm already using 4.2+ Alfresco, so no need to use head.ftl as deprecated, I'm using a second extensibility module to add my own configuration automatically, BUT:
how can I access the jsNode in my web-preview.get.js? Or better, is there a way to access properties values and aspects of a node which is being displayed?
I know about both server and client side var jsNode = new Alfresco.util.Node(model.widgets[i].options.nodeRef) and var jsNode = AlfrescoUtil.getNodeDetails(model.widgets[i].options.nodeRef);
which were mentioned in another question here, but it seems like except of default values like, mimeType, size, nodeRef, I'm not able to use those to get data from the file.
These are my changes:
web-preview.get.js in -config folder of my custom media-viewer
//<import resource="classpath:/alfresco/templates/org/alfresco/import/alfresco-util.js">
if (model.widgets)
{
for (var i = 0; i < model.widgets.length; i++)
{
var at = "test";
//var jsNode = AlfrescoUtil.getNodeDetails(model.widgets[i].options.nodeRef);
//var author = jsNode.properties["cm:author"];
var widget = model.widgets[i];
if (widget.id == "WebPreview")
{
var conditions = [];
// Insert new pluginCondition(s) at start of the chain
conditions.push({
attributes: {
mimeType: "application/pdf"
},
plugins: [{
name: "PDF",
attributes: {
}
}]
});
var oldConditions = eval("(" + widget.options.pluginConditions + ")");
// Add the other conditions back in
for (var j = 0; j < oldConditions.length; j++)
{
conditions.push(oldConditions[j]);
}
// Override the original conditions
model.pluginConditions = jsonUtils.toJSONString(conditions);
widget.options.pluginConditions = model.pluginConditions;
}
}
}
PDF.js
/**
* Copyright (C) 2014 Will Abson
*/
/**
* This is the "PDF" plug-in used to display documents directly in the web browser.
*
* Supports the "application/pdf" mime types.
*
* #namespace Alfresco.WebPreview.prototype.Plugins
* #class Alfresco.WebPreview.prototype.Plugins.PDF
*/
(function()
{
/**
* PDF plug-in constructor
*
* #param wp {Alfresco.WebPreview} The Alfresco.WebPreview instance that decides which plugin to use
* #param attributes {Object} Arbitrary attributes brought in from the <plugin> element
*/
Alfresco.WebPreview.prototype.Plugins.PDF = function(wp, attributes)
{
this.wp = wp;
this.attributes = YAHOO.lang.merge(Alfresco.util.deepCopy(this.attributes), attributes);
//this.wp.options.nodeRef = this.wp.nodeRef;
return this;
};
Alfresco.WebPreview.prototype.Plugins.PDF.prototype =
{
/**
* Attributes
*/
attributes:
{
/**
* Maximum size to display given in bytes if the node's content is used.
* If the node content is larger than this value the image won't be displayed.
* Note! This doesn't apply if src is set to a thumbnail.
*
* #property srcMaxSize
* #type String
* #default "2000000"
*/
srcMaxSize: "2000000"
},
/**
* Tests if the plugin can be used in the users browser.
*
* #method report
* #return {String} Returns nothing if the plugin may be used, otherwise returns a message containing the reason
* it cant be used as a string.
* #public
*/
report: function PDF_report()
{
// TODO: Detect whether Adobe PDF plugin is installed, or if navigator is Chrome
// See https://stackoverflow.com/questions/185952/how-do-i-detect-the-adobe-acrobat-version-installed-in-firefox-via-javascript
var srcMaxSize = this.attributes.srcMaxSize;
if (!this.attributes.src && srcMaxSize.match(/^\d+$/) && this.wp.options.size > parseInt(srcMaxSize))
{
return this.wp.msg("pdf.tooLargeFile", this.wp.options.name, Alfresco.util.formatFileSize(this.wp.options.size), Alfresco.util.formatFileSize(this.attributes.srcMaxSize));
}
},
/**
* Display the node.
*
* #method display
* #public
*/
display: function PDF_display()
{
// TODO: Support rendering the content of the thumbnail specified
var src = this.wp.getContentUrl();
var test = this.attributes.author;
//var test = this.wp.options.nodeRef;
//var jsNode = new Alfresco.util.Node(test);
//var jsNode = AlfrescoUtil.getNodeDetails(this.wp.options.nodeRef);
//var author = jsNode.properties["cm:author"];
//var test = this.wp.options.author;
//var test1 = this.wp.options.mimeType;
//var test = this.attributes.author.replace(/[^\w_\-\. ]/g, "");
//.replace(/[^\w_\-\. ]/g, "");
return '<iframe name="' + test + '" src="' + src + '"></iframe>';
}
};
})();
As you can see by commented sections I tried different methods to access node properties/values, even simple strings, but I'm missing something for sure.
Thanks.
If you take a look at the source code you'll see that the helper method is nothing else than doing a remote call to var url = '/slingshot/doclib2/node/' + nodeRef.replace('://', '/');
So take a look at what that Repository WebScript is returning en match it to the properties you need.
I normally don't use this one and I know for sure the /api/metadata returns all the properties.

Actionscript 3 introspection -- function names

I am trying to iterate through each of the members of an object. For each member, I check to see if it is a function or not. If it is a function, I want to get the name of it and perform some logic based on the name of the function. I don't know if this is even possible though. Is it? Any tips?
example:
var mems: Object = getMemberNames(obj, true);
for each(mem: Object in members) {
if(!(mem is Function))
continue;
var func: Function = Function(mem);
//I want something like this:
if(func.getName().startsWith("xxxx")) {
func.call(...);
}
}
I'm having a hard time finding much on doing this. Thanks for the help.
Your pseudocode is close to doing what you want. Instead of using getMemberNames, however, which can get private methods, you can loop over the members with a simple for..in loop, and get the values of the members using brackets. For example:
public function callxxxxMethods(o:Object):void
{
for(var name:String in o)
{
if(!(o[name] is Function))
continue;
if(name.startsWith("xxxx"))
{
o[name].call(...);
}
}
}
Dan Monego's answer is on the money, but only works for dynamic members. For any fixed instance (or static) members, you'll have to use flash.utils.describeType:
var description:XML = describeType(obj);
/* By using E4X, we can use a sort of lamdba like statement to find the members
* that match our criteria. In this case, we make sure the name starts with "xxx".
*/
var methodNames:XMLList = description..method.(#name.substr(0, 3) == "xxx");
for each (var method:XML in methodNames)
{
var callback:Function = obj[method.#name];
callback(); // For calling with an unknown set of parameters, use callback.apply
}
Use this in conjunction with Dan's answer if you have a mix of dynamic and fixed members.
I've done some work and combined both approaches. Mind you, it works only for publicly visible members - in all other cases null is returned.
/**
* Returns the name of a function. The function must be <b>publicly</b> visible,
* otherwise nothing will be found and <code>null</code> returned.</br>Namespaces like
* <code>internal</code>, <code>protected</code>, <code>private</code>, etc. cannot
* be accessed by this method.
*
* #param f The function you want to get the name of.
*
* #return The name of the function or <code>null</code> if no match was found.</br>
* In that case it is likely that the function is declared
* in the <code>private</code> namespace.
**/
public static function getFunctionName(f:Function):String
{
// get the object that contains the function (this of f)
var t:Object = getSavedThis(f);
// get all methods contained
var methods:XMLList = describeType(t)..method.#name;
for each (var m:String in methods)
{
// return the method name if the thisObject of f (t)
// has a property by that name
// that is not null (null = doesn't exist) and
// is strictly equal to the function we search the name of
if (t.hasOwnProperty(m) && t[m] != null && t[m] === f) return m;
}
// if we arrive here, we haven't found anything...
// maybe the function is declared in the private namespace?
return null;
}
greetz,
tox

Can I get some advice on JavaScript delegates?

I'm rusty with delegates and closures in JavaScript, and think I came across a situation where I'd like to try to use one or both.
I have a web app that behaves a lot like a forms app, with fields hitting a server to change data on every onBlur or onChange (depending on the form element). I use ASP.NET 3.5's Web Services and jQuery to do most of the work.
What you need to know for the example:
isBlocking() is a simple mechanism to form some functions to be synchronous (like a mutex)
isDirty(el) checks to make sure the value of the element actually changed before wasting a call to the server
Agent() returns a singleton instance of the WebService proxy class
getApplicationState() passes a base-64 encoded string to the web service. This string represents the state of the application -- the value of the element and the state are passed to a service that does some calculations. The onSuccess function of the web service call returns the new state, which the client processes and updates the entire screen.
waitForCallback() sets a flag that isBlocking() checks for the mutex
Here's an example of one of about 50 very similar functions:
function Field1_Changed(el) {
if (isBlocking()) return false;
if (isDirty(el)) {
Agent().Field1_Changed($j(el).val(), getApplicationState());
waitForCallback();
}
}
The big problem is that the Agent().Field_X_Changed methods can accept a different number of parameters, but it's usually just the value and the state. So, writing these functions gets repetitive. I have done this so far to try out using delegates:
function Field_Changed(el, updateFunction, checkForDirty) {
if (isBlocking()) return false;
var isDirty = true; // assume true
if (checkForDirty === true) {
isDirty = IsDirty(el);
}
if (isDirty) {
updateFunction(el);
waitForCallback();
}
}
function Field1_Changed(el) {
Field_Changed(el, function(el) {
Agent().Field1_Changed($j(el).val(), getTransactionState());
}, true);
}
This is ok, but sometimes I could have many parameters:
...
Agent().Field2_Changed($j(el).val(), index, count, getApplicationState());
....
What I'd ultimately like to do is make one-linen calls, something like this (notice no getTransactionState() calls -- I would like that automated somehow):
// Typical case: 1 value parameter
function Field1_Changed(el) {
Field_Changed(el, delegate(Agent().Field1_Changed, $j(el).val()), true);
}
// Rare case: multiple value parameters
function Field2_Changed(el, index, count) {
Field_Changed(el, delegate(Agent().Field1_Changed, $j(el).val(), index, count), true);
}
function Field_Changed(el, theDelegate, checkIsDirty) {
???
}
function delegate(method) {
/* create the change delegate */
???
}
Ok, my first question is: Is this all worth it? Is this harder to read but easier to maintain or the other way around? This is a pretty good undertaking, so I may end up putting a bounty on this one, but I'd appreciate any help you could offer. Thanks!
UPDATE
So, I've accepted an answer based on the fact that it pointed me in the right direction. I thought I'd come back and post my solution so that others who may just be starting out with delegates have something to model from. I'm also posting it to see if anybody wants to try an optimize it or make suggestions. Here's the common Field_Changed() method I came up with, with checkForDirty and omitState being optional parameters:
function Field_Changed(el, args, delegate, checkForDirty, omitState) {
if (isBlocking()) return false;
if (!$j.isArray(args) || args.length == 0) {
alert('The "args" parameter in Field_Changed() must be an array.');
return false;
}
checkForDirty = checkForDirty || true; // assume true if not passed
var isDirty = true; // assume true for updates that don't require this check
if (checkForDirty === true) {
isDirty = fieldIsDirty(el);
}
if (isDirty) {
omitState = omitState || false; // assume false if not passed
if (!omitState) {
var state = getTransactionState();
args.push(state);
}
delegate.apply(this, args);
waitForCallback();
}
}
It handles everything I need it to (check for dirty, applying the application state when I need it to, and forcing synchronous webservice calls. I use it like this:
function TransactionAmount_Changed(el) {
Field_Changed(el, [cleanDigits($j(el).val())], Agent().TransactionAmount_Changed, true);
}
cleanDigits strips out junk characters the user may have tried to type in. So, thanks to everyone, and happy coding!
OK, few things:
Delegates are extremely simple in javascript since functions are first class members.
Function.apply lets you call a function with an array of arguments.
So you can write it this way
function Field_Changed(delegate, args)
{
if (isBlocking()) return false;
if (isDirty(args[0])) { //args[0] is el
delegate.apply(this, args);
waitForCallback();
}
}
And call it as:
Field_Changed(Agent().Field2_Changed, [el, getApplicationState(), whatever...]);
I have been using the following utility function that I wrote a long time ago:
/**
* #classDescription This class contains different utility functions
*/
function Utils()
{}
/**
* This method returns a delegate function closure that will call
* targetMethod on targetObject with specified arguments and with
* arguments specified by the caller of this delegate
*
* #param {Object} targetObj - the object to call the method on
* #param {Object} targetMethod - the method to call on the object
* #param {Object} [arg1] - optional argument 1
* #param {Object} [arg2] - optional argument 2
* #param {Object} [arg3] - optional argument 3
*/
Utils.createDelegate = function( targetObj, targetMethod, arg1, arg2, arg3 )
{
// Create an array containing the arguments
var initArgs = new Array();
// Skip the first two arguments as they are the target object and method
for( var i = 2; i < arguments.length; ++i )
{
initArgs.push( arguments[i] );
}
// Return the closure
return function()
{
// Add the initial arguments of the delegate
var args = initArgs.slice(0);
// Add the actual arguments specified by the call to this list
for( var i = 0; i < arguments.length; ++i )
{
args.push( arguments[i] );
}
return targetMethod.apply( targetObj, args );
};
}
So, in your example, I would replace
function Field1_Changed(el) {
Field_Changed(el, delegate(Agent().Field1_Changed, $j(el).val()), true);
}
With something along the lines
function Field1_Changed(el) {
Field_Changed(el, Utils.createDelegate(Agent(), Agent().Field1_Changed, $j(el).val()), true);
}
Then, inside of Agent().FieldX_Changed I would manually call getApplicationState() (and encapsulate that logic into a generic method to process field changes that all of the Agent().FieldX_Changed methods would internally call).
Closures and delegates in JavaScript:
http://www.terrainformatica.com/2006/08/delegates-in-javascript/
http://www.terrainformatica.com/2006/08/delegates-in-javascript-now-with-parameters/

Is it possible to define a generic type Vector in Actionsctipt 3?

Hi i need to make a VectorIterator, so i need to accept a Vector with any type. I am currently trying to define the type as * like so:
var collection:Vector.<*> = new Vector<*>()
But the compiler is complaining that the type "is not a compile time constant". i know a bug exists with the Vector class where the error reporting, reports the wrong type as missing, for example:
var collection:Vector.<Sprite> = new Vector.<Sprite>()
if Sprite was not imported, the compiler would complain that it cannot find the Vector class. I wonder if this is related?
So it looks like the answer is there is no way to implicitly cast a Vector of a type to valid super type. It must be performed explicitly with the global Vector.<> function.
So my actual problem was a mix of problems :)
It is correct to use Vector. as a generic reference to another Vector, but, it cannot be performed like this:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = spriteList // this will cause a type casting error
The assignment should be performed using the global Vector() function/cast like so:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = Vector.<Object>(spriteList)
It was a simple case of me not reading the documentation.
Below is some test code, I would expect the Vector. to cast implicitly to Vector.<*>.
public class VectorTest extends Sprite
{
public function VectorTest()
{
// works, due to <*> being strictly the same type as the collection in VectorContainer
var collection:Vector.<*> = new Vector.<String>()
// compiler complains about implicit conversion of <String> to <*>
var collection:Vector.<String> = new Vector.<String>()
collection.push("One")
collection.push("Two")
collection.push("Three")
for each (var eachNumber:String in collection)
{
trace("eachNumber: " + eachNumber)
}
var vectorContainer:VectorContainer = new VectorContainer(collection)
while(vectorContainer.hasNext())
{
trace(vectorContainer.next)
}
}
}
public class VectorContainer
{
private var _collection:Vector.<*>
private var _index:int = 0
public function VectorContainer(collection:Vector.<*>)
{
_collection = collection
}
public function hasNext():Boolean
{
return _index < _collection.length
}
public function get next():*
{
return _collection[_index++]
}
}
[Bindable]
public var selectedItems:Vector.<Category>;
public function selectionChange(items:Vector.<Object>):void
{
selectedItems = Vector.<Category>(items);
}
I believe you can refer to an untyped Vector by just calling it Vector (no .<>)
With Apache Flex 4.11.0, you can already do what you want. It might have been there since 4.9.0, but I have not tried that before.
var collection:Vector.<Object> = new Vector.<Object>()
maybe?
But i'm just speculating, haven't tried it.
var collection:Vector.<Object> = new Vector.<Object>()
but only on targeting flash player 10 cs4

Resources