How to design app to be modular / support plugins - javascript

I'm currently in the process of refactoring my webplayer so that we'll be more easily able to run it on our other internet radio stations. Much of the setup between these players will be very similar, however, some will need to have different UI plugins / other plugins.
Currently in the webplayer I do something like this in it's init():
_this.ui = new UI();
_this.ui.playlist = new Playlist();
_this.ui.channelDropdown = new ChannelDropdown();
_this.ui.timecode = ne Timecode();
etc etc
This works fine but that blocks me into requiring those objects at run time. What I'd like to do is be able to add those based on the stations needs. Basically my question is, do I need to add some kind of "addPlugin()" functionality here? And if I do that, do I need to constantly check from my WebPlayer object if that plugin exists before it attempts to use it? Like...
if (_hasPlugin('playlist')) this.plugins.playlist.add(track);
I apologize if some of this might not be clear... really trying to get my head wrapped around all of this. I feel I'm closer but I'm still stuck. Any advice on how I should proceed with this would be greatly appreciated.
Thanks in advance,
Lee

You would need to expose certain functionality within your application that you want others to be able to work off of. IE: making public get{} set{} accessors on major components like your UI and your player. The more functionality you expose the more plugins will be able to modify important parts of your functionality.
So let's say you have a UI.header, and header contains properties that define how the header displays the UI. So you expose header.backgroundImage as a public string, header.Text as a public string, and header.height as a public int. Now someone designing a plugin can change your header values and make it look and say what they want.
It's all about how much you want people to be able to alter your player based on what you expose.

You can define JavaScript classes for your plugins, load them as dependencies to the webplayer and instantiate them at runtime as needed with the help of RequireJS AMD.
//in your webplayer.js
define(['./ui','./playlist'],function(ui, playlist){
var webPlayer = function(stationID){
//initializing work
}
return webPlayer;
});
At runtime load the webplayer.js file when needed and instantiate the web player.
Have a look at BoilerplateJS which is a reference architecture for JavaScript product development. Concerns such as event handling, creating self contained components, handling interaction between them, who decides when to create/show/hide your UI components are taken care of in order to quickstart development.

Related

Dynamic/static loading components/pages/HTML

I would like to ask your advice on our situation about dynamic/static loading components.
We're developing a "multi language teaching app" for Android/iOS. For UI text we use ng2-translate plugin (JSON files for each language). For the lesson content we use separate HTML files for each language. In the beginning the user selects a language to learn and then sees related lessons as a list (which comes from a JSON file too). Clicking a lesson loads the related HTML file and dynamically compiles directives/pipes in it (which makes it more interactive). By directives, I mean simple functions like showing a toast when user clicks a custom directive, like this: <example tooltip="explanation to show as a toast">An example sentence</example>. But maybe we can use more complex directives in the future.
Up to building the app, everything goes well in browser. But the AoT compiler does not support "dynamic loader components" in mobile devices, so we need to decide whether or not use this approach. And at that point I'm really confused. We may change our structure but I don't know which way is better.
As far as I can see, we have three options (if there are more, please enlighten me):
Stop using html files and convert each of them into a component with html templates (using AoT compiler (--prod mode)):
Be able to use directives/pipes
Gain interactivity
Gain performance (that's the main purpose of AoT, right? but what if I use hundreds of html pages/components? isn't it a bulky solution?)
Use hundreds of pre-compiled html pages for grammar lessons, stories, texts...
Load pure HTML files into an innerHTML of a loader component (using AoT compiler (--prod mode)):
Don't use directives/pipes
Loose interactivity (except being able to use simple HTML tags like p, strong, em, table etc. --if we count this as an interactive content)
Gain performance a bit (as we use AoT?)
Load HTML files dynamically as components via one dynamic template component (using JiT compiler (--dev mode)):
Be able to use directives/pipes
Use separate html files
Gain interactivity
Loose performance
Do something that Angular generally does not recommend
I can't decide what to do now, if I want more interactivity, I should drop the performance that Angular proposes.
I just wanted to be able to handle these grammar lessons in a simple syntax (like HTML) as seperate files and not to use/declare components for each of them...
What would you recommend?
I asked same question to Ionic forum and I decided to implement the solution of a user that replied to me:
I went through this with Markdown, tried a bunch of things, and here's what I eventually settled on:
Store your objects however is convenient for you. In my case, that's markdown source.
Define two components; we'll call them skeleton and bone for now.
skeleton has an input property giving it the source. In ngOnChanges, you need to parse that source into an array of elements, each corresponding to a different type of bone.
skeleton's template looks something like this:
<template ngFor let-bone [ngForOf]="bones">
<app-bone [bone]="bone"></app-bone>
</template>
Make sure each bone has a discriminator indicating its type, and then the BoneComponent template is a big giant switch:
<blockquote *ngIf="bone.tag === 'blockquote'">
<app-bone *ngFor="let child of bone.children" [bone]="child"></app-bone>
</blockquote>
<br *ngIf="bone.tag === 'br'">
... every other block-level element we support...
Note that this can work recursively if you need it to, in that the
inside of the blockquote case is effectively another skeleton. I'm
using HTML elements here, but the general technique works equally well
for other user-defined components (as types of bones).

Should I recreate all my page from scratch (html and css) if I begin using React/flux?

I have alreayd built a few pages of my app. As i need a javascript framework and sub second dynamic pages I think I'll try React/Flux.
The thing is despite much reading, I don't fully understand if you can keep my EXISTING codebase (html/js) and only use React (jsx , modules) on certain blocks of the web page that need interaction with database/dynamic actualization?
Let's take an example:
my page has a lot of stuff : bootstrap I adjusted a lot(with css) that is actually using behind the scene javascript/the DOM ex for dropdowns, and other stuff), respond.js for enabling media queries on ie8 (using I guess the DOM), and many third party tools like intercom.io or even google analytics js tracking window on the bottom of my screen.
you can see here what the pages look like.
My need: I just need dynamic adjustments and real time features on the block (D), all the other, the header (B), intercom(C) and the rest could stay like they are, it would save me some much time if i can keep them in their current html code.
So here are my question:
(1) do I have to convert EVERYTHING on the page on react or only put in jsx/react the block (D) and keep the rest as it is ?
Related to (1) I want to leverage the main advantage brought by React (the virtual DOM and the diffs), would I still be able to use it EVEN if the whole page is not on React ?
If the answer is basically "it's all or nothing, you've got to do it ALL in react jsx and redo your whole page", convert your html and find alternatives to all your js scripts that use the DOM such as dropdowns, light boxes, intercom.io script, google analytics scripts then is it hard? i mean or can i keep the css and just use this to change the html http://facebook.github.io/react/html-jsx.html ? that would be really easy but i fear there is a catch here...:)
In terms of the view layer of your app everything can be done with React
(Yes react can do everything you require)
The first thing I would suggest is to head to the react site for the docs, do a few tutorial use Google & YouTube and then start to re-build your app from fresh with react but not entirely. (Use JSX).
Because you now understand how React works and how to use props and states you will likely end up merging fragments of your app at a time.
The most important thing to consider is context. React is simply Javascript so you can bind, call and apply any objects from your existing app.
var blockA = React.createClass~
blockB = React.createClass~
blockC = React.createClass~
blockD = React.createClass~
React is just components, each block is a component.
But I can't stress more, understand the basic principles of react, it's not hard at all.
Edit...
YES use JSX I thought it was stupid initially but it's excellent!
With DOM manipulation it's all or nothing. React uses its copy of the DOM to manipulate the actual DOM faster. For parts of you code that doesn't touch the DOM it will not make a huge difference in React but React has a beautiful workflow by passing state changes down to its component's children. Really it's up to you but If you are using React do all DOM stuff in react. 70+% of what you are trying to do is likely DOM manipulation.
My advice in general, don't think too much about how "hard" it will be. Think about how quick you can learn the basics. It's quite easy to grasp.
I am new to React, but from what I've gathered you may sprinkle in React code as desired. You do not have to re-write your entire application. This includes the ability to use the features you outlined wherever you need them.

dojo vs extjs for large single page js app

I'm going to be building a very large mvc js app admin app and have narrowed it down to dojo and extjs
I would like to know if anyone has any experiences with either of these frameworks within the last 6 months and if you had any issues with any of the following areas
speed of development
mvc
documentation
bindings
internalization
theming of widgets
a searchable client side store (doesn't have to be offline just the ability to store records once received and then do local searches on those records)
testing using some full stack tool like selenium
datagrid, pagination, sorting the whole works
Since Dojo does everything you required.
Dojo supports "stores" that do exactly what you ask.
They also support different things like JsonRestStore, XMLStore, HTMLStore, and many others so you can easily switch the source of your data.
About unit testing you can either use the built-in tool called Dojo Objective Harness, and it's robot, or something else like selenium or eventd (dojo).
About MVC, dojo has something called dojox.mvc : http://livedocs.dojotoolkit.org/releasenotes/1.7#mvc
Though there many other things too :)
I would recommand reading the tutorials here : http://dojotoolkit.org/documentation/
Your question is a bit hard to answer because i guess pretty much every decent framework today, can do what you ask. And each dev will tell you the framework he likes better is better ^^
Personally, I use Dojo, I find it powerfull and especially well made for large applications. They also are very active and keep up with the latest trends (AMD Loader RequireJS, etc).
There is a nice community also, helping each other, especially on the mailing list and irc channel.
Also, if it matters in anyway, companies such as IBM trust and spend time helping the framework to make it better.
speed of development : good
mvc : good
documentation : good - huge progresses recently :)
bindings : good
internalization : good
theming of widgets : using LESS rocks
a searchable client side store (doesn't have to be offline just the ability to store records once received and then do local searches on those records) : good
testing using some full stack tool like selenium : good
datagrid, pagination, sorting the whole works : new dgrid is great, old grids are ok Dojo is quite powerful, but can be tricky at times, good support makes up for it
Here's what Ext-JS offers.
Speed of development: http://docs.sencha.com/ext-js/4-0/#!/example Look at how easy the examples are
MVC: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.app.Controller (Routing is not built in yet)
Documentation: http://docs.sencha.com/ext-js/4-0/#
Bindings http://docs.sencha.com/ext-js/4-0/#!/example/grid/binding.html
Internalization: every widget can be i18ned
Theming of widgets: Uses SASS
A searchable client side store: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.Store-method-find
Testing using some full stack tool like selenium: Not built in, but since it's all OO based and decoupled, testing is easy
datagrid, pagination, sorting the whole works: http://docs.sencha.com/ext-js/4-0/#!/example/grid/multiple-sorting.html and http://docs.sencha.com/ext-js/4-0/#!/example/grid/paging.html
Dynamic Class loading: http://www.sencha.com/blog/countdown-to-ext-js-4-dynamic-loading-and-new-class-system/
RTL support: http://www.sencha.com/forum/showthread.php?137065-EXTJS-4-RTL-When
Charting: I personally think it's below par for Ext-JS standards but they offer a pretty feature-full package (bugs non-withstanding) http://docs.sencha.com/ext-js/4-0/#!/guide/drawing_and_charting I actually prefer to use http://code.google.com/p/flot/ and I created a simple wrapper to use it as an Ext-JS Component
This doesn't belong in the answer, but if you end up using Ext-JS, you may need the following for better performing charts. The advantage of Ext charts is that they are easier to interact (mouseover, click) since it's not canvas based like flot.
/**
* Renders a single flot chart, a much simplifed version of ExtFlot
*/
Ext.define('Ext.ux.FlotPanel', {
extend: 'Ext.Component',
alias: 'widget.flot',
/**
* #cfg {number[][]} data The data to be drawn when it gets rendered
*/
data: null,
/**
* #cfg {object} flotOptions
* The options to be passed in to $.plot
*/
flotOptions: null,
/**
* #property
* The Flot object used to render the chart and to manipulate it in the future. It will only
* be available after the first resize event
* You may not set this property but you are free to call methods on it
*/
flot: null,
initComponent: function() {
this.callParent(arguments);
// The only time that we're guaranteed to have dimensions is after the first resize event
this.on('resize', function(cmp) {
if (!cmp.flot) {
cmp.flot = $.plot(cmp.getTargetEl().dom, cmp.data, cmp.flotOptions);
} else {
// Flot knows to look at the container's size and resize itself
cmp.flot.resize();
cmp.flot.setupGrid();
cmp.flot.draw();
}
});
this.on('beforedestroy', function(cmp){
if (cmp.flot) {
cmp.flot.shutdown();
}
});
}
});
When I looked at Dojo 4 years ago, I hated it. Coudln't stand declaring widgets in HTML. I much rather declare them with JS objects ( I have heard that you can now declare widgets without specifying the HTML. There are people who love creating widgets in the HTML, but in my case (dynamic business minded apps), every piece on the screen is dynamic and the configuration comes from the server, so I don't want the server generating my HTML since I need knowledge about it in my JS.
In any case, I'm really happy with Ext-JS and have no reason to go out shopping for a new framework.

Creating a javascript widget for other sites

I am looking to create a javascript "widget" that can be hosted on other sites. For example. I want to host the javascript code on my site:
http://scripts.mysite.com/mywidget.js
(Think of it like Google Analytics).
Basically I want to distribute data via this javascript. But what I am unsure of is:
Are the rules different for development when creating a javascript for another site (cross site)
Are there any websites that explain these differences?
I would try to:
Make it configurable
Load external stylesheets?
Where do I find resources I need? (images, stylesheets)
What layout/size should I have?
By doing this you let the user decide if he wants your widget to automatically load the stylesheet, or if he wants to host it himself. If he does, he can also update the styles to better fit the page the widget resides on.
Provide a wizard for generating a snippet of code to include on the page
Ensures that even moderately technical users can utilize your widget
Make it light-weight
Serve everything minified and compressed
Serve with cache-headers, e-tags, last-modified and all other useful headers you can think of. This will both reduce the load on your servers as well as make your widget more responsive.
Try to avoid dependencies on libraries, or check if they are loaded on the page where the widget is used before loading them
Be wary of conflicts
Prototype uses $, and so does jQuery. If your widget depends on Prototype, and the page it is hosted on uses jQuery without noConflict-mode, problems WILL arise
Do not clobber the global namespace!
If you don't want anyone to interact with your widget, put it in a self-executing function in a closure and don't create any global variables at all
If you want users to be able to interact with your widget, say for adding event listeners and such, claim a single global variable, let's say ExampleComWidget as an object literal and put your methods there. User's could then interact like: ExampleComWidget.addListener('update', callback);
Use clever markup
Be sure to use scoping on your classes and ids, to avoid conflicts as much as possible
I.e. if your company's name is example.com, you could use classes like: com-ex-widget-newsItem
Validate your markup! You do not want to break a user's site
Semantic markup is fine, but you might want to avoid <h1>-tags, since they have especially high ranking in SEO. You could probably get by with using <h4> and less. This bullet might be a bit off. When in doubt, it's much better to use semantic markup than not.
Fetch data from your site by inserting script elements
This is a fool-proof way to ensure that you get around the same-origin restrictions.
Attach an onload-listener to the script element to know when the data is ready, or use jsonp
Your script should not interfere with the rest of the page.
Keep the number of globals to a
minimum (one namespace object
should be enough)
Don't add properties to the built-in
objects for no reason
Don't expect to be the only script
that listen for events such as window.onload
If you're using for..in loops keep in mind
that other scripts may have added
stuff to Array.prototype
Take style-sheets into consideration. The default style of HTML elements may have been changed.
Don't update your script without reason as you risk breaking a lot of sites.
What PatrikAkerstrand said, is totally, 100% right.
What I want to add here, is a framework in vanilla JS that can save you a lot of time and effort to implement it, as everything is thought of, polished, and tested. All is left is to define your own widgets, and use them.
Here's an example of what it looks like.
A widget code
// inside a js file of a widget class
(function () {
var Module_Path = ["WidgetsLib", "a1", "Button"];
var curr = this;
Module_Path.forEach(function(i){if (curr[i] == null) {addChildToTree(curr, i, {})} curr = curr[i]});
specialize_with(curr, {
CSS_Literal: `
.{{WIDGET_CLASS_ID}}_Something {
color: hsl(0, 0%, 20%);
}
`,
HTML_Literal: `
<div onclick="{{WIDGET_INSTANCE}}.onclick(event)"
class="{{WIDGET_CLASS_ID}}_Something"
>
SOME SUPER COOL WIDGET
</div>
`,
new: typical_widget_new,
});
})();
An HTML:
<div id="w1" style="background-color: hsl(200, 50%, 50%);"></div>
<script src="WidgetsLib/a1/Button/js"></script>
A user JavaScript code:
var b1 = WidgetsLib.a1.Button.new("w1", {
onclick: function(ev) {
ev.target.style.color = "#ffff00";
console.log("====== HERE");
}
});
Please download, and open the Widget_v2.md.html in a browser, it's https://github.com/latitov/JS_HTML_Widgets .
What you'll get:
very interesting article about this;
snippets of code and examples;
ready to use... framework in vanilla JS, to create widgets of your own;
And enjoy creating re-usable widgets of your own, of arbitrary complexity, easily!

Commonly accepted best practices around code organization in JavaScript [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 8 years ago.
Improve this question
As JavaScript frameworks like jQuery make client side web applications richer and more functional, I've started to notice one problem...
How in the world do you keep this organized?
Put all your handlers in one spot and write functions for all the events?
Create function/classes to wrap all your functionality?
Write like crazy and just hope it works out for the best?
Give up and get a new career?
I mention jQuery, but it's really any JavaScript code in general. I'm finding that as lines upon lines begin to pile up, it gets harder to manage the script files or find what you are looking for. Quite possibly the biggest propblems I've found is there are so many ways to do the same thing, it's hard to know which one is the current commonly accepted best practice.
Are there any general recommendations on the best way to keep your .js files as nice and neat as the rest of your application? Or is this just a matter of IDE? Is there a better option out there?
EDIT
This question was intended to be more about code organization and not file organization. There has been some really good examples of merging files or splitting content around.
My question is: what is the current commonly accepted best practice way to organize your actual code? What is your way, or even a recommended way to interact with page elements and create reuseable code that doesn't conflict with each other?
Some people have listed namespaces which is a good idea. What are some other ways, more specifically dealing with elements on the page and keeping the code organized and neat?
It would be a lot nicer if javascript had namespaces built in, but I find that organizing things like Dustin Diaz describes here helps me a lot.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
I put different "namespaces" and sometimes individual classes in separate files. Usually I start with one file and as a class or namespace gets big enough to warrant it, I separate it out into its own file. Using a tool to combine all you files for production is an excellent idea as well.
I try to avoid including any javascript with the HTML. All the code is encapsulated into classes and each class is in its own file. For development, I have separate <script> tags to include each js file, but they get merged into a single larger package for production to reduce the overhead of the HTTP requests.
Typically, I'll have a single 'main' js file for each application. So, if I was writing a "survey" application, i would have a js file called "survey.js". This would contain the entry point into the jQuery code. I create jQuery references during instantiation and then pass them into my objects as parameters. This means that the javascript classes are 'pure' and don't contain any references to CSS ids or classnames.
// file: survey.js
$(document).ready(function() {
var jS = $('#surveycontainer');
var jB = $('#dimscreencontainer');
var d = new DimScreen({container: jB});
var s = new Survey({container: jS, DimScreen: d});
s.show();
});
I also find naming convention to be important for readability. For example: I prepend 'j' to all jQuery instances.
In the above example, there is a class called DimScreen. (Assume this dims the screen and pops up an alert box.) It needs a div element that it can enlarge to cover the screen, and then add an alert box, so I pass in a jQuery object. jQuery has a plug-in concept, but it seemed limiting (e.g. instances are not persistent and cannot be accessed) with no real upside. So the DimScreen class would be a standard javascript class that just happens to use jQuery.
// file: dimscreen.js
function DimScreen(opts) {
this.jB = opts.container;
// ...
}; // need the semi-colon for minimizing!
DimScreen.prototype.draw = function(msg) {
var me = this;
me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
//...
};
I've built some fairly complex appliations using this approach.
You can break up your scripts into separate files for development, then create a "release" version where you cram them all together and run YUI Compressor or something similar on it.
Inspired by earlier posts I made a copy of Rakefile and vendor directories distributed with WysiHat (a RTE mentioned by changelog) and made a few modifications to include code-checking with JSLint and minification with YUI Compressor.
The idea is to use Sprockets (from WysiHat) to merge multiple JavaScripts into one file, check syntax of the merged file with JSLint and minify it with YUI Compressor before distribution.
Prerequisites
Java Runtime
ruby and rake gem
You should know how to put a JAR into Classpath
Now do
Download Rhino and put the JAR ("js.jar") to your classpath
Download YUI Compressor and put the JAR (build/yuicompressor-xyz.jar) to your classpath
Download WysiHat and copy "vendor" directory to the root of your JavaScript project
Download JSLint for Rhino and put it inside the "vendor" directory
Now create a file named "Rakefile" in the root directory of the JavaScript project and add the following content to it:
require 'rake'
ROOT = File.expand_path(File.dirname(__FILE__))
OUTPUT_MERGED = "final.js"
OUTPUT_MINIFIED = "final.min.js"
task :default => :check
desc "Merges the JavaScript sources."
task :merge do
require File.join(ROOT, "vendor", "sprockets")
environment = Sprockets::Environment.new(".")
preprocessor = Sprockets::Preprocessor.new(environment)
%w(main.js).each do |filename|
pathname = environment.find(filename)
preprocessor.require(pathname.source_file)
end
output = preprocessor.output_file
File.open(File.join(ROOT, OUTPUT_MERGED), 'w') { |f| f.write(output) }
end
desc "Check the JavaScript source with JSLint."
task :check => [:merge] do
jslint_path = File.join(ROOT, "vendor", "jslint.js")
sh 'java', 'org.mozilla.javascript.tools.shell.Main',
jslint_path, OUTPUT_MERGED
end
desc "Minifies the JavaScript source."
task :minify => [:merge] do
sh 'java', 'com.yahoo.platform.yui.compressor.Bootstrap', '-v',
OUTPUT_MERGED, '-o', OUTPUT_MINIFIED
end
If you done everything correctly, you should be able to use the following commands in your console:
rake merge -- to merge different JavaScript files into one
rake check -- to check the syntax of your code (this is the default task, so you can simply type rake)
rake minify -- to prepare minified version of your JS code
On source merging
Using Sprockets, the JavaScript pre-processor you can include (or require) other JavaScript files. Use the following syntax to include other scripts from the initial file (named "main.js", but you can change that in the Rakefile):
(function() {
//= require "subdir/jsfile.js"
//= require "anotherfile.js"
// some code that depends on included files
// note that all included files can be in the same private scope
})();
And then...
Take a look at Rakefile provided with WysiHat to set the automated unit testing up. Nice stuff :)
And now for the answer
This does not answer the original question very well. I know and I'm sorry about that, but I've posted it here because I hope it may be useful to someone else to organize their mess.
My approach to the problem is to do as much object-oriented modelling I can and separate implementations into different files. Then the handlers should be as short as possible. The example with List singleton is also nice one.
And namespaces... well they can be imitated by deeper object structure.
if (typeof org === 'undefined') {
var org = {};
}
if (!org.hasOwnProperty('example')) {
org.example = {};
}
org.example.AnotherObject = function () {
// constructor body
};
I'm not big fan of imitations, but this can be helpful if you have many objects that you would like to move out of the global scope.
The code organization requires adoption of conventions and documentation standards:
1. Namespace code for a physical file;
Exc = {};
2. Group classes in these namespaces javascript;
3. Set Prototypes or related functions or classes for representing real-world objects;
Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
this.mask = mask;
...
};
Exc.ui.domTips = function (dom, tips) {
this.dom = gift;
this.tips = tips;
...
};
4. Set conventions to improve the code. For example, group all of its internal functions or methods in its class attribute of an object type.
Exc.ui.domTips = function (dom, tips) {
this.dom = gift;
this.tips = tips;
this.internal = {
widthEstimates: function (tips) {
...
}
formatTips: function () {
...
}
};
...
};
5. Make documentation of namespaces, classes, methods and variables. Where necessary also discuss some of the code (some FIs and Fors, they usually implement important logic of the code).
/**
* Namespace <i> Example </i> created to group other namespaces of the "Example".
*/
Exc = {};
/**
* Namespace <i> ui </i> created with the aim of grouping namespaces user interface.
*/
Exc.ui = {};
/**
* Class <i> maskdInput </i> used to add an input HTML formatting capabilities and validation of data and information.
* # Param {String} mask - mask validation of input data.
*/
Exc.ui.maskedInput = function (mask) {
this.mask = mask;
...
};
/**
* Class <i> domTips </i> used to add an HTML element the ability to present tips and information about its function or rule input etc..
* # Param {String} id - id of the HTML element.
* # Param {String} tips - tips on the element that will appear when the mouse is over the element whose identifier is id <i> </i>.
*/
Exc.ui.domTips = function (id, tips) {
this.domID = id;
this.tips = tips;
...
};
These are just some tips, but that has greatly helped in organizing the code. Remember you must have discipline to succeed!
Following good OO design principals and design patterns goes a long way to making your code easy to maintain and understand.
But one of the best things I've discovered recently are signals and slots aka publish/subscribe.
Have a look at http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html
for a simple jQuery implementation.
The idea is well used in other languages for GUI development. When something significant happens somewhere in your code you publish a global synthetic event which other methods in other objects may subscribe to.
This gives excellent separation of objects.
I think Dojo (and Prototype?) have a built in version of this technique.
see also What are signals and slots?
I was able to successfully apply the Javascript Module Pattern to an Ext JS application at my previous job. It provided a simple way to create nicely encapsulated code.
Dojo had the module system from the day one. In fact it is considered to be a cornerstone of Dojo, the glue that holds it all together:
dojo.require — the official doc.
Understanding dojo.declare, dojo.require, and dojo.provide.
Introducing Dojo.
Using modules Dojo achieves following objectives:
Namespaces for Dojo code and custom code (dojo.declare()) — do not pollute the global space, coexist with other libraries, and user's non-Dojo-aware code.
Loading modules synchronously or asynchronously by name (dojo.require()).
Custom builds by analyzing module dependencies to create a single file or a group of interdependent files (so-called layers) to include only what your web application needs. Custom builds can include Dojo modules and customer-supplied modules as well.
Transparent CDN-based access to Dojo and user's code. Both AOL and Google carry Dojo in this fashion, but some customers do that for their custom web applications as well.
Check out JavasciptMVC.
You can :
split up your code into model, view and controller layers.
compress all code into a single production file
auto-generate code
create and run unit tests
and lots more...
Best of all, it uses jQuery, so you can take advantage of other jQuery plugins too.
My boss still speaks of the times when they wrote modular code (C language), and complains about how crappy the code is nowadays! It is said that programmers can write assembly in any framework. There is always a strategy to overcome code organisation. The basic problem is with guys who treat java script as a toy and never try to learn it.
In my case, I write js files on a UI theme or application screen basis, with a proper init_screen(). Using proper id naming convention, I make sure that there are no name space conflicts at the root element level. In the unobstrusive window.load(), I tie the things up based on the top level id.
I strictly use java script closures and patterns to hide all private methods. After doing this, never faced a problem of conflicting properties/function definitions/variable definitions. However, when working with a team it is often difficult to enforce the same rigour.
I'm surprised no one mentioned MVC frameworks. I've been using Backbone.js to modularize and decouple my code, and it's been invaluable.
There are quite a few of these kinds of frameworks out there, and most of them are pretty tiny too. My personal opinion is that if you're going to be writing more than just a couple lines of jQuery for flashy UI stuff, or want a rich Ajax application, an MVC framework will make your life much easier.
"Write like crazy and just hope it works out for the best?", I've seen a project like this which was developed and maintained by just 2 developers, a huge application with lots of javascript code. On top of that there were different shortcuts for every possible jquery function you can think of. I suggested they organize the code as plugins, as that is the jquery equivalent of class, module, namespace... and the whole universe. But things got much worse, now they started writing plugins replacing every combination of 3 lines of code used in the project.
Personaly I think jQuery is the devil and it shouldn't be used on projects with lots of javascript because it encourages you to be lazy and not think of organizing code in any way. I'd rather read 100 lines of javascript than one line with 40 chained jQuery functions (I'm not kidding).
Contrary to popular belief it's very easy to organize javascript code in equivalents to namespaces and classes. That's what YUI and Dojo do. You can easily roll your own if you like. I find YUI's approach much better and efficient. But you usualy need a nice editor with support for snippets to compensate for YUI naming conventions if you want to write anything useful.
I create singletons for every thing I really do not need to instantiate several times on screen, a classes for everything else. And all of them are put in the same namespace in the same file. Everything is commented, and designed with UML , state diagrams. The javascript code is clear of html so no inline javascript and I tend to use jquery to minimize cross browser issues.
In my last project -Viajeros.com- I've used a combination of several techniques. I wouldn't know how to organize a web app -- Viajeros is a social networking site for travellers with well-defined sections, so it's kind of easy to separate the code for each area.
I use namespace simulation and lazy loading of modules according to the site section. On each page load I declare a "vjr" object, and always load a set of common functions to it (vjr.base.js). Then each HTML page decides which modules need with a simple:
vjr.Required = ["vjr.gallery", "vjr.comments", "vjr.favorites"];
Vjr.base.js gets each one gzipped from the server and executes them.
vjr.include(vjr.Required);
vjr.include = function(moduleList) {
if (!moduleList) return false;
for (var i = 0; i < moduleList.length; i++) {
if (moduleList[i]) {
$.ajax({
type: "GET", url: vjr.module2fileName(moduleList[i]), dataType: "script"
});
}
}
};
Every "module" has this structure:
vjr.comments = {}
vjr.comments.submitComment = function() { // do stuff }
vjr.comments.validateComment = function() { // do stuff }
// Handlers
vjr.comments.setUpUI = function() {
// Assign handlers to screen elements
}
vjr.comments.init = function () {
// initialize stuff
vjr.comments.setUpUI();
}
$(document).ready(vjr.comments.init);
Given my limited Javascript knowledge, I know there must be better ways to manage this, but until now it's working great for us.
Organising your code in a Jquery centric NameSpace way may look as follows... and will not clash with other Javascript API's like Prototype, Ext either.
<script src="jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
var AcmeJQ = jQuery.noConflict(true);
var Acme = {fn: function(){}};
(function($){
Acme.sayHi = function()
{
console.log('Hello');
};
Acme.sayBye = function()
{
console.log('Good Bye');
};
})(AcmeJQ);
// Usage
// Acme.sayHi();
// or
// Say Hello
</script>
Hope this helps.
Good principal of OO + MVC would definitely go a long way for managing a complex javascript app.
Basically I am organizing my app and javascript to the following familiar design (which exists all the way back from my desktop programming days to Web 2.0)
Description for the numeric values on the image:
Widgets representing the views of my application. This should be extensible and separated out neatly resulting good separation that MVC tries to achieve rather than turning my widget into a spaghetti code (equivalent in web app of putting a large block of Javascript directly in HTML). Each widget communicate via others by listening to the event generated by other widgets thus reducing the strong coupling between widgets that could lead to unmanageable code (remember the day of adding onclick everywhere pointing to a global functions in the script tag? Urgh...)
Object models representing the data that I want to populate in the widgets and passing back and forth to the server. By encapsulating the data to its model, the application becomes data format agnostics. For example: while Naturally in Javascript these object models are mostly serialized and deserialized into JSON, if somehow the server is using XML for communication, all I need to change is changing the serialization/deserialization layer and not necessarily needs to change all the widget classes.
Controller classes that manage the business logic and communication to the server + occasionally caching layer. This layer control the communication protocol to the server and put the necessary data into the object models
Classes are wrapped neatly in their corresponding namespaces. I am sure we all know how nasty global namespace could be in Javascript.
In the past, I would separate the files into its own js and use common practice to create OO principles in Javascript. The problem that I soon found that there are multiple ways to write JS OO and it's not necessarily that all team members have the same approach. As the team got larger (in my case more than 15 people), this gets complicated as there is no standard approach for Object Oriented Javascript. At the same time I don't want to write my own framework and repeat some of the work that I am sure smarter people than I have solved.
jQuery is incredibly nice as Javascript Framework and I love it, however as project gets bigger, I clearly need additional structure for my web app especially to facilitate standardize OO practice. For myself, after several experiments, I find that YUI3 Base and Widget (http://yuilibrary.com/yui/docs/widget/ and http://yuilibrary.com/yui/docs/base/index.html) infrastructure provides exactly what I need. Few reasons why I use them.
It provides Namespace support. A real need for OO and neat organization of your code
It support notion of classes and objects
It gives a standardize means to add instance variables to your class
It supports class extension neatly
It provides constructor and destructor
It provides render and event binding
It has base widget framework
Each widget now able to communicate to each other using standard event based model
Most importantly, it gives all the engineers an OO Standard for Javascript development
Contrary to many views, I don't necessarily have to choose between jQuery and YUI3. These two can peacefully co-exist. While YUI3 provides the necessary OO template for my complex web app, jQuery still provides my team with easy to use JS Abstraction that we all come to love and familiar with.
Using YUI3, I have managed to create MVC pattern by separating classes that extend the Base as the Model, classes that extends Widget as a View and off course you have Controller classes that are making necessary logic and server side calls.
Widget can communicate with each other using event based model and listening to the event and doing the necessary task based on predefined interface. Simply put, putting OO + MVC structure to JS is a joy for me.
Just a disclaimer, I don't work for Yahoo! and simply an architect that is trying to cope with the same issue that is posed by the original question. I think if anyone finds equivalent OO framework, this would work as well. Principally, this question applies to other technologies as well. Thank God for all the people who came up with OO Principles + MVC to make our programming days more manageable.
I use Dojo's package management (dojo.require and dojo.provide) and class system (dojo.declare which also allows for simple multiple inheritance) to modularize all of my classes/widgets into separate files. Not only dose this keep your code organized, but it also lets you do lazy/just in time loading of classes/widgets.
A few days ago, the guys at 37Signals released a RTE control, with a twist. They made a library that bundles javascript files using a sort of pre-processor commands.
I've been using it since to separate my JS files and then in the end merge them as one. That way I can separate concerns and, in the end, have only one file that goes through the pipe (gzipped, no less).
In your templates, check if you're in development mode, and include the separate files, and if in production, include the final one (which you'll have to "build" yourself).
Create fake classes, and make sure that anything that can be thrown into a separate function that makes sense is done so. Also make sure to comment a lot, and not to write spagghetti code, rather keeping it all in sections. For example, some nonsense code depicting my ideals. Obviously in real life I also write many libraries that basically encompass their functionality.
$(function(){
//Preload header images
$('a.rollover').preload();
//Create new datagrid
var dGrid = datagrid.init({width: 5, url: 'datalist.txt', style: 'aero'});
});
var datagrid = {
init: function(w, url, style){
//Rendering code goes here for style / width
//code etc
//Fetch data in
$.get(url, {}, function(data){
data = data.split('\n');
for(var i=0; i < data.length; i++){
//fetching data
}
})
},
refresh: function(deep){
//more functions etc.
}
};
Use inheritance patterns to organize large jQuery applications.
I think this ties into, perhaps, DDD (Domain-Driven Design). The application I'm working on, although lacking a formal API, does give hints of such by way of the server-side code (class/file names, etc). Armed with that, I created a top-level object as a container for the entire problem domain; then, I added namespaces in where needed:
var App;
(function()
{
App = new Domain( 'test' );
function Domain( id )
{
this.id = id;
this.echo = function echo( s )
{
alert( s );
}
return this;
}
})();
// separate file
(function(Domain)
{
Domain.Console = new Console();
function Console()
{
this.Log = function Log( s )
{
console.log( s );
}
return this;
}
})(App);
// implementation
App.Console.Log('foo');
For JavaScript organization been using the following
Folder for all your javascript
Page level javascript gets its' own file with the same name of the page. ProductDetail.aspx would be ProductDetail.js
Inside the javascript folder for library files I have a lib folder
Put related library functions in a lib folder that you want to use throughout your application.
Ajax is the only javascript that I move outside of the javascript folder and gets it's own folder. Then I add two sub folders client and server
Client folder gets all the .js files while server folder gets all the server side files.
I'm using this little thing. It gives you 'include' directive for both JS and HTML templates. It eleminates the mess completely.
https://github.com/gaperton/include.js/
$.include({
html: "my_template.html" // include template from file...
})
.define( function( _ ){ // define module...
_.exports = function widget( $this, a_data, a_events ){ // exporting function...
_.html.renderTo( $this, a_data ); // which expands template inside of $this.
$this.find( "#ok").click( a_events.on_click ); // throw event up to the caller...
$this.find( "#refresh").click( function(){
widget( $this, a_data, a_events ); // ...and update ourself. Yep, in that easy way.
});
}
});
You can use jquery mx (used in javascriptMVC) which is a set of scripts that allows you to use models, views, and controllers. I've used it in a project and helped me create structured javascript, with minimal script sizes because of compression. This is a controller example:
$.Controller.extend('Todos',{
".todo mouseover" : function( el, ev ) {
el.css("backgroundColor","red")
},
".todo mouseout" : function( el, ev ) {
el.css("backgroundColor","")
},
".create click" : function() {
this.find("ol").append("<li class='todo'>New Todo</li>");
}
})
new Todos($('#todos'));
You can also use only the controller side of jquerymx if you aren't interested in the view and model parts.
Your question is one that plagued me late last year. The difference - handing the code off to new developers who had never heard of private and public methods. I had to build something simple.
The end result was a small (around 1KB) framework that translates object literals into jQuery. The syntax is visually easier to scan, and if your js grows really large you can write reusable queries to find things like selectors used, loaded files, dependent functions, etc.
Posting a small framework here is impractical, so I wrote a blog post with examples (My first. That was an adventure!). You're welcome to take a look.
For any others here with a few minutes to check it out, I'd greatly appreciate feedback!
FireFox recommended since it supports toSource() for the object query example.
Cheers!
Adam
I use a custom script inspired by Ben Nolan's behaviour (I can't find a current link to this anymore, sadly) to store most of my event handlers. These event handlers are triggered by the elements className or Id, for example.
Example:
Behaviour.register({
'a.delete-post': function(element) {
element.observe('click', function(event) { ... });
},
'a.anotherlink': function(element) {
element.observe('click', function(event) { ... });
}
});
I like to include most of my Javascript libraries on the fly, except the ones that contain global behaviour. I use Zend Framework's headScript() placeholder helper for this, but you can also use javascript to load other scripts on the fly with Ajile for example.
You don't mention what your server-side language is. Or, more pertinently, what framework you are using -- if any -- on the server-side.
IME, I organise things on the server-side and let it all shake out onto the web page. The framework is given the task of organising not only JS that every page has to load, but also JS fragments that work with generated markup. Such fragments you don't usually want emitted more than once - which is why they are abstracted into the framework for that code to look after that problem. :-)
For end-pages that have to emit their own JS, I usually find that there is a logical structure in the generated markup. Such localised JS can often be assembled at the start and/or end of such a structure.
Note that none of this absolves you from writing efficient JavaScript! :-)
Lazy Load the code you need on demand. Google does something like this with their google.loader

Categories