Javascript is not my core work, but I do want to structure my jQuery file properly. For now, I've got some functions and loose jQuery, but nothing really OO ;) Mind you, I'm mostly manipulating the DOM, like adding and removing classes and inserting HTML. Nothing fancy really.
Just wondering how you people structure these things. Maybe some good articles somewhere on this?
Oh, I am using JSLint though, and that helps a bit with consistency, but it doesn't care about how I structure it all. ;)
Just to show you what I mean by simple jQuery, see this Codepen: codepen.io/robertvanderelst/pen/xZrjRq
If you don't have that much Javascript, you can go with modules.
(function($) {
var Module = {
'common': {
init: function() {
xxx
},
finalize: function() {
xxx
}
},
'home': {
init: function() {
xxx
}
},
};
})(jQuery);
However as I am using babel and browserify and some ES6 sugar, I am going a more modular way.
My main javascript file, which requires or imports (es6 way) my components. Example:
import Slider from './Components/Slider'
var mainSlider = new Slider('.carousel')
mainSlider.up()
const magConfig = {
slidesToShow: 5,
slidesToScroll: 1,
....
}
var magazinSlider = new Slider('.magazin-listing', magConfig )
magazinSlider.up()
import slick from 'slick-carousel'
import $ from 'jquery'
import _ from 'underscore'
class Slider {
constructor(selector, settings) {
let defaultSettings = {
// Some slider settings....
}
this.settings = defaultSettings
// Some other constructor code....
}
up() {
$(this.selector).slick(this.settings)
}
down() {
$(this.selector).slick('unslick')
}
}
export default Slider
It's actually a bit more work, but it's cleaner and you can reuse stuff easy.
import $ from 'jquery';
const selector = '.mobile-trigger';
const navigation = '.main__navigation__content';
class MobileMenu {
constructor() {
$(selector).on('click', (e) => {
$(navigation).toggleClass('main__navigation--open')
})
}
}
export default new MobileMenu()
The approach that I use currently is to have my javascript functions in separate module files using a module pattern (see post from @Kleo) and then call those functions from a simpler jQuery file. This allows me to re-use the javascripts in other projects ... for example (this is made up):
// module file
var myCar = (function () {
var configs = {
"colour" : "red",
"cost" : 10000,
};
function _applyPaint() {
// private, not exposed
...
}
function start() {
...
}
function stop () {
...
}
function accelerae () {
...
}
var publicFunctions {
start : start,
stop : stop,
accelerate : accelerate,
}
return PublicFunctions;
})();
// jQuery file
$(document).ready( function() {
$("#start").click (function (e) {
e.preventDefault();
myCar.start();
})
$(".stop").click (function (e) {
e.preventDefault();
myCar.stop();
})
});
If you need good structure try any JavaScript framework. Most of them are easy to use for little tasks.
For your codepen example no further organisation is nessecary... that's just a function, so just bring the file which holds that code in after your jquery include at the bottom of your HTML.
Libraries like RequireJS and CommonJS will help to you keep our code modularized. AMD allows you to explicitly state what your code depends on and call it on demand. You will have to include only one javascript in your HTML and the necessary modules will get executed after its dependencies got loaded. That way global variable pollution will be completely gone (if done properly).
Using the Module Pattern or Revealing Module Pattern brings sanity to every spaghetti code. Addy Osmani explains greatly the two patterns in his Learning JavaScript Design Patterns:
Things that should be customized, will be separated in it's own configuration object literal. That way other developers won't need to go through the whole code to find what they need to change. Chirstian Heilmann (from whom I've learned about this approach) wrote:
There’s a clear separation of “change what you need to change here” and “only touch this if you know what you are doing” – allowing more developers to use your code.
Here is a simple example:
var module = function(){
// configuration, change things here
var config = {
CSS:{
classes:{
hover:'hover',
active:'current',
jsEnabled:'js'
},
ids:{
container:'maincontainer'
}
},
timeout:2000,
userID:'chrisheilmann'
};
// start of main code
function init(){
...
};
// ... more methods and other code ...
// make init a public method
return {
init:init
};
}();
module.init();
You can read more about the topic here - Providing Script Configuraton In-line and programatically
Steffen Cope
Indelible Web.
Simon Toulson
Take a look at this video youtube.com/watch - I pretty much follow this pattern for jquery development and it works for me - even for the simple sort of task you mention in your example.