I want to write some helper functions that I can use in my other JavaScript files.
It says here:
Some JavaScript libraries only work when placed in the client/compatibility subdirectory. Files in this directory are executed without being wrapped in a new variable scope.
It seems a bit bizarre to me that I should have to throw all my libraries in a folder called compatibility. Generally "compatible" stuff is for legacy code that hasn't been upgraded to the new style. Is there no way to export modules so that I can access them in my other files?
Using this pattern now:
Util = (function(exports) {
exports.getFileExtension = function(filename) {
var i = filename.lastIndexOf('.');
return (i < 0) ? '' : filename.substr(i);
};
// more functions
return exports;
})(typeof Util !== 'undefined' ? Util : {});
Not sure if that's the best or not...but it appears to work.
It would be bizarre, you are right. Write your own code, just put it somewhere and it works. This refers to complicated frameworks that make a lot of functions all over the place, where no one has 'tamed' them to only expose a root object that all its powers spring from.
Please read "Namespacing and Modules" at
http://www.meteor.com/blog/2013/08/14/meteor-065-namespacing-modularity-new-build-system-source-maps
It's helping you with built in maintainability for avoiding collisions with other things you write, which is largely what namespaces is for.
A good practice is to have your own helper object, named helper or util, where you put grouped things:
utils = {
distance_between: function(lat1,lng1,lat2,lng2) {
var radiusEarth = 3963.1676; // miles radius earth
var dLat = deg2rad(lat2-lat1); // deg2rad below
...
displayHumanReadableTime: function(timestamp){
var a = new Date(timestamp);
If the intention is to write Utility method then it can be written using the ECMA6 Script standard.
Write your method by exporting once in method.js and use it by importing in the desired file(s)
Ex:
export const MyUtilityMethod = function (){...} in /method.js
import {MyUtilityMethod} from './method.js'
Hope this helps.
Related
I maintain a data flow library that allows programmers to define new properties during instantiation, then does neat things at run-time with both property reads and writes, all transparently thanks to JS defineProperty. Sample usage, where TagSession is defined with the ES6 class keyword:
const sithApp = new TagSession( null, 'SithTrakSession',
{
obiTrakker: cF( c => new WebSocket('ws://localhost:4000')
.onmessage = msg => c.md.obiLoc = JSON.parse(msg.data)),
obiLoc: cI( null),
sithIds: cI([-1,-2,3616,-3,-4])
});
I can now write code where the map keywords are transparent accessors:
function SithTrak () {
return div({class: "app-container"},
h1({
class: "css-planet-monitor",
content: cF(c => "Obi-Wan currently on " +
(sithApp.obiLoc ?
sithApp.obiLoc.name : "...dunno"))
}))
}
This works great uncompiled and with Google Closure SIMPLE_OPTIMIZATION, but ADVANCED_COMPILATION warns (and the output fails) about, eg:
WARNING - Property obiLoc never defined on TagSession
withObi: cF( c=> c.md.info && sithApp.obiLoc
I have looked at all the annotations that might apply, but nothing seems suited to such a dynamic capability.
Am I missing something obvious, or is this combo of dynamism and optimization asking too much?
Dynamic properties added with this method would require using a bracket access for ADVANCED mode: sithApp['obiLoc']. In ADVANCED mode, the compiler must know about all properties accessed via the dot nation at compile time.
Since it isn't known that these properties are defined on the class you are going to get type warnings, bit it shouldn't break your code.
You can add declarations to silence the type warnings:
/** #type {?} */
TagSession.prototype.objLoc;
In other cases, you might be able to use #lends but I don't think this will work here as the types provided might not match the expected type of the property value. But there isn't enough context to be sure:
/** #lends {TagSession.prototype} */ ({
obiTrakker: ...,
obiLoc: ...,
sithIds: ...
})
I have a very specialized filter I want to use for a single page without making it a global filter. I tried doing this (that isn't the function I want, it's just a test):
$this->get('twig')
->addFilter(new \Twig_SimpleFilter('chgname', function ($string) {
return substr($string, 0, 5);
}));
But I get an error, "Unable to add filter as extensions have already been initialized".
I know that I can create a class in the AppBundle/Twig directory and add it as a service, but 1) That's incredibly heavy and a PITA for just a simple filter that I need, and 2) It makes it global to the entire application, which is dumb for something I need locally.
Is there any way to do this, or am I stuck with only global extensions? Thanks in advance.
Twig loads an environment when your app boots and you cannot dynamically change it.
if you think Symfony is too heavy you can still take a look at Silex (which uses Symfony components) so you could write something like :
$app['twig'] = $app->extend('twig', function ($twig) {
$twig->addFilter(new \Twig_SimpleFilter('chgname', function ($string) {
return substr($string, 0, 5);
}));
return $twig;
});
see http://silex.sensiolabs.org
here is the code of an alloy controller written in two different ways. Although the both work the same, Which one might be best practice?
example 1 of controller.js:
var currentState = true;
$.getState = function(){
return currentState;
}
example 2 of controller.js:
var currentState = true;
exports.getState = function(){
return currentState;
}
Titanium is based on the CommonJS framework. The exports variable is a special variable used typically to expose a public API in a class object. So when you want to expose a method of doSomething() on the MyModule.js class you would use the exports variable like this:
exports.doSomething() = function(args) {
//Some really cool method here
};
Then reference that class using
var myModule = require('MyModule');
myModule.doSomething();
However when referencing a view object the typical way to reference the is using the $. shortcut. You can see they prefer that method in the official documentation.
http://docs.appcelerator.com/platform/latest/#!/guide/Alloy_XML_Markup
The $ variable holds a reference to your controller instance. It also contains some references to all indexed views (understand, views for which you supplied an index in you xml markup).
Both ways are strictly equivalent as, during the compilation, Alloy will merge the content of the exports with your controller referenced in $. Adding them directly to the instance won't change a thing.
Neverthless, developers are used to see the public API as the set of functions exported via the special variable exports; Thus, I will recommend to keep using it in a clean and clear way (for instance, defining your functions in your module scope, and only expose them at the end or beginning of your controller).
function myFunction1 () { }
function myFunction2 () { }
function myFunction3 () { }
exports.myFunction1 = myFunction1;
exports.myFunction3 = myFunction3;
Thereby, your API is quite clear for people diving into your source code. (A readMe file is also highly recommended :) ).
Where do I define the functions that I want to use across the client code? Is it fine to define it with Template.registerHelper() although it is not necessarily intended to use inside templates? I want to be able to do something like util.calculateDistance(a,b) in any client code base.
You can define the method globally or on a global object (don't use the var keyword to make it global):
util = {} //instead of var util = {}
util.calculateDistance = function(a,b) {....}
If I have rolled my own RSL, and I want to use it in my pure as3 apps, is there documentation or an example of how to do this?
Or do I need to traverse the flex source code to figure out what adobe's engineers have done?
This is a very tricky one, with lots to go into I'm afraid. Some pointers:
To get a class from an externally loaded SWF use the getDefinition method on an application domain e.g.
public function loadHandler(evt:Event):void
{
var loaderInfo:LoaderInfo = evt.target as LoaderInfo;
var clazz:Class = loaderInfo.applicationDomain.getDefinition("your.external.class");
}
This will give you the class definition if you know the name of the class you want.
To 'join' class domains into each other (so applications can compile against a swc, but not include the classes and load them externally) you need to specify a loaderContext of the same security domain.
var loader:Loader = new Loader();
var context:LoaderContext = new LoaderContext();
context.applicationDomain = ApplicationDomain.currentDomain;
loader.load(new URLRequest("library.swf"), context);
The third pointer I can give you is the compiler option "-external-library-path", use this to specify a list of swc's to compile time check against, but not include (resulting in a lower filesize).
mxmlc -source-path="dir/src" -external-library-path="dir/lib/framework.swc" --main.swf
Sorry I couldn't elaborate more, it's a very expansive topic, hope this gets you started....