Can I call behaviors methods directly without eventproxy? - javascript

I'm searching for alternative ways to call a method defined in Marionette's behaviors from inside a view.
For sure there is the eventproxy but maybe it's more intuitive to call the method directly like:
view.behaviorsMethod();
I could assign it like:
view.method = behavior.method;
I could check for reassignment because it'll maybe lead to unexpected results for others:
view.method = (view.method !== undefined ? view.method : behavior.method);
But this doesn't seem to be an elegant way.

The answer to your question is you can not directly do so, but there is always a way.
you can do it using _.invoke(this._behaviors, 'yourMethodName') but I will discourage using it
since
_behaviors is a private variable of the Marionette.View class and it's name can be changed or it can be dropped in upcoming versions
You will have to set context for the method as _.invoke will not set
the context of the method to proper this.
if you can set the context properly then this will work for you.
as suggested by #ThePaxBisonica in comment
I will suggest you to go with a mixin pattern from which you can extend both your behavior and view and you will not have to set any context and do not have to worry about the _behavior private variable
as
var mixin = {
behaviorMethodWhichYouWantToCallFromView: function(){
alert("mixin method");
}
}
var behavior = mn.behavior.extend(_.extend(mixin, {
//actual behavior code remove the method as behavior will get it from mixin
}))
var view = mn.view.extend(_.extend(mixin, {
//actual view code remove the method as behavior will get it from mixin
}))
Hope it helps.
I know this is bit long approach.

Related

Getter functions

I've peeked into many plugins' code (for educational purposes) and basically every one of them (which deals with prototypes), has bunch of functions like this:
myMarker.prototype.getPosition = function() {
return this.latlng;
};
//OR
myMarker.prototype.getObject = function() {
return this;
};
What's the reason behind this?
Why not just to use someObject.latlng instead of someObject.getPosition()?
One common reason for doing this is to avoid coupling the object's internal data storage to the API; in this example you could change the way the position is stored internally, and then add some processing to getPosition() to return a backwards compatible result.
For example, version 1.1 of this library might look like this, and calling code wouldn't need to be changed:
myMarker.prototype.getPosition = function() {
return this.latitude + this.longitude;
};
It is possible to accomplish this using computed properties with ES5 get and set, but only if the code doesn't need to run on Internet Explorer 8 and below.
When you say like this.
myMarker.prototype.getPosition = function() {
return this.latlng;
};
You are defining function getPosition which available to all instance to class myMarker.
So,all object of this class share this method without replication.
For someObject.latlng,there is nothing wrong.
But assume, this object is accessible to all which are in the current scope.So,it can be modified/accessible to anyone.
When you go through prototype you are trying to define some pattern,which gives restriction for access and modification of property

Firefox add-on: function not available after juggling scopes

As of Firefox 36, Function.__exposedProps__ was made unavailable. Instead if one wanted to expose a chrome JS object to be used in content scripts, they have to use Components.utils.cloneInto with the target scope as browser.contentWindow.wrappedJSObject.
If one does not turn on the cloneFunctions flag, only those attributes are cloned that are not functions. Turning the flag does clone functions too, but not those functions that are defined via the Function.prototype path. For those functions one has to export them via Components.utils.exportTo with the target scope as your exposed object.
Coming to the issue I'm facing. (As I am unable to put it in words, I am adding a MWE).
Chrome end JS:
function Foo(){
this._nFunc = "something";
this._func = function(){/*do something*/};
}
Foo.prototype.Bar = function(){
this._func();
}
Foo.prototype.FooBar = function(){
this._nFunc = "somthing else";
}
var myFoo = new Foo();
var targetScope = browser.contentWindow.wrappedJSObject;
targetScope.myExposedObject = Components.utils.cloneInto(myFoo, targetScope, {cloneFunctions:true});
Components.utils.exportFunction(myFoo.Bar, targetScope.myExposedObject , {defineAs:"Bar"});
Components.utils.exportFunction(myFoo.FooBar, targetScope.myExposedObject , {defineAs:"FooBar"});
Content end JS:
window.myExposedObject.FooBar(); // works
window.myExposedObject._func(); // works
window.myExposedObject.Bar() // error this._func is undefined
Upon logging the this scope received by the function Bar(), we get _func:(void 0), while _nFunc is logged correctly.
Questions:
Is there something I'm missing, or is this a limitation in Firefox? If it is a limitation, please suggest possible ways to workaround the limitation.
Initially I thought that Bar() was somehow unable to access the scope of the calling object, and I tried to supply it the scope as parameters, i.e., Foo.prototype.Bar = function(scope){ scope._func();} and window.myExposedObject.Bar(window.myExposedObject);. Interestingly upon logging, the scope object also turned out to be (void 0). Why is that? I am sure that I am missing something here. What I expected was that the exposed object would map to the original object and upon sending the exposed object as parameters the chrome end JS would be able to get the original object.
While what you're trying to do might be possible with the right combination of cloneInto/exportFunction and waiving of xrays i would suggest you simply load the unprivileged part of your class hierarchy directly into the target context with the subscript loader and only hook the minimal amount of privileged functions into the prototype once it has been created.
This should reduce the attack surface and also avoid headaches with inheritance.
Additionally, these may prove useful:
https://developer.mozilla.org/en-US/docs/Components.utils.createObjectIn
https://developer.mozilla.org/en-US/docs/Components.utils.makeObjectPropsNormal

Override javascript function while preserving the original context

I just want to confirm that I'm not missing something with regards to managing context and overriding methods. I'm using the http-proxy module in a node.js app and I need to override the function HttpProxy.prototype.proxyRequest. I'd like to do it without modifying the original module code directly but haven't been able to find a way to do it.
If I do this:
var httpProxy = require('http-proxy'),
httpProxyOverride = require('./http-proxy-override.js');
httpProxy.HttpProxy.prototype.proxyRequest = httpProxyOverride.proxyRequestOverride;
Then I lose the original context and errors are thrown. If I use apply(), I can provide a new context, but it doesn't appear I can persist the original context.
Based off of this SO thread:
Is it possible to call function.apply without changing the context?
It doesn't appear that there is a way to achieve what I'm trying to do and I'm hoping that someone can confirm this or correct me if I'm wrong.
What about saving the old function and then overwriting it like:
var old = httpProxy.HttpProxy.prototype.proxyRequest;
httpProxy.HttpProxy.prototype.proxyRequest = function () {
old.apply(this, arguments);
//do more stuff
}
taken from Javascript: Extend a Function

How can I create a selector like how jQuery has jQuery() or $()?

I have been creating my own library for a custom layout script. For ease of use, I am trying to emulate how jQuery exposes its library through the jQuery() which makes the code very easy to read and straightforward. I have come up with something that works but I am not sure if this is the correct way to do this. Rather than keep the functions internal all the functions are "appended" to the library. Anyways, the code which works for me so far is as follows:
slateUI = (function(slateID){
slateUI.ID = slateID;
return slateUI;
});
and a related function looks something like this:
slateUI.doSomething = function(content)
{
//DID SOMETHING USING slateUI.ID
}
I am fairly new to OOP like features of the language. I am sure there is a better way to approach this. The issue that I have is handing down the Element to an appened function call so for instance:
slateUI("#someSlate").doSomething(...)
Obtains its element from the slateUI.ID
Is this the correct way to approach this? Or is this a hacked way that I came up with and there is some straight forward way to do this?
// function which returns a new SlateUI object (so we dont have to use the "new" keyword)
slateUI = function ( slateID ) {
return new SlateUI( slateID );
};
// class definition
function SlateUI ( slateId ) {
this.id = slateId;
}
// methods added to the class prototype (allows for prototypical inheritance)
SlateUI.prototype.someFunction = function() {
alert( this.id );
return this; // adding this line to the end of each method allows for method chaining
};
// usage
slateUI( 'someid' ).someFunction();
The short version of your question is that you're looking for the ability to chain your functions.
This is achieved simply by returning the relevant object from each function. If the function has no other return value, then just return the this variable, to pass control back to the caller.

Hidden Features of MooTools

What are the hidden or obscure features of MooTools that every MooTools developer should be aware of?
One feature per answer, please.
Class Mutators
MooTools has a wonderful feature that allows you to create your own Class mutators. Eg, to add a logger for particular class methods being referenced, you can do:
// define the mutator as 'Monitor', use as Mointor: ['methodname', 'method2'...]
Class.Mutators.Monitor = function(methods){
if (!this.prototype.initialize) this.implement('initialize', function(){});
return Array.from(methods).concat(this.prototype.Monitor || []);
};
Class.Mutators.initialize = function(initialize){
return function(){
Array.from(this.Monitor).each(function(name){
var original = this[name];
if (original) this[name] = function() {
console.log("[LOG] " + name, "[SCOPE]:", this, "[ARGS]", arguments);
original.apply(this, arguments);
}
}, this);
return initialize.apply(this, arguments);
};
};
and then in the Class:
var foo = new Class({
Monitor: 'bar',
initialize: function() {
this.bar("mootools");
},
bar: function(what) {
alert(what);
}
});
var f = new foo();
f.bar.call({hi:"there from a custom scope"}, "scope 2");
Try the jsfiddle: http://jsfiddle.net/BMsZ7/2/
This little gem has been instrumental to me catching nested bugfoot race condition issues inside a HUUUGE async webapp that would have been so difficult to trace otherwise.
Function.prototype.protect is maybe a lesser known nice one.
Is used to have protected methods in classes:
var Foo = new Class({
fooify: function(){
console.log('can\'t touch me');
}.protect(),
barify: function(){
this.fooify();
}
});
var foo = new Foo();
foo.fooify(); // throws error
foo.barify(); // logs "can't touch me"
Personally I don't use it very often, but it might be useful in some cases.
Function.prototype.overloadGetter and Function.prototype.overloadSetter
See this post: What does MooTools' Function.prototype.overloadSetter() do?
There are many features that one can use if you read the source code, although the official line is: if it's not in the documentation, it is not in the api and it's not supported so do not base your code around it as it may change
That being said, there are a few things that really can be quite useful. One of my favourites undocumented features is this:
Referenced Elements have a uid
Any element that has either being created or is passed on through a selector, gets assigned a property uid, which is incremental and unique. Since MooTools 1.4.2, this is only readable via Slick.uidOf(node) and not via the old element attr .uid. You can now use the new uniqueNumber property of any MooTools Element object.
How is that being used? For starters, Element Storage. It relies on the uid as the key in the Storage object inside a closure, which will have anything you have .store'd for that element.
element.store('foo', 'bar');
translates to:
Storage[Slick.uidOf(element)].foo = 'bar';
and
element.retrieve('foo'); // getter of the storage key
element.eliminate('foo'); // delete Storage[Slick.uidOf(element)].foo
Initializing storage for an element you have created externally, eg, via var foo = document.createElement('div') and not Element constructor
Slick.uidOf(foo); // makes it compatible with Storage
// same as:
document.id(foo);
Things that are stored by the framework into Storage also include all events callbacks, validators instances, Fx instances (tween, morph etc) and so forth.
What can you do knowing the UIDs of elements? Well, cloning an element does NOT get the element's storage or events. You can actually write a new Element.cloneWithStorage prototype that will also copy all of the stored values you may have, which is useful upto a point - instances that reference a particular element (such as, Fx.Tween) will continue referencing the old element, so it may have unexpected results. This can be useful in moving your own storage, though, all you need is a similar method that will record what you have stored and allow you to clone it.
Example Storage puncture of another Element's data:
var foo = new Element('div'),
uid = foo.uniqueNumber;
foo.store('foo', 'foo only');
var bar = new Element('div');
console.log(bar.retrieve('foo')); // null
bar.uniqueNumber = uid; // force overwrite of uid to the other el
console.log(bar.retrieve('foo')); // foo only - OH NOES
console.log(Object.keys(foo)); // ["uniqueNumber"] - oh dear. enumerable!
One of my favorite features that I learned later but wished I knew from the beginning - event pseudos, especially :once.
See http://mootools.net/docs/more/Class/Events.Pseudos#Pseudos:once
I'd recommend reading the excellent Up the Moo Herd series by Mark Obcena, author of Pro Javascript With MooTools :)

Categories