Overriding a private function within a closure - javascript

I have this puzzler. I've downloaded a jQuery plugin that has the following construction
(function($, undefined) {
function a() {
...
}
$.fn.fullCalendar = function(options) {
...
var avar = a();
...
}
})(jQuery);
and my taks is to modify the plugin (I need to override the 'a' function) but I can't touch the core and I need to modify it from an external file. So... the problem is I don't know is there at all a way to access an unnamed closure and the second if I'd be able to will I be able to override a private function within it?
To be more specific: the plugin is: http://arshaw.com/fullcalendar and I need to override the 'daySegHTML' function within the core.
Thank You for any advices.

You can't override functions in closures (at least not if they aren't exposed to the outside somehow). The only chance to modify it, is modifying the source code itself (if it's license allows it).
Closures are used to "hide" functionality from the user. It is probably the only reason why there are powerful javascript libraries like google maps out there.

Related

Add a public function to a jquery plugin, to be called from another script

I'm using the Adobe Accessible Mega Menu plugin and am looking to extend this, (basically add a function that can be called from another script).
I've looked into extending jquery plugins, javascript closures and various other threads on the subject and I can see how this works
I can also see a bunch of public attributes and methods (ln 695 on) however attempting to call these merely returns the jquery object?
Equally adding a function and attempting to call that doesn't seem to work?
I've added a function called testFunction which fires an alert and should (i think) be called :
$("nav:first").accessibleMegaMenu("testFunction");
but no luck far..
Does anyone know how I can add a function to the above script, that can be called from another script?
https://codepen.io/anon/pen/VjzkqE
edit: solved - functions need to be accessed through the prototype obj as in :
nav.accessibleMegaMenu.AccessibleMegaMenu.prototype.customFunction(param);
I have implemented this approach on a project by using extend function from jquery and prototype to extend infinitescroll plugin you can take this approach and implement it to your plugin I hope this would be useful for you as well
$.extend($.infinitescroll.prototype, {
fucntion1: function() {
//function implementation
},
fucntion2: function() {
//function implementaion
}
});
take a look for the question Best Way to Extend a jQuery Plugin

Starting with RequireJS, communication between modules

I am an ActionScript 3 developer who is just making his first way in building a large-scale JavaScript app.
So I understand modules and understand that AMD is a good pattern to use. I read about RequireJS and implemented it. However, what I still don't understand is how to achieve Cross-Module communication. I understand that there should be some kind of mediator...
I read articles and posts and still couldn't understand how to implement it simply.
Here is my code, simplified:
main.js
require(["Player", "AssetsManager"], function (player, manager) {
player.loadXML();
});
Player.js
define(function () {
function parseXml(xml)
{
// NOW HERE IS THE PROBLEM -- how do I call AssetsManager from here???
AssetsManager.queueDownload($(xml).find("prop").text());
}
return {
loadXML: function () {
//FUNCTION TO LOAD THE XML HERE, WHEN LOADED CALL parseXml(xml)
}
}
});
AssetsManager.js
define(function () {
var arrDownloadQueue = [];
return {
queueDownload: function(path) {
arrDownloadQueue.push(path);
}
}
});
Any "for dummies" help will be appreciated :)
Thank you.
To load up modules from another modules that you define(), you would simply set the first parameter as an array, with your module names in it. So let's say, in your code, you wanted to load Player.js into AssetsManager.js, you would simply include the string Player in the array.
This is simply possible because define's abstract implementation is equivalent to require, only that the callback passed to define expects a value to be returned, and that it will add a "module" to a list of dependencies that you can load up.
AssetsManager.js
define(['Player'], function (player) {
//... Your code.
});
However, if I can add to it, I personally prefer the use of require inside of the callback passed to define to grab the dependency that you want to load, instead of passing parameter to the callback.
So here's my suggestion:
define(['Player'], function () {
var player = require('Player');
});
And this is because it's much more in tune with CommonJS.
And this is how main.js would look like formatted to be more CommonJS-friendly:
require(["Player", "AssetsManager"], function () {
var player = require('Player');
var manager = require('AssetsManager');
player.loadXML();
});
But the CommonJS way of doing things is just a personal preference. My rationale for it is that the order in which you input the dependency names in the array might change at any time, and i wouldn't want to have to step through both the array and the parameters list.
Another rationale of mine (though, it's just pedantic), is that I come from the world of Node.js, where modules are loaded via require().
But it's up to you.
(This would be a reply to skizeey's answer, but I don't have enough reputation for that)
Another way of solving this problem without pulling in Player's AssetManager dependency via require is to pass the AssetManager instance that main.js already has around. One way of accomplishing this might be to make Player's loadXML function accept an AssetManager parameter that then gets passed to parseXml, which then uses it. Another way might be for Player to have a variable to hold an AssetManager which gets read by parseXml. It could be set directly or a function to store an AssetManager in the variable could be used, called say, setAssetManager. This latter way has an extra consideration though - you then need to handle the case of that variable not being set before calling loadXml. This concept is generally called "dependency injection".
To be clear I'm not advising this over using AMD to load it in. I just wanted to provide you with more options; perhaps this technique may come in handier for you when solving another problem, or may help somebody else. :)

One javascript file kills all the others. Ways to avoid this?

I will not add any code in here. Just working on a project and not only this time, but frequently one javascript file kills the others, so I ussually in this situation looked for similar solution (lets say a different slider and etc.)
But are there any more ways to wrap up some how a javascript file that it wont interfere with the others?
Please provide more details of what exactly you mean - but I have a feeling.
Use namespaces.
If you're using a collective of different libraries it could happen that libraries have the same global name, if you're not using namespaces.
Example how collisions usually occur:
function dontdothis() {
alert("Foo");
}
function dontdothis() {
alert("Bar");
}
dontdothis();
Example how to avoid those collisions:
var myownspace={};
myownspace.dothis=function() {
alert("Foo");
}
function dothis() {
alert("Bar");
}
myownspace.dothis();
In general, each desecrate chuck of JavaScript should be wrapped in a closure with an API that is exposed to the wide world through a single global (which has a non-generic name, so YAHOO is reasonable as it is unlikely to be used by something else, while $ is awful).
This is known as namespacing
If I understood your question correctly, your solution is namespaces.
var APP = {};
APP.namespace = function(sNamespace) {
if ("undefined" == typeof APP[sNamespace]) {
APP[sNamespace] = {};
}
}
Usage:
APP.namespace("profile");
APP.profile.AskQuestionDialog = function(oConfigs) { ... }
DOM tree:
-window
-APP
-profile
And you should define you namespace in beginning of each file using APP.namespace()

How to isolate different javascript libraries on the same page?

Suppose we need to embed a widget in third party page. This widget might use jquery for instance so widget carries a jquery library with itself.
Suppose third party page also uses jquery but a different version.
How to prevent clash between them when embedding widgets? jquery.noConflict is not an option because it's required to call this method for the first jquery library which is loaded in the page and this means that third party website should call it. The idea is that third party site should not amend or do anything aside putting tag with a src to the widget in order to use it.
Also this is not the problem with jquery in particular - google closure library (even compiled) might be taken as an example.
What solutions are exist to isolate different javascript libraries aside from obvious iframe?
Maybe loading javascript as string and then eval (by using Function('code to eval'), not the eval('code to eval')) it in anonymous function might do the trick?
Actually, I think jQuery.noConflict is precisely what you want to use. If I understand its implementation correctly, your code should look like this:
(function () {
var my$;
// your copy of the minified jQuery source
my$ = jQuery.noConflict(true);
// your widget code, which should use my$ instead of $
}());
The call to noConflict will restore the global jQuery and $ objects to their former values.
Function(...) makes an eval inside your function, it isn't any better.
Why not use the iframe they provide a default sandboxing for third party content.
And for friendly ones you can share text data, between them and your page, using parent.postMessage for modern browser or the window.name hack for the olders.
I built a library to solve this very problem. I am not sure if it will help you of course, because the code still has to be aware of the problem and use the library in the first place, so it will help only if you are able to change your code to use the library.
The library in question is called Packages JS and can be downloaded and used for free as it is Open Source under a Creative Commons license.
It basically works by packaging code inside functions. From those functions you export those objects you want to expose to other packages. In the consumer packages you import these objects into your local namespace. It doesn't matter if someone else or indeed even you yourself use the same name multiple times because you can resolve the ambiguity.
Here is an example:
(file example/greeting.js)
Package("example.greeting", function() {
// Create a function hello...
function hello() {
return "Hello world!";
};
// ...then export it for use by other packages
Export(hello);
// You need to supply a name for anonymous functions...
Export("goodbye", function() {
return "Goodbye cruel world!";
});
});
(file example/ambiguity.js)
Package("example.ambiguity", function() {
// functions hello and goodbye are also in example.greeting, making it ambiguous which
// one is intended when using the unqualified name.
function hello() {
return "Hello ambiguity!";
};
function goodbye() {
return "Goodbye ambiguity!";
};
// export for use by other packages
Export(hello);
Export(goodbye);
});
(file example/ambiguitytest.js)
Package("example.ambiguitytest", ["example.ambiguity", "example.greeting"], function(hello, log) {
// Which hello did we get? The one from example.ambiguity or from example.greeting?
log().info(hello());
// We will get the first one found, so the one from example.ambiguity in this case.
// Use fully qualified names to resolve any ambiguities.
var goodbye1 = Import("example.greeting.goodbye");
var goodbye2 = Import("example.ambiguity.goodbye");
log().info(goodbye1());
log().info(goodbye2());
});
example/ambiguitytest.js uses two libraries that both export a function goodbye, but it can explicitly import the correct ones and assign them to local aliases to disambiguate between them.
To use jQuery in this way would mean 'packaging' jQuery by wrapping it's code in a call to Package and Exporting the objects that it now exposes to the global scope. It means changing the library a bit which may not be what you want but alas there is no way around that that I can see without resorting to iframes.
I am planning on including 'packaged' versions of popular libraries along in the download and jQuery is definitely on the list, but at the moment I only have a packaged version of Sizzle, jQuery's selector engine.
Instead of looking for methods like no conflict, you can very well call full URL of the Google API on jQuery so that it can work in the application.
<script src="myjquery.min.js"></script>
<script>window.myjQuery = window.jQuery.noConflict();</script>
...
<script src='...'></script> //another widget using an old versioned jquery
<script>
(function($){
//...
//now you can access your own jquery here, without conflict
})(window.myjQuery);
delete window.myjQuery;
</script>
Most important points:
call jQuery.noConflict() method IMMEDIATELY AFTER your own jquery and related plugins tags
store the result jquery to a global variable, with a name that has little chance to conflict or confuse
load your widget using the old versioned jquery;
followed up is your logic codes. using a closure to obtain a private $ for convience. The private $ will not conflict with other jquerys.
You'd better not forget to delete the global temp var.

JSObject-like stuff in ActionScript 3?

I would like to ask if there is a liveconnect equivalent for ActionScript 3. I understand that there is the ExternalInterface class inside AS3 but it only supports calling a method by name. The really cool thing about Java and LiveConnect is that you can do something like
function jsFunc(name) = {
this.name = name;
this.talk = function(){
alert('hello world my name is ' + this.name);
}
}
javaapplet.function(new jsFunc("bob"));
The above approaches pseudo code since I never tested it but I've seen it in action. In AS3, while I am able to pass in an instance of JavaScript "object" into AS, it is often converted into an ActionScript Object instance which does away with all the functions as far as I'm aware.
I saw an implementation of JSInterface but I don't think it does specifically that. Is there any way to make OO like javascript work with ActionScript 3?
Try this library on Google code:
http://code.google.com/p/jsobject/
ExternalInterface.call("f = function() { alert('Is this like live connect?'); }");
Actually the main usage scenario is to have JS "objects" interacting with the Flex SWF application. Therefore when the JS "object" wants to say wait for something happening in the SWF object, it will put in a "this" with a callback.
After researching, the way I used to accomplish this is via the Flex Ajax bridge. It may not be a direct answer to the way I phrased the question but it was sufficient for my needs.
Basically what I do is via FABridge, after initializing, I'll attach event listeners to the object.
// JS
FlexApp.addEventListeners('flexDidSomething', this.doSomething().bind(this)); //using mootools;
and in Flex, the main application itself
// AS
dispatchEvent(new CustomCreatedEvent(param1, param2));
And inside the JS function I'll access the get methods of the event object to retrieve the params.
There's tight coupling in that sense but it works at least for what I need.
Hope this is helpful!
JSInterface designed exactly for such things.

Categories

Resources