Interface Segregation Principle in jQuery - javascript

Anyone able to give a good illustration of how this works in jQuery?
Specifically with regards to the answer from here.
It sounds the same as Single Responsibility Principle (SRP) for OOP? How is it different?

I feel more comfortable with answering my own question now.
With Single Responsibility Principle, I'm thinking mainly of objects created like in a game. That object should be responsible only for itself, in terms of internal functions/methods.
As for Interface Segregation, I'm thinking more of avoiding anonymous function calls, and segregating a large chunk of code... to different named calls. This was well explained by Paul Irish in jQuery Anti-Patterns for performance.
Instead of anonymous functions bound everywhere like
$(function() {
//do stuff related to setup menu
//add facebook, twitter widgets
//more anonymous actions....
}):
Segregation into a well defined interface might look something like the below:
var homepage = (function() {
function setupMenu() {
//do stuff related to setup menu
}
function setupSocial() {
//add facebook, twitter widgets
}
return {
setupMenu:setupMenu,
setupSocial:setupSocial
}
})();
$(function() {
homepage.setupMenu();
homepage.setupSocial();
})

Related

Javascript local scopes and using objects - best practice?

I am currently working on large projects that make use of lots of javascript files.
I then start learning of using local scopes and using objects.
What I do not really understand is how to call them into you local scope?
E.g if I create an object in an local scope in file-a, how can I use them as in a function in the document.ready scope file-b?
I get that you can find this online, but I get demotivation by the high amount of javascript on the internet and can't really find good examples or material. Any help?
Not sure,but I think you might be referring to the use of namespaces within JavaScript as a way to avoid adding all your functions to the main window object.
The Ugly Way
Let's assume you have 3 functions related to cats:
Function AddCat(cat) {
}
Function DeleteCat(catId) {
}
Function BreedCat(cat,cat) {
}
The way these items are coded, they are globally available. Not only does that clutter up your window object, it's hard to share data between these functions in a discreet way.
As long as this js file is loaded, any function in your app can call these functions just by calling AddCat()
Cleaner
To solve that problem, we could create a Cats object that acts as a "namespace" here:
Cats = {
AddCat: function(cat) {
},
DeleteCat: function(catId) {
},
BreedCat: function(cat,cat) {
}
}
Now, you've only added ONE object to the windows class: Cats. In addition, other methods in your web app can call any of those 3 items by calling Cats.AddCat() for example.
This lets you encapsulate all of the Cat data in your entire system within a single "namespace, so it's easier to read.
This can get a lot more detailed. By encapsulating items like this, you can start to hide variables that all your cat routines require from the rest of your code.
There is an excellent set of resources on this type of namespacing (including tons of detail) here and here with links that lead you deeper.
Is that what you were looking for?

Best way to organize jQuery/JavaScript code (2013) [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
The Problem
This answer has been answered before but are old and not up to date. I have over 2000 lines of code in a single file, and as we all know this is bad practice, especially when i'm looking through code or adding new features. I want to better organize my code, for now and for the future.
I should mention that I'm building a tool (not a simple website) with lots of buttons, UI elements, drag, drops, action listeners/handlers and function in the global scope where several listeners may use the same function.
Example code
$('#button1').on('click', function(e){
// Determined action.
update_html();
});
... // Around 75 more of this
function update_html(){ .... }
...
More example code
Conclusion
I really need to organize this code for best use and not to repeat myself and be able to add new features and update old ones. I will be working on this by myself. Some selectors can be 100 lines of code others are 1. I have looked a bit at require.js and found it kinda repetitive, and actually writing more code than needed . I'm open to any possible solution that fit this criteria and link to resource / examples are always a plus.
Thanks.
I'll go over some simple things that may, or may not, help you. Some might be obvious, some might be extremely arcane.
Step 1: Compartmentalize your code
Separating your code into multiple, modular units is a very good first step. Round up what works "together" and put them in their own little encased unit. don't worry about the format for now, keep it inline. The structure is a later point.
So, suppose you have a page like this:
It would make sense to compartmentalize so that all the header-related event handlers/binders are in there, for ease of maintenance (and not having to sift through 1000 lines).
You can then use a tool such as Grunt to re-build your JS back to a single unit.
Step 1a: Dependency management
Use a library such as RequireJS or CommonJS to implement something called AMD. Asynchronous Module Loading allows you to explicitely state what your code depends on, which then allows you to offload the library-calling to the code. You can just literally say "This needs jQuery" and the AMD will load it, and execute your code when jQuery is available.
This also has a hidden gem: the library loading will be done the second the DOM is ready, not before. This no longer halts load-up of your page!
Step 2: Modularize
See the wireframe? I have two ad units. They'll most likely have shared event listeners.
Your task in this step is to identify the points of repetition in your code and to try to synthesise all this into modules. Modules, right now, will encompass everything. We'll split stuff as we go along.
The whole idea of this step is to go from step 1 and delete all the copy-pastas, to replace them with units that are loosely coupled. So, instead of having:
ad_unit1.js
$("#au1").click(function() { ... });
ad_unit2.js
$("#au2").click(function() { ... });
I will have:
ad_unit.js:
var AdUnit = function(elem) {
this.element = elem || new jQuery();
}
AdUnit.prototype.bindEvents = function() {
... Events go here
}
page.js:
var AUs = new AdUnit($("#au1,#au2"));
AUs.bindEvents();
Which allows you to compartmentalize between your events and your markup in addition to getting rid of repetition. This is a pretty decent step and we'll extend this further later on.
Step 3: Pick a framework!
If you'd like to modularize and reduce repetitions even further, there are a bunch of awesome frameworks around that implement MVC (Model - View - Controller) approaches. My favourite is Backbone/Spine, however, there's also Angular, Yii, ... The list goes on.
A Model represents your data.
A View represents your mark-up and all the events associated to it
A Controller represents your business logic - in other words, the controller tells the page what views to load and what models to use.
This will be a significant learning step, but the prize is worth it: it favours clean, modular code over spaghetti.
There are plenty of other things you can do, those are just guidelines and ideas.
Code-specific changes
Here are some specific improvements to your code:
$('.new_layer').click(function(){
dialog("Create new layer","Enter your layer name","_input", {
'OK' : function(){
var reply = $('.dialog_input').val();
if( reply != null && reply != "" ){
var name = "ln_"+reply.split(' ').join('_');
var parent = "";
if(selected_folder != "" ){
parent = selected_folder+" .content";
}
$R.find(".layer").clone()
.addClass(name).html(reply)
.appendTo("#layer_groups "+parent);
$R.find(".layers_group").clone()
.addClass(name).appendTo('#canvas '+selected_folder);
}
}
});
});
This is better written as:
$("body").on("click",".new_layer", function() {
dialog("Create new layer", "Enter your layer name", "_input", {
OK: function() {
// There must be a way to get the input from here using this, if it is a standard library. If you wrote your own, make the value retrievable using something other than a class selector (horrible performance + scoping +multiple instance issues)
// This is where the view comes into play. Instead of cloning, bind the rendering into a JS prototype, and instantiate it. It means that you only have to modify stuff in one place, you don't risk cloning events with it, and you can test your Layer stand-alone
var newLayer = new Layer();
newLayer
.setName(name)
.bindToGroup(parent);
}
});
});
Earlier in your code:
window.Layer = function() {
this.instance = $("<div>");
// Markup generated here
};
window.Layer.prototype = {
setName: function(newName) {
},
bindToGroup: function(parentNode) {
}
}
Suddenly, you have a way to create a standard layer from anywhere in your code without copy pasting. You're doing this in five different places. I've just saved you five copy-pastes.
One more:
// Ruleset wrapper for actions
var PageElements = function(ruleSet) {
ruleSet = ruleSet || [];
this.rules = [];
for (var i = 0; i < ruleSet.length; i++) {
if (ruleSet[i].target && ruleSet[i].action) {
this.rules.push(ruleSet[i]);
}
}
}
PageElements.prototype.run = function(elem) {
for (var i = 0; i < this.rules.length; i++) {
this.rules[i].action.apply(elem.find(this.rules.target));
}
}
var GlobalRules = new PageElements([
{
"target": ".draggable",
"action": function() { this.draggable({
cancel: "div#scrolling, .content",
containment: "document"
});
}
},
{
"target" :".resizable",
"action": function() {
this.resizable({
handles: "all",
zIndex: 0,
containment: "document"
});
}
}
]);
GlobalRules.run($("body"));
// If you need to add elements later on, you can just call GlobalRules.run(yourNewElement);
This is a very potent way to register rules if you have events that are not standard, or creation events. This is also seriously kick-ass when combined with a pub/sub notification system and when bound to an event you fire whenever you create elements. Fire'n'forget modular event binding!
Here is a simple way to split your current codebase into multiple files, using require.js.
I will show you how to split your code into two files. Adding more files will be straightforward after that.
Step 1) At the top of your code, create an App object (or whatever name you prefer, like MyGame):
var App = {}
Step 2) Convert all of your top-level variables and functions to belong to the App object.
Instead of:
var selected_layer = "";
You want:
App.selected_layer = "";
Instead of:
function getModified(){
...
}
You want:
App.getModified = function() {
}
Note that at this point your code will not work until you finish the next step.
Step 3) Convert all global variable and function references to go through App.
Change stuff like:
selected_layer = "."+classes[1];
to:
App.selected_layer = "."+classes[1];
and:
getModified()
to:
App.GetModified()
Step 4) Test Your code at this stage -- it should all work. You will probably get a few errors at first because you missed something, so fix those before moving on.
Step 5) Set up requirejs. I assume you have a web page, served from a web server, whose code is in:
www/page.html
and jquery in
www/js/jquery.js
If these paths are not exactly like this the below will not work and you'll have to modify the paths.
Download requirejs and put require.js in your www/js directory.
in your page.html, delete all script tags and insert a script tag like:
<script data-main="js/main" src="js/require.js"></script>
create www/js/main.js with content:
require.config({
"shim": {
'jquery': { exports: '$' }
}
})
require(['jquery', 'app']);
then put all the code you just fixed up in Steps 1-3 (whose only global variable should be App) in:
www/js/app.js
At the very top of that file, put:
require(['jquery'], function($) {
At the bottom put:
})
Then load page.html in your browser. Your app should work!
Step 6) Create another file
Here is where your work pays off, you can do this over and over.
Pull out some code from www/js/app.js that references $ and App.
e.g.
$('a').click(function() { App.foo() }
Put it in www/js/foo.js
At the very top of that file, put:
require(['jquery', 'app'], function($, App) {
At the bottom put:
})
Then change the last line of www/js/main.js to:
require(['jquery', 'app', 'foo']);
That's it! Do this every time you want to put code in its own file!
For your question and comments I'll assume you are not willing to port your code to a framework like Backbone, or use a loader library like Require. You just want a better way to orgainze the code that you already have, in the simplest way possible.
I understand it is annoying to scroll through 2000+ lines of code to find the section that you want to work on. The solution is to split your code in different files, one for each functionality. For example sidebar.js, canvas.js etc. Then you can join them together for production using Grunt, together with Usemin you can have something like this:
In your html:
<!-- build:js scripts/app.js -->
<script src="scripts/sidebar.js"></script>
<script src="scripts/canvas.js"></script>
<!-- endbuild -->
In your Gruntfile:
useminPrepare: {
html: 'app/index.html',
options: {
dest: 'dist'
}
},
usemin: {
html: ['dist/{,*/}*.html'],
css: ['dist/styles/{,*/}*.css'],
options: {
dirs: ['dist']
}
}
If you want to use Yeoman it will give you a boilerplate code for all this.
Then for each file itself, you need to make sure you follow best practices and that all the code and variables are all in that file, and don't depend on other files. This doesn't mean you can't call functions of one file from other, the point is to have variables and functions encapsulated. Something similar to namespacing. I'll assume you don't want to port all your code to be Object Oriented, but if you don't mind refactoring a bit, I'd recommend to add something equivalent with what is called a Module pattern. It looks something like this:
sidebar.js
var Sidebar = (function(){
// functions and vars here are private
var init = function(){
$("#sidebar #sortable").sortable({
forceHelperSize: true,
forcePlaceholderSize: true,
revert: true,
revert: 150,
placeholder: "highlight panel",
axis: "y",
tolerance: "pointer",
cancel: ".content"
}).disableSelection();
}
return {
// here your can put your "public" functions
init : init
}
})();
Then you can load this bit of code like this:
$(document).ready(function(){
Sidebar.init();
...
This will allow you to have a much more maintainable code without having to rewrite your code too much.
Use javascript MVC Framework in order to organize the javascript code in a standard way.
Best JavaScript MVC frameworks available are:
Backbone
Angular
CanJS
Ember
ReactJS
Selecting a JavaScript MVC framework required so many factors to consider. Read the following comparison article that will help you to select best framework based on the factors important for your project:
http://sporto.github.io/blog/2013/04/12/comparison-angular-backbone-can-ember/
You can also use RequireJS with the framework to support Asynchrounous js file & module loading.
Look the below to get started on JS Module loading:
http://www.sitepoint.com/understanding-requirejs-for-effective-javascript-module-loading/
Categorize your code. This method is helping me a lot and does work with any js framework:
(function(){//HEADER: menu
//your code for your header
})();
(function(){//HEADER: location bar
//your code for your location
})();
(function(){//FOOTER
//your code for your footer
})();
(function(){//PANEL: interactive links. e.g:
var crr = null;
$('::section.panel a').addEvent('click', function(E){
if ( crr) {
crr.hide();
}
crr = this.show();
});
})();
In your preferred editor (the best is Komodo Edit) you may fold in by collapsing all entries and you will see only the titles:
(function(){//HEADER: menu_____________________________________
(function(){//HEADER: location bar_____________________________
(function(){//FOOTER___________________________________________
(function(){//PANEL: interactive links. e.g:___________________
I would suggest:
publisher/subscriber pattern for event management.
object orientation
namespacing
In your case Jessica, divide the interface into pages or screens. Pages or screens can be objects and extended from some parent classes. Manage the interactions among pages with a PageManager class.
I suggest that you use something like Backbone. Backbone is a RESTFUL supported javascript library. Ik makes your code cleaner and more readable and is powerful when used together with requirejs.
http://backbonejs.org/
http://requirejs.org/
Backbone isn't a real library. It is meant to give structure to your javascript code. It is able to include other libraries like jquery, jquery-ui, google-maps etc. Backbone is in my opinion the closest javascript approach to Object Oriented and Model View Controller structures.
Also regarding your workflow.. If you build your applications in PHP use the Laravel library. It'll work flawlessly with Backbone when used with the RESTfull principle. Below the link to Laravel Framework and a tutorial about building RESTfull APIs:
http://maxoffsky.com/code-blog/building-restful-api-in-laravel-start-here/
http://laravel.com/
Below is a tutorial from nettuts. Nettuts has a lot of High Quality tutorials:
http://net.tutsplus.com/tutorials/javascript-ajax/understanding-backbone-js-and-the-server/
Maybe its time for you start implementing a whole development workflow using such tools as yeoman http://yeoman.io/. This will help control all your dependencies, build process and if you wanted, automated testing. Its a lot of work to start with but once implemented will make future changes a lot easier.

Best way to organize a javascript application

I have been trying out some different ways to organize my code in my javascript applications and i wonder which one is the most appropriate.
First example:
var Application = {
init: function() {
//Some code
Calculate();
},
Calculate: function() {
//Some code
}
};
Second example:
(function() {
function init() {
//Some code
Calculate();
}
function Calculate() {
//Some code
}
})();
Third example:
(function() {
var init = function() {
//Some code
Calculate();
};
var Calculate = function() {
//Some code
};
})();
Or is it some other way that is preferred? I get very confused over this. Thanks in advance!
The answer is, without question, "it depends." How big is your application? Do you need all of the modules all of the time? How scalable and reusable does your app need to be? These are not JavaScript questions specifically, but rather "architectural" questions, and while learning JavaScript basics is relatively easy, it takes a lot of years to learn to be a good architect in software development. (though it is excellent that you are asking these questions.)
I would encourage you to dive into programming patterns. Learning patterns is learning to structure an application in the right way, depending on the given application.
I can say that a combination of your first example and your second example are a good place to start (an instantly invoked function expression wrapping and returning an object literal). This gives a degree of private scope via closure, and is called the Module Pattern. You will see this pattern used to some degree in almost all major JS applications and libraries because of its versatility and elegance.
To learn more about JavaScript patterns, I highly recommend Addy Osmani's "Learning JavaScript Design Patterns." You can read it for free, here: http://addyosmani.com/resources/essentialjsdesignpatterns/book/

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 use javascript namespaces correctly in a View / PartialView

i've been playing with MVC for a while now, but since the project i'm on is starting to get wind in its sails more and more people are added to it. Since i'm in charge of hacking around to find out some "best practice", i'm especially wary about the possible misuses of javascript and would like to find out what would be the best way to have our views and partial views play nicely with javascript.
For the moment, we're having code that looks like this (only simplified for example's sake)
<script type="text/javascript">
function DisableInputsForSubmit() {
if ($('#IsDisabled').is(':checked')) {
$('#Parameters :input').attr('disabled', true);
} else {
$('#Parameters :input').removeAttr('disabled');
}
}
</script>
<%=Html.SubmitButton("submit", Html.ResourceText("submit"), New With {.class = "button", .onclick = "DisableInputsForSubmit(); if ($('#EditParameters').validate().form()) {SetContentArea(GetHtmlDisplay('SaveParameters', 'Area', 'Controller'), $('#Parameters').serialize());} return false;"})%><%=Html.ResourceIcon("Save")%>
Here, we're saving a form and posting it to the server, but we disable inputs we don't want to validate if a checkbox is checked.
a bit of context
Please ignore the Html.Resource* bits, it's the resource management
helpers
The SetContentArea method wraps ajax calls, and GetHtmlDisplay
resolves url regarding an area,
controller and action
We've got combres installed that takes care of compressing, minifying
and serving third-parties libraries and what i've clearly identified as reusable javascript
My problem is that if somebody else defines a function DisableInputsForSubmit at another level (let's say the master page, or in another javascript file), problems may arise.
Lots of videos on the web (Resig on the design of jQuery, or Douglas Crockford for his talk at Google about the good parts of javascript) talk about using the namespaces in your libraries/frameworks.
So far so good, but in this case, it looks a bit overkill. What is the recommended way to go? Should i:
Create a whole framework inside a namespace, and reference it globally in the application? Looks like a lot of work for something so tiny as this method
Create a skeleton framework, and use local javascript in my views/partials, eventually promoting parts of the inline javascript to framework status, depending on the usage we have? In this case, how can i cleanly isolate the inline javascript from other views/partials?
Don't worry and rely on UI testing to catch the problem if it ever happens?
As a matter of fact, i think that even the JS code i've written that is in a separate file will benefit from your answers :)
As a matter of safety/best practice, you should always use the module pattern. If you also use event handlers rather than shoving javascript into the onclick attribute, you don't have to worry about naming conflicts and your js is easier to read:
<script type="text/javascript">
(function() {
// your button selector may be different
$("input[type='submit'].button").click(function(ev) {
DisableInputsForSubmit();
if ($('#EditParameters').validate().form()) {
SetContentArea(GetHtmlDisplay('SaveParameters', 'Area','Controller'), $('#Parameters').serialize());
}
ev.preventDefault();
});
function DisableInputsForSubmit() {
if ($('#IsDisabled').is(':checked')) {
$('#Parameters :input').attr('disabled', true);
} else {
$('#Parameters :input').removeAttr('disabled');
}
}
})();
</script>
This is trivially easy to extract into an external file if you decide to.
Edit in response to comment:
To make a function re-usable, I would just use a namespace, yes. Something like this:
(function() {
MyNS = MyNS || {};
MyNS.DisableInputsForSubmit = function() {
//yada yada
}
})();

Categories

Resources