Created
September 30, 2014 12:01
-
-
Save ethyde/f79bcc77c85037d64c1d to your computer and use it in GitHub Desktop.
Garber Irish and variation around it. See also : http://techblog.treenodes.com/index.php/2012/04/19/organize-javascript-and-jquery-events-dom-ready-execution/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * | |
| * 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 ) ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| <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