Skip to content

Instantly share code, notes, and snippets.

@ethyde
Created September 30, 2014 12:01
Show Gist options
  • Select an option

  • Save ethyde/f79bcc77c85037d64c1d to your computer and use it in GitHub Desktop.

Select an option

Save ethyde/f79bcc77c85037d64c1d to your computer and use it in GitHub Desktop.
/*
*
* Garber-Irish Implementation :
* http://viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution
* http://www.diegolago.co.uk/development/organise-your-javascript-and-make-your-life-easier/
*
* Modif pour se baser sur X element dans la page et non sur le body
* http://techblog.treenodes.com/index.php/2012/04/19/organize-javascript-and-jquery-events-dom-ready-execution/
*
* plus simple, mais dans le même esprit :
* http://www.netmagazine.com/tutorials/get-your-javascript-order
* http://rmurphey.com/blog/2009/10/15/using-objects-to-organize-your-code/
* http://mahdipedram.com/object-oriented-with-jquery-javascript/
* Version en court https://gist.github.com/3098158 (http://bit.ly/Mahd5J version sans commentaire)
*
* Attention à bien spécifier les valeurs des data-attributs sur le body.
*
* Exemple :
*
* <body id="home" data-controller="home" data-action="slideshow,search">
*
* Sur le sujet lire aussi : http://jqfundamentals.com/legacy#chapter-9 #Beware anonymous functions
*
*/
/*
*
* Namespace principal du projet.
* Sert à englober et restreindre le code du projet, ainsi
* qu'à exposer l'interface publique. Je suggère qu'on utilise
* toujours le préfixe "UI_" dans nos variables globales pour
* réduire au maximum les chances de conflits.
*
*/
var UI_PROJECT = (function( $, window, document, undefined ) {
// Devrait maintenant être utilisé dans tous nos projets.
// Va nous permettre de développer du meilleur code JavaScript:
// http://bit.ly/JNBf5z
'use strict';
var SITE = {}, UTIL = SITE;
// Objet contenant toutes les fonctionnalitées propres au site en cours.
SITE = {
common: {
// Function commune exécutée dans toutes les pages
init: function() {
console.log('exécute une action générale');
//Toggle val sur les champs text et password
$('input[type="text"],input[type="password"]').toggleVal();
//S'ouvre dans une nouvelle fenetre propre et optimisé avec .on()
$('#contenu').on( 'click', 'a[rel="external"]', function(event) { event.preventDefault(); window.open( this.href ); });
// démo requete ajax-json profile 0.170ms, 16 calls
ajaxCTA('ajax-panel');
// demo conditional loading based Modernizr feature detection
loadPolyfill();
// Exécute ce code dans la page lorsque tout le
// reste est terminé
$(document).on( 'finalized', function() {
console.log('Callback: tout est fini d\'exécuter, finalisation');
});
},
// Exemple de function commune qui pourrait servir pour
// certains controlleurs seulement
notSoCommon: function() {
console.log('exécute une action générale spécifique à certaines pages');
// hauteur egal, peut aussi etre largueur egal
// $(document.getElementById('hauteurEgal')).equalize();
// fonction imprimer propre
imprimer('#imprimer');
// test retrouver dimension ecran via UTIL._page.width() type number
console.log('width',UTIL._page.width());
// test retrouver dimension ecran via UTIL._page.height type number
console.log('height',UTIL._page.height);
console.log('dimensions', UTIL._page.dimension());
// Test usage UTIL._lang
console.log(UTIL._lang);
// Test usage UTIL._page.isSplitContent()
console.log(UTIL._page.isSplitContent());
},
// Exemple d'action commune qui pourrait être appellé sans controlleur,
// comme dans les pages d'erreur par exemple, en utilisant
// <body data-action="error">...
error: function() {
console.log('oups, ceci ressemble à une page d\'erreur!');
}
},
// Chaque controlleur représente une page
home: {
init: function() {
console.log('initialisation de la page Home');
// Appelle une function semi-commune, qui pourrait servir à certains
// controlleurs seulement.
SITE.common.notSoCommon();
hoverStop('#hauteurEgal div');
},
slideshow: function() {
console.log('initialisation du slideshow spécifique à la page Home');
},
search: function() {
console.log('initialisation du search spécifique à la page Home');
// UTIL._validate();
console.log(typeof UTIL._validate);
}
},
contact: {
init: function() {
console.log('initialisation de la page Contact Us');
// Rappel dans une autre page d'une fonction prévu pour la home
SITE.home.slideshow();
}
}
};
// Pour tout le stock ré-utilisable (comme la variable de la langue, une
// function de validation, etc.), l'objet UTIL va être utilisé et peut
// facilement être appellé par l'objet SITE.
UTIL = {
_exec: function( controller, action ) {
var ns = SITE,
ctr = ( controller === undefined ) || ( controller == false ) ? 'common' : controller,
cmd = ( action === undefined ) ? 'init' : action;
if ( ns[ctr] && typeof( ns[ctr][cmd] ) === 'function' ) {
ns[ctr][cmd]();
}
},
// Va lire les propibuts appliqués sur la balise body (controlleur
// et action) et appelle ensuite les functions du site dans l'ordre.
_init: function() {
var body = document.body,
controller = body.getAttribute( 'data-controller' ),
actions = body.getAttribute( 'data-action' );
UTIL._exec( 'common' );
UTIL._exec( controller );
// Vérifie s'il y a au moins une action, et si oui les sépare
// dans un tableau avant de les exécuter une à une.
if ( actions ) {
actions = actions.split( ',' );
for ( var i = 0; i < actions.length; i++ ) {
UTIL._exec( controller, actions[i] );
}
}
// Déclanche la function "callback" exécutée uniquement
// lorsque tout le reste est terminé.
$( document ).trigger( 'finalized' );
},
// Quelques functions utilitaires que j'ai définies en exemple qui
// retournent de l'information sur la page courante.
// Éventuellement, ces functions utiles pourraient être déclarées
// comme des modules AMD et chargés selon les besoins avec requireJS!
_page: {
// Retourne si la page à une colonne de droite ou de gauche
isSplitContent: function() {
return $( 'aside' ).length;
},
// Retourne la largeur de la fenêtre
width: function() {
return $( window ).width();
},
// Retourne la hauteur de la fenêtre
height: $( window ).height(),
dimension: function(){
var heightScreen = $( window ).height(),
widthScreen = $( window ).width();
return {'height':heightScreen, 'width': widthScreen}
},
// À l'aide du plugin de validation, retourne si
// la page courante est valide ou non
isValid: function() {
var validator = $( 'form' )[0].validate();
if ( validator.numberOfInvalids() === 0 ) {
return true;
} else {
return false;
}
}
},
// Exemple de variable utilitaire privée qui peut être utilisée
// dans l'objet site via UTIL._lang
_lang: $( 'html' ).prop( 'lang' ),
_validate: function() {
// Chargez le plugin de validation et initialiser
$.getScript( 'http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js',
function() {
$( '#siteForm' ).validate();
}
);
},
// Function publique (par convention d'ecriture elle n'est pas prefixé d'un underscore)
log: function() {
console.log('public method that could be used for logging or something');
},
// Il serait aussi possible de rendre publique une function et
// de permettre d'utiliser des paramètre.
publicParams: function ( param ) {
console.log('param = ' + param);
}
};
// Ceci est le call qui met en branle tout le processus.
// Il est exécuté lorsque le DOM est fini de chargé (dom.ready) donc
// pas besoin de le réutiliser à l'intérieur des controlleurs/actions
// profil : 0.089ms, 12 calls
$( document ).ready( UTIL._init );
// (optionnel - en dev) Permet d'exposer l'interface publique du site.
return {
toOutLog:UTIL.log,
custom: UTIL.publicParams
};
} ( jQuery, window, document ) );
/*****************************************************************************
* TEST CASES
*****************************************************************************/
// 1- Chargement (auto execution) de la page avec data-controller="home" data-action="slideshow,search"
// Output (voir console):
//
// exécute une action générale
// initialisation de la page Home
// exécute une action générale spécifique à certaines pages
// initialisation du slideshow spécifique à la page Home
// initialisation du search spécifique à la page Home
// 2- Exécution de la function publique avec paramètre, va s'executer AVANT l'action générale
// UI_PROJECT.custom( 'mes paramètres personnalisés' );
// UI_PROJECT.toOutLog();
// Output (voir console):
//
// param = mes paramètres personnalisés
var UI_PROJECT = (function( $, window, document, undefined ) {
'use strict';
var SITE = {}, UTIL = SITE;
// Objet contenant toutes les fonctionnalitées propres au site en cours.
SITE = {
common: {
// Function commune exécutée dans toutes les pages
init: function() {
$(document).on( 'finalized', function() {});
},
action: function() {}
},
// Chaque controlleur représente une page
home: {
init: function() {},
action: function() {}
},
interne: {
init: function() {},
action: function() {}
}
};
UTIL = {
_exec: function( controller, action ) {
var ns = SITE,
ctr = ( controller === undefined ) || ( controller === false ) ? 'common' : controller,
cmd = ( action === undefined ) ? 'init' : action;
if ( ns[ctr] && typeof( ns[ctr][cmd] ) === 'function' ) {
ns[ctr][cmd]();
}
},
_init: function() {
var body = document.body,
controller = body.getAttribute( 'data-controller' ),
actions = body.getAttribute( 'data-action' );
UTIL._exec( 'common' );
UTIL._exec( controller );
if ( actions ) {
actions = actions.split( ',' );
for ( var i = 0; i < actions.length; i++ ) {
UTIL._exec( controller, actions[i] );
}
}
$( document ).trigger( 'finalized' );
},
_page: {},
};
$( document ).ready( UTIL._init );
// (optionnel - en dev) Permet d'exposer l'interface publique du site.
return {};
} ( jQuery, window, document ) );
/*
<div class="init" data-controller="controller_name" data-action="action_name"></div>
*/
var UI_PROJECT = (function( $, window, document, undefined ) {
'use strict';
var SITE = {}, UTIL = SITE;
// Objet contenant toutes les fonctionnalitées propres au site en cours.
SITE = {
common: {
// Function commune exécutée dans toutes les pages
init: function() {
$(document).on( 'finalized', function() {});
},
// commun étant appelé par defaut, un element concerné peut n'avoir qu'un data-action, pas besoin de lui spécifier un data-controller="commun"
action: function() {}
},
// Chaque controlleur represente un element
home: {
init: function() {},
action: function() {}
},
interne: {
init: function() {},
action: function() {}
}
};
UTIL = {
_exec: function( controller, action ) {
var ns = SITE,
ctr = ( controller === undefined ) || ( controller === false ) ? 'common' : controller,
cmd = ( action === undefined ) ? 'init' : action;
if ( ns[ctr] && typeof( ns[ctr][cmd] ) === 'function' ) {
ns[ctr][cmd]();
}
},
_init: function() {
var context = document.querySelectorAll('.init');
UTIL._exec( 'common' );
$(context).each(function(){
var that = $(this),
controller = that.attr( 'data-controller' ),
actions = that.attr( 'data-action' );
UTIL._exec( controller );
if ( actions ) {
actions = actions.split( ',' );
for ( var i = 0; i < actions.length; i++ ) {
UTIL._exec( controller, actions[i] );
}
}
});
$( document ).trigger( 'finalized' );
},
_page: {},
};
$( document ).ready( UTIL._init );
// (optionnel - en dev) Permet d'exposer l'interface publique du site.
return {};
} ( jQuery, window, document ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment