I am having a lot of issues with jquery. I am managing an older application that used prototype. My new pages don't use prototype, but I am encapsulating things in jquery.noConflict just in case. This however is resulting in me being unable to share functions through different js files.
Order files are loaded:
jquery.js
jquery.commonFuncs.js
jquery.database.js
Example contents of files
commonFuncs.js
var someGlobalVar = "abc";
jQuery.noConflict()(function($){
function doStuff(x){
return x;
}
});
database.js
jQuery.noConflict()(function($){
var a = 123;
doStuff(a);
});
Error: doStuff is not defined.
I can kind of understand why encapsulating the function removes it from the global namespace. How can I add it back?
I also have no darn idea why I have to use noConflict if I do not load prototype.js If I completely remove prototype.js and remove the noConflict encapsulation, I get $ is undefined, and I don't know where to start with that. jQuery is clearly loading first. No clue.
As Madbreaks proposed, something like in the example below should work.
(Have a look in the web browser console to see that there's no error message.)
var someGlobalVar = "abc";
var myApp = {};
jQuery.noConflict()(function($){
function doStuff(x){
return x;
}
myApp.doStuff = doStuff;
});
jQuery.noConflict()(function($){
var a = 123;
//doStuff(a);
console.log(myApp.doStuff(a));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You can refactor your code like this:
var someGlobalVar = "abc";
var doStuff;
jQuery.noConflict()(function($){
doStuff = function(x){
return x;
}
});
Related
I have a bunch of extension methods of String and other JavaScript types, they now reside in global namespace.
What is the best practice to organize those extension methods? Should I encapsulate them inside a namespace? If yes, how to achieve that? Thanks!
Namespace your JavaScript if you need to refer to it elsewhere.
// define your global namespace
var Extensions = Extensions || {};
// add modules to it
Extensions.String = function() {
var myPrivateProperty = 2;
var myPublicProperty = 1;
var myPrivateFunction = function() {
console.log("myPrivateFunction()");
};
var myPublicExtension = function() {
// this extension is being called, now what?
console.log("myPublicExtension()");
};
// this object will be returned, giving access to public vars/methods
return {
myPublicProperty: myPublicProperty,
myPublicExtension : myPublicExtension
};
}();
console.log("Calling myPublicExtension()...");
Extensions.String.myPublicExtension();
Anonymously scope JavaScript if you’re never going to call it elsewhere.
// This will keep your namespace clean
(function() {
// here you can define your modules, functions, etc..
var x = 123;
console.log(x);
// to make something global you can define it like
window.globalVar = 5;
}());
Or you can extend the native javascript objects with prototype like this:
String.prototype.myExtension = function(p1, p2) {
// here is your function
return this + p1 + p2;
}
This way you don't need to define namespaces and you can call your extensions directly from any object you extended:
var otherString = "mystring".myExtension(" is", " great!");
console.log(otherString);// mystring is cool
you can do that with any object in javascript
EDIT:
Prototype extensions don't pollute global namespace, because they are accesible only through the object you extended.
If you have many extensions consider taking them into a file like extensions.js, then add it to your pages whenever you need those extensions. This way extensions.js can be cached by the browser and will be loaded faster
There are 2 ways of doing that:
Encapsulating in a namespace (I think the bare minimum to keep things tidy). A custom namespace ie:
window.MyNameSpace.trim = function(str) {
return str.replace(/^\s+|\s+$/g, "");
}
(replace MyNameSpace with a single letter! R for Raphael, L for Leaflet, etc)
Extend prototypes! Lots of people will disagree with that but I see no harm if it is your site and you don't override/conflict with anyone else code:
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, "");
};
I find this "cleaner" since you don't pass unnecessary arguments around... but again, it is a matter of opinion... This will work for any build-in type. The rest I think should follow #1
DISCLAIMER: Code from This post
Oh hi,
I saw some interesting posts about this subject but I think it's a really personal question that needs a customized answer. So I'm asking you what is the best way to organize my code for a Javascript plugin that need to be the more unobstructiv posible.
So my code looks like that :
var myApp = (function(){
//here are my global methods or variables
var self = this;
return {
method1:function(){}
method2:function(){}
method3:function(){}
}
})() || (myApp = {})
myApp.method1();
I execute the method1 that calls or use the entire code of my app.
I think i could add and onload event with addEventListener method to execute this method1, and i guess my code could have a better organisation.
I want to precise that my plugin is a bit small, like 200 lanes of javascript code, and it must be in Vanilla js. It's used on a single page in a website, no need to do a prototype class called with "new", in my opinion.
It really depends on your project and what you're trying to obtain.
There are several patterns that help you organize and maintain your code better.
I for one use a combination of patterns that I've made myself comfortable with among the years.
Here's my boilerplate for a module of my application :
;(function(global, udnefined){
var app = global.app || {},
moduleName = 'util',
module = app[moduleName] || {};
// "private" vars
var version = "1.2";
// fake "private" members (the udnerscore naming convention)
module._bindEventHandlers = function(){
// code here
// for chainability purposes
return this;
}
// "public" method
module.someMethod = function(){
// for chainability purposes
return this;
}
// "public" method
module.someOtherMethod = function(){
// for chainability purposes
return this;
}
// the init method
module.init = function(){
this
._bindEventHandlers()
.someMethod();
}
app[moduleName] = module;
global.app = app;
})(this);
And then, in your app (in the app initialization or whenever you actually need the module) you can simply call :
app.util.init();
app.util.someOtherMethod();
The provided module is highly reusable for creating new modules, because most modules should have an initialization logic (the init method), most of them would listen to some events (be it dom or custom events) - the _bindEventHandlers method - and it doesn't pollute the global namespace with variables (it just adds an object to the main app).
i use somthing the lines of this. all depenting on what i need to get done
(function(app, undefined){
var module = app.module = (function(){
var privatestuff
return {}
}())
var singelton = app.singleton = (function(){
var Module = function(){}
module.prototype.method1 = function(){}
return new Module()
}())
var ModulePrototype = app.ModulePrototype = function(){
var Module = function(){}
module.prototype.method1 = function(){}
return Module
}
}(myApp = window.myApp ||{}))
I failed to create a mini-library with some useful functions that I have found over the Internet, and I want to use them easily by just including a file to the HTML (like jQuery).
The problem is that some vars and functions share the same name and they are causing problems.
Is there a better solution to this instead of giving crazy names to the vars/funcs like "bbbb123" so the odds that someone is working with a "bbbb123" var is really low?
I would put all of your functions and variables into a single object for your library.
var MyLibrary = {
myFunc: function() {
//do stuff
},
myVar: "Foo"
}
There are a few different ways of defining 'classes' in JavaScript. Here is a nice page with 3 of them.
You should take one variable name in the global namespace that there are low odds of being used, and put everything else underneath it (in its own namespace).
For example, if I wanted to call my library AzureLib:
AzureLib = {
SortSomething: function(arr) {
// do some sorting
},
DoSomethingCool: function(item) {
// do something cool
}
};
// usage (in another JavaScript file or in an HTML <script> tag):
AzureLib.SortSomething(myArray);
Yes, you can create an object as a namespace. There are several ways to do this, syntax-wise, but the end result is approximately the same. Your object name should be the thing that no one else will have used.
var MyLibrary = {
myFunc: function() { /* stuff */ }
};
Just remember, it's object literal syntax, so you use label : value to put things inside it, and not var label = value;.
If you need to declare things first, use a wrapping function to enclose the environment and protect you from the global scope:
var MyLibrary = (function() {
var foo = 'bar';
return {
myFunc: function() { /* stuff */ }
};
})(); // execute this function right away to return your library object
You could put all of your library's functions inside of a single object. That way, as long as that object's name doesn't conflict, you will be good. Something like:
var yourLib = {};
yourLib.usefulFunction1 = function(){
..
};
yourLib.usefulFunction2 = function(){
..
};
i was exploring in the last few days how big frameworks works , how they assign their function name and it can't(?) be override , i pretty much know how framework work with anonymous function , for example they do it this way or similar version :
(function(){
var Sizzle = function (){
var x;
};
Sizzle.f = function(){
alert("!");
};
window.Sizzle = Sizzle;
})();
i still don't get few things about those huge frameworks and i hope i can find answer :
how do they assign function name and the name can't be override?
in the code above to call the function i need to write Sizzle.f() to get the function to work , but when i use jquery i don't write Jquery.show() , just show() , how do they vanish the "jquery" from "jquery.show()" function call?
by saying the name can't be override i mean , if i create function with one of the jquery functions names , the jquery function will work.
thanks in advance.
As has been shown for #2, it's really easy for BIG_NAMESPACE.Functions.doStuff to be added to anything you want.
var _ = BIG_NAMESPACE.Functions.doStuff;
_(); // runs BIG_NAMESPACE.Functions.doStuff;
As for #1:
Most libraries DO let their functions be overwritten.
It's the values that are inside of the framework's closure which are preserved, for safety reasons.
So you could do something like:
BIG_NAMESPACE.Functions.doStuff = function StealEverything() {};
(BIG_NAMESPACE.Functions.doStuff === StealEverything) // true;
But doStuff would have NO access to any of the variables hidden inside of the framework's closure.
It would also mean that until the page was reloaded, doStuff would also not work the way you want it to.
HOWEVER, in newer versions of JavaScript (ECMA5-compatible browsers), it WILL be possible to do something like what you're suggesting.
BIG_NAMESPACE = (function () {
var do_stuff = function () { console.log("doin' stuff"); },
functions = {
set doStuff (overwrite) { }
get doStuff () { return do_stuff; }
};
return { Functions : functions };
}());
Then, this will work:
BIG_NAMESPACE.Functions.doStuff(); // "doin' stuff"
BIG_NAMESPACE.Functions.doStuff = function () { console.log("ain't doin' jack"); };
BIG_NAMESPACE.Functions.doStuff(); // "doin' stuff"
However, Frameworks aren't going to use this for a LONG time.
This is not even remotely backwards compatible. Maybe in 2016...
There were defineGetter and defineSetter methods as well, but they aren't a formal part of the JavaScript language. Like innerHTML, they're things that the browser vendors put in, to make life better... ...as such, there's no real guarantee that they're going to be in any/all browsers your users have. Plus, they're deprecated, now that new browsers use the get and set constructs that other languages have.
(function(){
var jqueree = {};
jqueree.someval = 22;
jqueree.somefunc = function(){ alert(this.someval); };
window.jqueree = jqueree;
window.somefunc = function(){ jqueree.somefunc.call(jqueree); };
window.$$$ = jqueree;
})();
// all equivalent
window.somefunc();
window.jqueree.somefunc();
$$$.somefunc();
somefunc();
Answering your Questions
At the top of jQuery you'll see: var jQuery = (function() {, which creates the local function (its incomplete; the }); occurs elsewhere).
At the very end of jQuery you'll notice the following, which is how it attaches it to the global namespace:
// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;
I have never seen a jQuery function called without referencing the jQuery object. I think you always need to use jQuery.show() or $.show(); however maybe you're saying you don't have to call window.jQuery.show(), which you are permitted to drop the window, since that is the default.
Using your example
(function(){
/* This is where Sizzle is defined locally, but not exposed globally */
var Sizzle = function (){
var x;
};
/* If you put "window.f = Sizzle.f = function(){" then you could *
* call f() w/o typing Sizzle.f() */
Sizzle.f = function(){
alert("!");
};
/* The following line is what makes it so you can use Sizzle elsewhere *
* on your page (it exposes it globally here) */
window.Sizzle = Sizzle;
})();
use function _name_() {} and the name is static
the simply use var $ = jQuery; to create an alias.
jQuery works this way:
Supposed you have this jQuery code:
$("#title").show();
You have three elements to that line.
$ is a javascript function
"#title" is an argument to that function
.show() is a method call
Here's how it works.
Javascript executes the function named $ and passed it an argument of "#title".
That function does it's business, finds the #title object in the DOM, creates a jQuery object, puts that DOM element into the array in the jQuery object and returns the jQuery object.
The Javascript execution engine then takes the return value from that function call (which is now a jQuery object) and looks for and executes the .show() method on that object.
The .show() method then looks at the array of DOM elements in the jQuery object and does the show operation for each DOM element.
In answer to your question, there is no .show() all by itself. It's a method on a jQuery object and, in this example, that jQuery object is returned from the $("#title") function call.
Is the following method wrong way of declaring namespace in Javascript? It is from the book I'm reading and doesn't seem to work in my code.
<script type="text/javascript">
var mynamespace = {};
if(Drupal.jsEnabled){
$(document).ready(mynamespace.init);
}
mynamespace.init = function() {
$("#mybutton").bind("click",function(){
alert('hello');
});
}
</script>
It looks like your code is dependent on jQuery. Make sure that is loaded before you run this script. Also, define your function before it gets called. Try this:
var mynamespace = {};
mynamespace.init = function() {
$("#mybutton").bind("click",function(){
alert('hello');
});
}
if(Drupal.jsEnabled){
$(document).ready(mynamespace.init);
}
What seems to be going wrong here is that the mynamespace.init function isn't defined at the time you are hooking it up to $(document).ready.
This should work as expected:
<script type="text/javascript">
var mynamespace = {};
mynamespace.init = function() {
$("#mybutton").bind("click",function(){
alert('hello');
});
}
if(Drupal.jsEnabled){
$(document).ready(mynamespace.init);
}
</script>
You may also consider forming it like this, as it is easier to understand (at least to me anyhow)
<script type="text/javascript">
var mynamespace = {
init : function() {
$("#mybutton").bind("click",function(){
alert('hello');
})
};
if(Drupal.jsEnabled){
$(document).ready(mynamespace.init);
}
</script>
Be careful using $(document).ready(mynamespace.init);. When executed in this way, this is no longer a reference to mynamespace, normally it would be equal to window, but jQuery do some call magic in the background to set it equal to document. It won't hurt you in this instance, but be wary of it in the future.
$(document).ready(function () {
mynamespace.init();
});
Is how I would do it.
In this case, the reason your code isn't working is that the init method of mynamespace isn't defined at the document $(document).ready(mynamespace.init) is called.
What strikes me as odd, at least working mostly in C#, is that a namespace should not directly contain code logic. In C# it can't, that is what classes are for. So for me, having an init function on a namespace is a contradiction.
Yes, you can use object as a namespace. Another way to form a namespace is to use closures:
(function(inner_variable_1, inner_variable_2) {
// define whatever here, they won't pollute namespace outside this closure
})(outer_variable_1, outer_variable_2);
Popular example is jQuery's noconflict-mode, which enables you to use $ variable in your jQuery code without making $ a global variable, thus leaving the global $ for another use.