jQuery like custom functions - javascript

I have been wondering how I can create functions like jQuery. For example: $(ID).function()
Where ID is the id of an HTML element, $ is a function that return the document.getElementById reference of the element "ID" and function is a custom javascript function.
I'm creating a little library which implements some functions. And I want to use that sintax without using jQuery.
Now, my questions are: how I can implement that? What is the name of the tecnique that allow that?
Edit:
What I want to do is this:
HTMLElement.prototype.alertMe = function() {alert(this.value);}
Then, when I call document.getElementById('html_input_id').alertMe(), it must show an alertbox with the input value. But HTMLElement.prototype doesn't work in IE.

$ = function(id) {
return document.getElementById(id);
}

Okay, look, what you're asking has a lot of details and implications. The code for jQuery is open source, you can read it for the details; you'd do well to find a good Javascript book as well, the the O'Reilly Definitive Guide.
$ is just a character for names in JS, so as some of the other answers have shown, there's no reason you can't just write a function with that name:
var $ = function(args){...}
Since everyone and his brother uses that trick, you want to have a longer name as well, so you can mix things.
var EstebansLibrary = function(args){...}
var $ = EstebansLibrary; // make an alias
Since you end up doing different things with the entry point function, you need to know how JS uses arguments -- look up the arguments object.
You'll want to package this so that your internals don't pollute the namespace; you'll want some variant of the module pattern, which will make it something like
var EstebansLibrary = (function(){
// process the arguments object
// do stuff
return {
opname : implementation,...
}
})();
And you'll eventually want to be prepared for inheritance and that means putting those functions into the prototype object.

You can use prototype to assign a new function to the Element prototype.
Element.prototype.testFunction=function(str){alert(str)};
This would provide the function 'testFunction' to all HTML elements.
You can extend any base Object this way, i.e. Array, String etc.
This will work without any plugin at all - although that said I don't think it will work in IE. I believe libraries such as MooTools and jQquery create their own inheritance with DOM elements to ensure cross-browser compatibility, although don't quote me on that.

Related

How to add Javascript function to every object?

I'm wondering how can I attach a function to be available for each object on the page. I know that I can do it like this:
mything = {
init: function(SELECTOR){
},
destroy: function(){
}
};
But then it is available to me only this way: mything.init(SELECTOR);
What I want is to be able to do the same thing this way:
$('.mydiv, input, whatever').myFunction({ 'my' : 'arg', 'my2' : 'arg2' });
$('.mydiv').myFunction('destroy');
I know that there are plenty of Javascript tutorials out there but I don't know how to search for this type of functionality. Any help would be appreciated!
In your case, it looks like it is just enough for you to extend the jQuery.prototype.
jQuery.extend( jQuery.fn, mything );
However, it is of course possible, even if not very recommendable, to go that ultimate root and extend the Object.prototype. This really would add those functions to every and each object.
This isn't necessarily a great idea (it's a terrible idea), but you can accomplish this with prototypes:
Object.prototype.myFunction = function() {
console.log('Called myFunction');
};
And you can see what happens for an arbitrary object:
document.myFunction();
Note that adding to the prototypes of classes other than your own (and especially the builtin objects or classes belonging to libraries other than your own) can induce lots of confusion. This is one of the reasons why Google's own style guide recommends against this (despite much temptation to add String.startsWith, String.endsWith, and many other useful operations to builtin types).
The clean way to do what you describe is to wrap your code inside a jQuery plugin.
Here is the official jquery plugin guide. Read through it, it is actually quite simple to understand.
The part about wrapping functions (so that $(selector).myFunction() calls init, $(selector).myFunction('doThis') calls doThis, etc...) is here.

Keeping your javascript structured and tidy (as an OO programmer)

I've recently been playing with javascript, HTML5, chrome extensions, jQuery, and all that good stuff. I'm pretty impressed so far with the possibilities of javascript, the only thing I struggle with is structuring my code and keeping it tidy. Before I know it, functions are scattered all over the place. I've always done my programming in an object oriented manner (C++ and C#), and I find myself not being able to keep things tidy. It feels like I always end up with a bunch of static util functions, were I to 'think' in C#.
I've been looking for some information on objects in javascript, but it seems to come down to wrapping functions in functions. Is this a good way of structuring your codebase? On the surface it seems a bit hackish. Or are there other ways of keeping things tidy for an OO mindset?
One important aspect to remember about Javascript is that it is a prototypical language. Functions can be objects, and anything can be put on the object, often affecting related objects in the process. There's no official way to 'extend' an object because of this. It's a concept that I still have a hard time understanding.
Javascript 'acts' like any other OOP language for the most part, with some exceptions, namely extending objects (http://jsweeneydev.net84.net/blog/Javascript_Prototype.html).
After extensive research, I did find a very, very light-weight way to simulate expanding objects (I'm using using it in my GameAPI). The first field is the parent object, the second is the object that expands.
extend : function(SuperFunction, SubFunction) {
//'Extends' an object
SubFunction.prototype = new SuperFunction();
SubFunction.prototype.constructor = SubFunction;
},
This link might clear up some problems and misconceptions:
http://www.coolpage.com/developer/javascript/Correct%20OOP%20for%20Javascript.html
Personally, I tend to be anti-framework, and I haven't seen a framework yet that doesn't force the programmer to significantly change their programming style in this regard anyway. More power to you if you find one, but chances are you won't really need one.
My best advise is to try to adapt to Javascript's prototypical style, rather than force old methodologies on it. I know it's tricky; I'm still trying to myself.
Best of luck diggingforfire.
I generally follow the make-an-anonymous-function-then-call-it pattern. Basically, you create an inner scope and return a single object containing your interface. Nothing else escapes, because it's all trapped within the function scope. Here's an example using jQuery:
var FancyWidget = (function($) {
// jQuery is passed as an argument, not referred to directly
// So it can work with other frameworks that also use $
// Utility functions, constants etc can be written here
// they won't escape the enclosing scope unless you say so
function message(thing) {
alert("Fancy widget says: " + thing);
}
// Make a simple class encapsulating your widget
function FancyWidget(container) {
container = $(container); // Wrap the container in a jQuery object
this.container = container; // Store it as an attribute
var thisObj = this;
container.find("#clickme").click(function() {
// Inside the event handler, "this" refers to the element
// being clicked, not your FancyWidget -- so we need to
// refer to thisObj instead
thisObj.handleClick();
});
}
// Add methods to your widget
FancyWidget.prototype.handleClick = function() {
this.container.find("#textbox").text("You clicked me!");
message("Hello!");
};
return FancyWidget; // Return your widget class
// Note that this is the only thing that escapes;
// Everything else is inaccessible
})(jQuery);
Now, after all this code executes, you end up with one class, FancyWidget, which you can then instantiate.
You can define multiple classes this way too; instead of using return FancyWidget, you can return an object literal instead:
return {
FancyWidget: FancyWidget,
Frobnicator: Frobnicator,
// Nested namespaces!
extra: {
thing: thing,
blah: blah
}
};
One of the best OOP javascript libraries out there is Google's Closure library http://closure-library.googlecode.com/svn/docs/index.html
It's structured in a way that OOP programmers will be familiar with especially if you come from a java/C# background. Have a look at the source code of any file and it should feel right at home as an OOP programmer. http://closure-library.googlecode.com/svn/docs/closure_goog_graphics_canvasgraphics.js.source.html
I have never used this personally, but have seen backbone.js referenced many times to this question. See at: http://documentcloud.github.com/backbone/
Using some framework designed to meet similar requirements may be a good idea.
But there are some things you should really follow to be efficient:
remember about closures in JavaScript and do not forget about var keyword,
use callbacks where possible and reasonable, JavaScript is asynchronous by nature,

Please explain these lines in the jQuery-ui project - has to do with adding "sub-plugins"

Lines 10 - 16 of jquery.effects.core.js:
;jQuery.effects || (function($, undefined) {
var backCompat = $.uiBackCompat !== false; // Irrelevant
$.effects = {
effect: {}
};
})(jQuery); // At end of file
As I understand it, this adds an effects "namespace", but only if it doesn't already exist.
Can someone explain to me:
What is the initial semi-colon for?
What is the purpose of the undefined parameter? Is the meaning of undefined overridden in some way?
What's the difference between adding a function directly to the jQuery object, and adding one to jQuery.fn as recommended in the jQuery documentation?
Finally, if I wanted to create a bunch of jQuery plugins that would only be used by my own team, would it make sense to lump them all under a company namespace using something like the code above?
Edit: I realize now jQuery.effects is probably a bad example. I see jQuery.ui.core.js does it differently:
(function( $, undefined ) {
$.ui = $.ui || {};
// add some stuff to $.ui here
$.fn.extend({
// plugins go here
});
})(jQuery);
But what is the use of the ui object if plugins are added directly to $.fn anyway? Could I define my namespace under $.fn and add all my plugins to $.fn.acme, so that I use them like so: $('something').acme.doStuff()?
Is there a best practice for this sort of thing?
It checks if jQuery.effects exists
If not, it defines a function and calls in the same time
(function() { ... } (jquery), it passes jQuery object for reasons related to scope and conflict and such.
The first line in that function is said to be irrelevant, it seems to be checking a presence of a jQuery plugin property
It defines a placeholder (like namespace or container class) for the effects jQuery plugin property.
So, to your questions:
1 . What is the initial semi-colon for?
I think nothing special. Just ensuring clean statement. This has some edge cases if the last line before this one was a function declaration close.
2 . What is the purpose of the undefined parameter? Is the meaning of undefined overridden in some way?
It just ensures this doesn't happen later. Passes the global object directly. Common pattern I think.
3 . What's the difference between adding a function directly to the jQuery object, and adding one to jQuery.fn as recommended in the jQuery documentation?
It's the way jQuery is structured and general organization issue. The jQuery object is a function and returns an object. The .fn handles registering this one to apply on returned jQuery objects (from jQuery select or so), so, that's better so that jQuery actually knows about your added function.
4 . Finally, if I wanted to create a bunch of jQuery plugins that would only be used by my own team, would it make sense to lump them all under a company namespace using something like the code above?
Most people don't do it. Wouldn't recommend it. Maybe a common "small" prefix is enough.

What does JS $ mean?

I don't grok the idea/purpose/use of Javascript $, as in
function $(id) {
return document.getElementById(id);
}
Could someone please explain or point me at an explanation?
Thanks!
-- Pete
When you see JavaScript code that involves lots of $(foo) function calls, it's probably using either the jQuery or the Prototype web development frameworks. It's just an identifier; unlike a lot of other languages, identifiers (function and variable names) can include and start with "$".
In your code it is the name of a function.
function $(id) { return document.getElementById(id); }
$("my_id")
function myfunc(id) { return document.getElementById(id); }
myfunc("my_id")
Two functions, two different identifiers.
Most commonly this is used by JQuery - specifically, JQuery creates an object with a reference of $ which has various methods to simplify page manipulation.
It's technically possible for anything to attach a class to $
It's just the name of a function called $(). The dollar sign ($) is a valid character for identifiers in JavaScript. jQuery, for example, uses it as a shorthand alias for the jQuery() function.
There are two main reasons to use $ as a function name, especially in frameworks like jQuery:
It's short but distinctive - you're going to use it all over the place, so you don't want it to take up too much space.
When used as a DOM element selector, the function and its parameters together kind of look like a Perl/PHP/Java properties variable - and it kind of works like that as well, since the main purpose is to do something with the selected DOM elements.

Any difference between a $ wrap function and getElementById?

I mean a wrap function like this:
function $(id) { return document.getElementById(id); }
but in some code like this:
oDiv1 = $("postInfoDiv");
oDiv2 = document.getElementById("postInfoDiv");
alert(oDiv1 == oDiv2); // return false
alert(oDiv1.style); // error
alert(oDiv2.style); // correct
alert(document.getElementById("postInfoDiv").style); // correct
I got strange results as the comments imply.
I thought the first alert should return the true since they are the same dom object.
I thought the second alert should alert something like "object" or "CSS StyleDeclaration" but not "defined".
So what are the problems? Have you ever met this kind of problems?
thanks.
Your $ function is probably being overridden, potentially by a framework.
You should try doing alert( oDiv1.nodeType ) to see if it's a DOM element. alert( oDiv1.length ) to see if it's an empty array because you may be using jQuery on the same page which overrides your $ function.
oDiv1 may be an array-like object containing that item if jQuery is included. oDiv2 is an actual DOM reference. You probably need to compare oDiv1[0] to oDiv1, in which you reference the first element in the array which points to the actual dom element to make a fair comparison.
function $(id){return document.getElementById(id)}
$('content') == document.getElementById('content')
true
The custom $ function will work perfectly but if you're using a framework function it will return that array-like object instead of the DOM element.
You can also rename your function to something like function getID which would be unique and not conflict with framework $s.
My main concern with this is that it will confuse the heck out of someone the first time they read your code, especially if they are used to coding with a JavaScript framework such as jQuery.
For this reason alone I recommend you do not use this particular syntax for your wrap function.
BTW note that even when jQuery is not loaded, Firebug provides its own $ function, which may participate to confusion.

Categories

Resources