A étudier également: Lazy Loading JavaScript Modules With ConditionerJS sur Smashing Magazine.
ATTENTION: Note that this only works in browsers that support Dynamic import(). At the time of this writing that would be Chrome 63 and Safari 11.
Comme d’hab on pourra pas s’en servir parce qu’on doit tjrs avoir une compatibilité avec un vieux navigateur à la noix.
Télécharger une démo
(zip 35ko).
Article de Jean-Luc BOES sur le blog Netapsys: Introduction aux développements sur la suite SAP Hybris (section Le javascript).
Le javascript dans Hybris est du javascript standard mais il est intéressant de remarquer la fonction d’autoload et l’utilisation des espaces de noms. Chaque fichier javascript doit définir une variable
_autoload
et chaque fonction remplissant les conditions seront appelé une fois le DOM de la page web chargée.
[à traduire] to avoid collisions and improve code organization when working with components under another namespace
Remarque
Attention: je ne suis (pour l’instant) pas parvenu à faire fonctionner l'autoload
lorsqu’une condition doit être remplie (dans notre exemple ci-dessous ["bindCarousel", $(".js-owl-carousel").length != 0]
) et que les sources JS sont chargées au sein de l’élément HEAD
d’un document. Il faut obligatoirement charger les sources Js (au moins l’autoload et les fichiers qui y font référence) tout en bas du DOM, juste avant la fermeture de la balise BODY
, et ce même si le code JS est encapsulé dans un $(document).ready(function(){});
ou équivalent.
Cela ne devrait pas être un problème en soi car faire appel aux sources JS en bas de page est une bonne pratique, mais d’expérience ce n’est pas toujours possible…
1 2 3 |
<script src="js/autoload.js"></script> <script src="js/carousel.js"></script> </body> |
Source de la fonction _autoload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
//################################################################ //#### Autoload //################################################################ // // ACC.sample={ // _autoload: [ // "samplefunction", // ["somefunction", "some expression to test"] // ["somefunction","some expression to test","elsefunction"] // ], // samplefunction:function(){ // //... do some suff here, executed every time ... // }, // somefunction:function(){ // //... do some suff here. if expression match ... // }, // elsefunction:function(){ // //... do some suff here. if expression NOT match ... // } // } // // sample expression: $(".js-storefinder-map").length != 0 function _autoload(){ $.each(ACC,function(section,obj){ if($.isArray(obj._autoload)){ $.each(obj._autoload,function(key,value){ if($.isArray(value)){ if(value[1]){ ACC[section][value[0]](); }else{ if(value[2]){ ACC[section][value[2]]() } } }else{ ACC[section][value](); } }) } }) } $(function(){ _autoload(); }); |
Assurez vous que ACC
soit disponible
1 |
var ACC = ACC || {}; // make sure ACC is available |
Exemple d’utilisation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
ACC.carousel = { _autoload: [ ["bindCarousel", $(".js-owl-carousel").length != 0] ], carouselConfig:{ "default":{ navigation:true, navigationText : ["<span class='glyphicon glyphicon-chevron-left'></span>", "<span class='glyphicon glyphicon-chevron-right'></span>"], pagination:false, itemsCustom : [[0, 2], [640, 4], [1024, 5], [1400, 7]] }, "rotating-image":{ navigation:false, pagination:true, singleItem : true, }, "lazy-reference":{ navigation:true, navigationText : ["<span class='glyphicon glyphicon-chevron-left'></span>", "<span class='glyphicon glyphicon-chevron-right'></span>"], pagination:false, itemsDesktop : [5000,7], itemsDesktopSmall : [1200,5], itemsTablet: [768,4], itemsMobile : [480,3], lazyLoad:true, }, }, bindCarousel: function(){ $(".js-owl-carousel").each(function(){ var $c = $(this) $.each(ACC.carousel.carouselConfig,function(key,config){ if($c.hasClass("js-owl-"+key)){ var $e = $(".js-owl-"+key); $e.owlCarousel(config); } }); }); } }; |
Cette méthodologie consiste à limiter le nombre d’initialisation d’un même plugin (ici Owl Carousel). On l’initialise une seule fois via la classe .js-owl-carousel
affectée à tous les carousels utilisés dans le site. On passe ensuite les paramètres pour différentes configs (default
, rotating-image
, lazy-reference
) en fonction d’une classe (.js-owl-default
, .js-owl-rotating-image
, .js-owl-lazy-reference
) présente dans la vue.
Vue HTML pour un carousel avec config « lazy-reference » (voir au-dessus)
Notez ligne 8 la présence de la classe .js-owl-lazy-reference
(qui déclenche la config) sur le même élément que la classe .js-owl-carousel
(qui initialise le plug-in).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<c:choose> <c:when test="${not empty productReferences and component.maximumNumberProducts > 0}"> <div class="carousel-component"> <div class="headline">${component.title}</div> <div class="carousel js-owl-carousel js-owl-lazy-reference js-owl-carousel-reference"> <div id="quickViewTitle" class="quickView-header" style="display:none"> <div class="headline"> <span class="headline-text"><spring:theme code="popup.quick.view.select"/></span> </div> </div> <c:forEach end="${component.maximumNumberProducts}" items="${productReferences}" var="productReference"> <c:url value="${productReference.target.url}/quickView" var="productUrl"/> <div class="item"> <a href="${productUrl}" class="js-reference-item" data-quickview-title="<spring:theme code="popup.quick.view.select"/></span>"> <div class="thumb"> <product:productPrimaryReferenceImage product="${productReference.target}" format="product" /> </div> <c:if test="${component.displayProductTitles}"> <div class="item-name">${productReference.target.name}</div> </c:if> <c:if test="${component.displayProductPrices}"> <div class="priceContainer"> <format:fromPrice priceData="${productReference.target.price}" /> </div> </c:if> </a> </div> </c:forEach> </div> </div> </c:when> <c:otherwise> <component:emptyComponent /> </c:otherwise> </c:choose> |
Modifier à la volée les paramètres d’un objet
1 |
var ACC.carousel.carouselConfig.default.navigation = false; |
Conclusion
Je n’ai pas un niveau de ninja en javaScript (je pratique pas mal jQuery pour répondre à des contraintes liées au front). Cette organisation du code JS autour d’une fonction _autoload
(la méthodologie adoptée par les concepteurs d’Hybris) m’a permis de rentrer facilement dans le code sans lire aucune documentation et de greffer rapidement mes propres fonctions à l’existant sans pour autant le dénaturer, tant j’ai trouvé cette ossature facile à comprendre. C’est là l’intérêt de l’utilisation d’un pattern.
Pour aller plus loin
et ses patterns (et notamment le namespaced pattern dont la philosophie se rapproche de la méthodologie JS Hybris.