Why can't my jQuery.Widgets namespace be accessed? - javascript

I've been reading alot about the advantages of using the jQuery.Widget Factory for my plugins. One of the capabilities touted is how the jQuery.widget creates a namespeace for your widget. This is attractive, as I can maintain my current namespacing (naturally) within the jQuery context.
THE PROBLEM:
I keep getting "$(".myWidget").namespace.newWay is not a function" error.
For the following element...
<div class="myWidget"></div>
THIS EXAMPLES CODE WORKS:
While nice...this is NOT what I am trying to achieve...as I still want my namespace to be honored.
var workingVersion = {
_init: function () { /* Do Something*/ }
};
$.widget("ui.workingVersion", workingVersion);
$(document).ready(function () {
$('.myWidget').workingVersion();
});
HOWEVER, MY CODE FAILS:
var namespace = namespace || { };
;namespace.newWay = (function ($, window, document, undefined) {
return function (options) {
var self = this;
this._create = function () {
// Do something
},
this._init = function() {
// Do something
},
this.publicFunction = function () {
// Do something
};
};
})(jQuery, window, document);
$(document).ready(function () {
$.widget("ui.namespace.newWay", namespace.newWay); //<-- Namespace does get appended
$('.myWidget').namespace.newWay({ type: 'testing' }); //<-- But still fails here
});
MY QUESTION IS:
Why does it fail?
RELATED READING:
Understanding jQuery UI widgets: A tutorial
Tips for Developing jQuery UI 1.8 Widgets

This answer comes a bit late, maybe, but I was struggling with the same thing and had to do some reading.
$() in General
The $() instance is a no-namespace shortcut list to different functions spread out over different namespaces. You can add more functions to this shortcut list by writing:
$.fn.myFunction = function() {
...
};
Which then will be accessed by calling
$("...").myFunction();
If you add two functions by the same name the latter one will overwrite the first one.
Widgets
When you create a widget with a namespace it's created with it's namespace, as you would expect, but to $() it's added without it's namespace, as a simplified shortcut to your real widget-with-shortcut. This is done using $.widget.bridge(). You can therefore create your own namespaced link to $() by writing like this:
$.widget.bridge("namespace_myFunction", $.namespace.myFunction );
And then access your widget like this:
$("#myDiv").namespace_myFunction();
To use a widget directly with it's original namespace you can instead invoke it like this:
$.namespace.myWidget(
{
option1: "",
option2: ""
},
$("#div")
);
Hope this will clarify a little...

Related

extending jQuery functionality specifics on variations

I understand I can extend jQuery in two forms:
1)
jQuery.fn.extend({
variation1: function(){
...
}
});
I use this like $(selector).variation1();
2)
and custom function
jQuery.variation2 = {
something: function(){
var execute = function(){
...
}
}
}
I use this like $.variation2.something()
My questions are:
In the first case, I was unable to call functions without a selector; this code caused errors $.variation1(); Is this correct? meaning, is there a way to call these functions without an element selector?
In the second case, how could I initialize variation2 with options? The reason I ask this is because in MooTools, when creating a class, we can initialize the class like:
var jsClass = new Class({
Implements: [Options],
options: {
},
initialize: function(options){
this.setOptions(options);
}
});
we call it, and initialize with custom options like
new jsClass({option1: this, option2: that})
So in the MooTools example the class instance executes options by default. Going back to the question, is there a way to do similar in jQuery?
Thanks in advance
The two variations are distinct as you have noticed. jQuery.fn provides the set of functions that are applied to a jQuery QuerySet object (the result of applying a jQuery selector). jQuery.* could simply be thought of as global static objects, including (sometimes) functions that are accessible to anyone who has access to the jQuery object.
To initialize variation 2, I would do something like:
jQuery.variation2 = (function() {
var a = ...;
var b = ...; // other initialization
return {
something: function() {
...
}, ...
};
})();
You could use closures in similar ways to provide initialized code.

Access parent property inside object literal

We have a JS framework that lets us set up "modules". Each module is added by calling the addModule method and passing a literal object that contains required properties about the module as well as optional methods. Example:
framework.addModule({
id: "test-module",
init: function () {
//stuff to do when initializing like set up jQuery bindings
$("div").click(function () {
// need access to literal object so I can call:
something.utility1();
});
},
utility1: function () {
something.utility2();
},
utility2: function () {
// need access to literal object so I can call:
}
});
I'm trying to figure out the easiest way to make the object itself available to any code, at any level, inside the object (in place of "something").
The best I've been able to do is to add a this: this property to the object and then inside of methods I can put var module = this, which works but requires that variable to be added to each module. I'd like to see if there's another way that wouldn't require adding a variable to each method. Thanks.
Thanks for the comments and, zzzzBov, thanks for your suggestions.
However, it looks like the below code will work best for my needs. The devs on my team are writing a lot of these modules and I need the solution to be clear to them. Having to call $.proxy could make it less clear. I was hoping to avoid having to put var module = this in each method, so it would be cleaner, but it seems that it's not possible without it.
framework.addModule({
id: "test-module",
init: function () {
var module = this;
$("div").click(function () {
module.utility1();
});
},
utility1: function () {
var module = this;
module.utility2();
},
utility2: function () {
}
});
If anyone has a cleaner solution, let me know.
jQuery has a proxy method which will bind the function to a specific context. This would turn your event binding into:
$('div').click($.proxy(this, 'utility1'));
Alternatively, instead of using an object literal to instantiate the module object, you could instantiate an anonymous function:
framework.addModule(new function () {
this.id = 'test-module';
this.init = function () {
$('div').click($.proxy(this, 'utility1'));
};
this.utility1 = function () {
...more code...
};
this.utility2 = this.utility1;
});

access an extended object in javascript

I am having a bit of trouble creating an instance of useful things
from another JS file, I would like to change the properties of the
instance and use the methods. Or whatever you suggest if this is not
possible. This extends and this construct are confusing me.
(function($) {
$.extend({
usefulThings: new function() {
this.defaults = {
prop_path:'/la/lala',
//OTHER STUFF
};
this.construct = function(options) {
return this.each(function() {
var setting;
this.settings = {};
settings = $.extend(this.settings, $.usefulThings.defaults, options);
$this = $(this);
//OTHER STUFF
$.data(this, "usefulThings",settings);
// FIRST METHOD CALL
//OTHER STUFF
});
};
//SOME METHODS
}
});
$.fn.extend({
usefulThings: $.usefulThings.construct
});
})(jQuery);
I have seen usefulThings called from script blocks like so:
$("#myDivName").usefulThings({
prop_path: '/la/lala' //these seems to get overwritten in the above
});
First, have a look at MDN's introduction to the this keyword. And in the jQuery docs for .each.
Next, check out how does jquery chaining work? to understand the construct method.
Then, you should notice that the use of the new keyword is absolutely inappropriate in this case. The expression should be replaced by a simple object literal:
{
defaults: {
prop_path:'/la/lala',
// …
},
construct: function(options) {
…
},
//SOME METHODS
}
Now, the jQuery.extend. The relevant sentence from the docs is
If only one argument is supplied to $.extend(), this means the target argument was omitted. In this case, the jQuery object itself is assumed to be the target. By doing this, you can add new functions to the jQuery namespace. This can be useful for plugin authors wishing to add new methods to JQuery.
And it's the same for $.fn.extend (which actually is === $.extend), it extends the jQuery.fn object which is a shortcut for jQuery's prototype object.

understanding a modular javascript pattern

I'm trying to write 'better' javascript.
Below is one pattern I've found, and am trying to adopt. However, I'm slightly confused about its use.
Say, for example, I've got a page called "Jobs". Any JS functionality on that page would be encapsulated in something like:
window.jobs = (function(jobs, $, undefined){
return {
addNew: function(){
// job-adding code
}
}
})(window.jobs|| {}, jQuery);
$(function(){
$('.add_job').on('click', function(event){
event.preventDefault();
window.jobs.addNew();
});
});
As you can probably deduct, all I've done is replaced all the code that would have sat inside the anonymous event-handler function, with a call to a function in my global jobs object. I'm not sure why that's a good thing, other than it's reduced the possibility of variable collisions and made the whole thing a bit neater, but that's good enough for me.
The - probably fairly obvious - question is: all my event-binding init-type stuff is still sitting outside my shiny new jobs object: where should it be? Inside the jobs object? Inside the return object inside the jobs object? Inside an init() function?
I'm just trying to get a sense of a stable, basic framework for putting simple functionality in. I'm not building JS apps, I'd just like to write code that's a little more robust and maintainable than it is currently. Any and all suggestions are warmly welcomed :)
You can break down your application in whatever number of modules / objects you like too.
For instance, you can have another object / module which caches and defines all your DOM nodes and another one, which just handles any event. So for instance:
(function ( win, doc, $, undef ) {
win.myApp = win.myApp || { };
var eventHandler = {
onJobClick: function( event ) {
event.preventDefault();
myApp.addNew();
}
};
var nodes = (function() {
var rootNode = $( '.myRootNode' ),
addJob = rootNode.find( '.add_job' );
return {
rootNode: rootNode,
addJob: addJob
};
}());
$(function() {
myApp.nodes.addJob.on( 'click', myApp.handler.onJobClick );
});
myApp.nodes = nodes;
myApp.handler = eventHandler;
}( this, this.document, jQuery ));
It doesn't really matter how you create singletons in this (module) pattern, either as literal, constructor, Object.create() or whatnot. It needs to fit your requirements.
But you should try to create as many specific modules/objects as necesarry. Of course, if makes even more sense to separate those singletons / modules / objects into multiple javascript files and load them on demand and before you can say knife, you're in the world of modular programming patterns, dealing with requireJS and AMD or CommonJS modules.
Encapsulation-wise, you're fine: you could even just declare addNew in the jQuery closure and you'd still avoid the global scope. I think what you're getting at is more of implementing something close to an MVC architecture.
Something I like to do is create an object that you instantiate with a DOM element and that takes care of its own bindings/provides methods to access its controls etc.
Example:
// (pretend we're inside a closure already)
var myObj = function(args){
this.el = args.el; // just a selector, e.g. #myId
this.html = args.html;
this.bindings = args.bindings || {};
}
myObj.prototype.appendTo = function(elem){
elem.innerHTML += this.html;
this.bindControls();
};
myObj.prototype.remove = function(){
$(this.el).remove(); // using jQuery
};
myObj.prototype.bindControls = function(){
for(var i in this.bindings){ // event#selector : function
var boundFunc = function(e){ return this.bindings[i].call(this,e); };
$(this.el).on(i,boundFunc);
}
};
The way you are doing it right now is exactly how I do it also, I typically create the window objects inside the anonymous function itself and then declare inside that (in this case: jClass = window.jClass).
(function (jClass, $, undefined) {
/// <param name="$" type="jQuery" />
var VERSION = '1.31';
UPDATED_DATE = '7/20/2012';
// Private Namespace Variables
var _self = jClass; // internal self-reference
jClass = window.jClass; // (fix for intellisense)
$ = jQuery; // save rights to jQuery (also fixes vsdoc Intellisense)
// I init my namespace from inside itself
$(function () {
jClass.init('branchName');
});
jClass.init = function(branch) {
this._branch = branch;
this._globalFunctionality({ globalDatePicker: true });
this._jQueryValidateAdditions();
//put GLOBAL IMAGES to preload in the array
this._preloadImages( [''] );
this._log('*******************************************************');
this._log('jClass Loaded Successfully :: v' + VERSION + ' :: Last Updated: ' + UPDATED_DATE);
this._log('*******************************************************\n');
};
jClass._log = function() {
//NOTE: Global Log (cross browser Console.log - for Testing purposes)
//ENDNOTE
try { console.log.apply(console, arguments); }
catch (e) {
try { opera.postError.apply(opera, arguments); }
catch (e) { /* IE Currently shut OFF : alert(Array.prototype.join.call(arguments, ' '));*/ }
}
};
}(window.jClass= window.jClass|| {}, jQuery));
The reason I leave them completely anonymous like this, is that let's say in another file I want to add much more functionality to this jClass. I simply create another:
(function jClass, $, undefined) {
jClass.newFunction = function (params) {
// new stuff here
};
}(window.jClass = window.jClass || {}, jQuery))
As you can see I prefer the object.object notation, but you can use object literals object : object, it's up to you!
Either way by leaving all of this separate, and encapsulated without actual page logic makes it easier to have this within a globalJS file and every page on your site able to use it. Such as the example below.
jClass._log('log this text for me');
You don't want to intertwine model logic with your business logic, so your on the right path separating the two, and allowing for your global namespace/class/etc to be more flexible!
You can find here a comprehensive study on module pattern here: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html It covers all the aspects of block-scoped module approach. However in practice you gonna have quite a number files encapsulating you code, so the question is how to combine them property. AMD... multiple HTTP requests produced by every module loading will rather harm your page response time. So you can go with CommonJS compiled to a single JavaScript file suitable for in-browser use. Take a look how easy it is http://dsheiko.github.io/cjsc/

jQuery plugin design pattern (common practice?) for dealing with private functions [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I've been developing jQuery plugins for quite some time now, and I like to think I know how to design one well by now. One issue keeps nagging me though, and that is how to deal with private functions in a powerful yet elegant manner.
My plugins generally look something like this:
(function($) {
$.fn.myplugin = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'green');
...
};
$.fn.mypluginAnotherPublicMethod = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'red');
...
};
}(jQuery));
Now my question is: how to neatly DRY up that shared functionality? An obvious solution would be to put it in a function within the plugin's namespace:
var fill = function($obj, color) {
$obj.css('background-color', color);
};
Although this solution is effective and nicely namespaced, I really dislike it. For one simple reason: I have to pass it the jQuery object. I.e. I have to call it like this: fill(this, 'red');, while I would like to call it like this: this.fill('red');
Of course we could achieve this result by simply putting fill into jQuery.fn. But that feels very uncomfortable. Imagine having ten plugins developed based on this approach and each plugin putting five of those 'private' functions into the jQuery function namespace. It ends up in a big mess. We could mitigate by prefixing each of these functions with the name of the plugin they belong to, but that doesn't really make it more attractive. These functions are supposed to be private to the plugin, so we do not want to expose them to the outside world at all (at least not directly).
So there's my question: does anyone of you have suggestions for how to get the best of both worlds. That is; plugin code being able to call 'private' plugin functions in a way similar to this.fill('red') (or this.myplugin.fill('red') or even this.myplugin().fill('red') etc.), while preventing jQuery function namespace pollution. And of course it should be light-weight, as these private functions might be called very frequently.
UPDATE: Thanks for your suggestions.
I especially like David's idea of defining an object type that holds the 'private' functions and wraps a jQuery object. The only problem with it is that it still disallows me from chaining 'private' and 'public' functions. Which was big reason to want a syntax like this.fill('red') to begin with.
I ended up with a solution which I consider not tremendously elegant, but appealing to the 'best of both worlds' cause:
$.fn.chain = function(func) {
return func.apply(this, Array.prototype.slice.call(arguments, 1));
};
Which allows for constructs like:
this.
find('.acertainclass').
chain(fill, 'red').
click(function() {
alert("I'm red");
});
I cross-posted my question in other places, which also collected some interesting responses:
http://forum.jquery.com/topic/jquery-plugin-design-pattern-common-practice-for-dealing-with-private-functions
http://groups.google.com/group/jquery-en/browse_thread/thread/fa8ccef21ccc589a
One thing first: if you would like to call something like this.fill('red'); where this is an instance of jQuery, you have to extend the jQuery prototype and make fill() "public". jQuery provides guidelines for extending it's prototype using so called "plugins" that can be added using $.fn.fill, which is the same as jQuery.prototype.fill.
In jQuery callbacks, this is often a reference to the HTML Element, and you can't add prototypes to those (yet). That is one of the reason why jQuery wraps elements and return jQuery instances that can be easily extended.
Using the (function(){})(); syntax, you can create and execute "private" javascript on the fly, and it all disappears when it's done. Using this technique, you can create your own jQuery-like syntax that wraps jQuery into your own private chainable object.
(function(){
var P = function(elem) {
return new Private(elem);
};
var Private = function(elem) {
this.elem = jQuery(elem);
}
Private.prototype = {
elem: null,
fill: function(col) {
this.elem.css('background',col);
return this;
},
color: function(col) {
this.elem.css('color', col);
return this;
}
}
$.fn.myplugin = function() {
P(this).fill('red');
};
$.fn.myotherplugin = function() {
P(this).fill('yellow').color('green');
};
})();
$('.foo').myplugin();
$('.bar').myotherplugin();
console.log(typeof P === 'undefined') // should print 'true'
This way, the P stands for your own toolbox of "private" functions. They won't be available anywhere else in the code or in the jQuery namespace unless you attach them somewhere. You can add as many methods as you like in the Private object, and as long as you return this, you can also chain them jQuery-style as I did in the example.
How about (within the plugin's scope):
var fill = function ()
{
(function (color)
{
this.css ('backgrorund-color', color);
//.. your stuff here ...
}).apply (this, arguments);
}
$.fn.myplugin = function ()
{
fill ('green');
}
That way, fill will retain the jQuery context you're in, and is still private to your plugin
Amended: the above is incorrect w.r.t. scoping, Try the following instead:
var fill = function (color)
{
if (!$this) return; // break if not within correct context
$this.css ('backgrorund-color', color);
//.. your stuff here ...
}
$.fn.myplugin = function ()
{
var $this = $(this); // local ref to current context
fill ('green');
}
You might want to take a look at how the jQuery UI Widget Factory is implemented.
The basic approach is like this:
(function($){
$.fn.myplugin = function(method)
{
if (mp[method]) // map $('foo').myplugin('bar', 'baz') to mp.bar('baz')
{
return mp[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || ! method)
{
return mp.init.apply(this, arguments); // if called without arguments, init
}
else
{
$.error('Method ' + method + ' does not exist on $.myplugin');
}
};
// private methods, internally accessible via this.foo, this.bar
var foo = function() { … };
var bar = function() { … };
var private = { // alternative approach to private methods, accessible via this.private.foo
foo : function() { … },
bar : function() { … }
}
var mp = { // public methods, externally accessible via $.myplugin('foo', 'bar')
init : function( options )
{
return this.each(function()
{
// do init stuff
}
},
foo : function() { … },
bar : function() { … }
};
})(jQuery);
Unfortunately, "private" methods (or any property for that matter) can never be called with a "this" prefix in javascript. Anything which is called like this.myFunc(myArgs) must be publicly available.
And "private" methods can only be called from within the scope in which they were defined.
Your original solution is the only one that will work. Yes, it's a pain having to pass in this, but there's no more verbosity than there would be if your impossible request was possible:
this.fill('green');
//or
fill(this,'green');
As you can see, they both take up exactly the same number of characters in your code.
Sorry to say, but you're stuck with this as a solution, unless you want to create a new namespace and make them not private - which is simply going to add to the amount of code you need to write, i.e. what you indirectly called "not directly exposed":
this.myplugin.fill('green');
...is more verbose, thus kind of defeats the purpose.
Javascript is not like other languages, there are no "private" members per-se, only members accessible within closures, which can sometimes be used in a similar way to private members, but is more of a "workaround", and not the "real-deal" private members you are looking for.
It can be difficult to come to terms with this (I often struggle), but don't try to mould javascript into what you understand from other languages, take it for what it is...

Categories