Dans ces dernières versions la modal de BS permet justement de s'empiler mais malheureusement il y a un effet, que je trouve désagréable, c'est qu'a chaque ouverture d'une fenêtre un élément "backdrop" viens s'ajouter au DOM, rendant l'arrière plan de plus en plus opaque au fur et à mesure de l'ouverture de fenêtre.
Je me suis donc penché sur les solutions permettant de minimiser l'effet et deux solutions s'offrent à nous:
- Soit nous définissons un code "rustine" qui permettra de corriger le problème.
- Soit nous agissons directement au niveau du plugin.
La première solution est normalement celle que tout le monde devrait choisir, en effet les modals BS offrent une API permettant d'agir sur les éléments à 4 étapes de l'initialisation et de la destruction des fenêtres. De plus agir de cette manière nous assure l'intégrité du framework BS notamment lorsque décision est prise de le mettre à jour.
Malheureusement cette solution souffre d'un problème de "timing" dans notre cas d'étude, en agissant de cette manière et avec le même code que je propose ci dessous, vous constaterez des effets visuels indésirables.
C'est pourquoi j'ai opté pour la deuxième solution, un peu plus contraignante mais très fonctionnelle:
Après avoir lut le code du plugin deux fonctions nous intéressent:
Modal.prototype.show et Modal.prototype.backdrop.
Fonction Show:
Code javascript : | Sélectionner tout |
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | Modal.prototype.show = function (_relatedTarget) { var that = this var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) this.$element.trigger(e) if (this.isShown || e.isDefaultPrevented()) return this.isShown = true this.checkScrollbar() this.setScrollbar() this.$body .addClass('modal-open') // Nous intervenons ici afin d'enregistrer un nombre de modals ouvertes .data('modalIndice', this.$body.data('modalIndice') ? this.$body.data('modalIndice') + 1 : 1 ) this.escape() this.resize() this.$element .on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) // Grace à la donnée modalIndice nous pouvons attribuer un numéro ordonné à la modal actuelle. .data('modalOrder', this.$body.data('modalIndice')) this.$dialog.on('mousedown.dismiss.bs.modal', function () { that.$element.one('mouseup.dismiss.bs.modal', function (e) { if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true }) }) this.backdrop(function () { var transition = $.support.transition && that.$element.hasClass('fade') if (!that.$element.parent().length) { that.$element.appendTo(that.$body) // don't move modals dom position } that.$element .show() .scrollTop(0) that.adjustDialog() if (transition) { that.$element[0].offsetWidth // force reflow } that.$element .addClass('in') .attr('aria-hidden', false) that.enforceFocus() var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) transition ? that.$dialog // wait for modal to slide in .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e) }) } |
Fonction Backdrop:
Code javascript : | Sélectionner tout |
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | Modal.prototype.backdrop = function (callback) { var that = this var animate = this.$element.hasClass('fade') ? 'fade' : '' var lastVisibleBackdrop = this.$body.find('.modal-backdrop:last:visible') // Nous récupérons le dernier arrière plan visible var lastHiddenBackdrop = this.$body.find('.modal-backdrop:hidden:last') // Nous récupérons le dernier arrière plan caché if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate // On cache tous les autres backdrop à part celui actif puis on réduis le z-index des autres modals pour les faire passer sous le backdrop actif if (lastVisibleBackdrop.length) { lastVisibleBackdrop.hide(); this.$body.find('.modal:visible').each(function() { if ($(this)[0] !== that.$element[0]) { $(this).css('z-index', 1030) } }) } this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') .appendTo(this.$body) this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { if (this.ignoreBackdropClick) { this.ignoreBackdropClick = false return } if (e.target !== e.currentTarget) return this.options.backdrop == 'static' ? this.$element[0].focus() : this.hide() }, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow this.$backdrop.addClass('in') if (!callback) return doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback() } else if (!this.isShown && this.$backdrop) { this.$backdrop.removeClass('in') // On affiche le dernier backdrop caché puis on augmente le z-index de la modal ayant l'indice juste au dessous de celle qui est active et en cours de destruction if (lastHiddenBackdrop.length) { lastHiddenBackdrop.show(); this.$body.find('.modal:visible').each(function() { if ($(this).data('modalOrder') === that.$element.data('modalOrder') - 1) { $(this).css('z-index', 1050) } }) } var callbackRemove = function () { that.removeBackdrop() callback && callback() } $.support.transition && this.$element.hasClass('fade') ? this.$backdrop .one('bsTransitionEnd', callbackRemove) .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove() } else if (callback) { callback() } } |
Et le tour est joué

Avis, remarques et optimisations sont les bienvenus

Le code est disponible ici
Vous avez lu gratuitement 0 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.