Как убрать DOM-элементы из модала при закрытии - PullRequest
1 голос
/ 17 января 2020

Предыстория: на момент написания, Fomanti c -UI - это разветвленная ветка разработки Semanti c -UI, которая однажды будет свернута в Semanti c -UI и пока что является поддерживаемый фактом род Semanti c -UI.

Проблема: Fomanti c -UI предоставляет модальные возможности - просто вызовите .modal () для элемента JQuery et voila. Однако, когда модальное окно закрыто, элементы DOM для модального элемента остаются скрытыми в DOM. Мой вариант использования требует удаления этих элементов, но меня беспокоит «оставшаяся» разводка для модальных возможностей.

Проведенное исследование: документация FUI по модалам полезна, но написана с точки зрения поднятия модала, но не совсем его снятия.

Воспроизведение. Приведенный ниже фрагмент кода представляет собой основанный на коде подход к созданию модального и проводного соединения для слушателей кнопок. Нажмите кнопку, чтобы открыть модал, затем нажмите кнопку закрытия. Через две секунды будет показано простое число JQuery оставшихся модальных элементов DOM - оно должно быть нулевым, но будет 1.

Примечания:

1 - модальное ПУИ имеет разочаровывающую особенность: автоматическое закрытие модального окна при нажатии любой кнопки. У него есть одно условие сохранения, заключающееся в том, что если обработчик события сработавшей кнопки возвращает значение false, то модальный режим остается открытым. Очевидно, что если вы проводите проверку формы и т. Д. c, вам нужно это знать. Кроме того, если вы предпочитаете переопределить функцию по умолчанию для всех кнопок, верните false из функции onHide, например

element.modal('setting', 'onHide', function(){ return false; });
element.modal('show');

2 - в этом фрагменте используются версии FUI 'dist' для dist. Поскольку FUI ​​часто меняется, фрагмент кода может перестать работать, если к моменту его просмотра произошли критические изменения. На момент написания официального релиза на jsdelivr cdn 2.8.3. (Отредактировано 17 января 2020 г.).

var fnSpecial = function(){
	console.log('Close button click function - return true to hide');
  // ... do function activity here....
  return true;
}

$('#b1').on('click', function(){
	
  makeModal({
  	title: 'I be modal',
    content: 'Modal be I !',
    actions: [
      { text: 'Close', fn: fnSpecial}, // for more buttons in the modal add more entries here. 
    ]    
  })

})



function makeModal(opts){
  // create your modal element - I grab the modal template
  var tplt = $('#modalTemplate').html();

  // defaults for modal create
  var obj = {
    title: 'No title !',
    content: 'No content',
    actions: [
    ]
  }

  // Merge the above defaults with the user-supplied options
  obj = $.extend(obj, opts);

  // Apply modal options to the soon-to-be modal element 
  var ele = $(tplt);
  ele.find('.modalHeading').html(obj.title);
  ele.find('.modalBody').html(obj.content);
  ele.addClass('modalContentCopy');

	var modalButtons = ele.find('.modalButtons');
	for (var i =0, max = obj.actions.length; i < max; i = i + 1 ){
  
  	var btn = $('<button >' + obj.actions[i].text + '</button>');
    var fn = obj.actions[i].fn;
    btn.data('fn', fn); // store the callback on the element to avoid closures.
    
    btn.appendTo(modalButtons);
    
    btn.on('click', function(e){    
    	var fn = $(this).data('fn');
      
      if (typeof fn === "function"){
      
        var hide = fn(); // IMPORTANT: the function triggered for the button must return true to close the modal or false to keep it open !

        console.log('Button says hide=' + hide)

        if (hide){

            ele.modal('destroy');
            ele.modal('hide');

              $('#info')
                .html('***');
                
            // wait 2 secs and see if the DOM element has gone
            setTimeout( function(){
              var num = $('.modalContentCopy').length;
              $('#info')
                .html(num)
                .css({ backgroundColor: (num === 0 ? 'lime' : 'red')});
              }, 2000);
        }
      }
      
    });  
  }

	// Simple example of how to reveal the modal element as a f-ui modal 
  ele
    .appendTo($('body'))
    .modal('setting', 'transition', "vertical flip")
	.modal('setting', 'onHide', function(){ return false; }) // stop the auto-closing by FUI
	  .modal('show'); // finally show the modal
    

}
p {
  padding: 10px;
}

.modalContent {
  border: 1px solid lime;
  margin: 5px;
  padding: 5px;
}

.modalHeading {
  border: 1px solid cyan;
  margin: 5px;
  padding: 5px;
}

.modalBody {
  border: 1px solid magenta;
  margin: 5px;
  padding: 5px;
}

.modalContent {
  background-color: white;
}

.ipt {
  margin: 5px 20px;
  display: block;
}
<link href="https://fomantic-ui.com/dist/semantic.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://fomantic-ui.com/dist/semantic.js"></script>

<body>
<p>Click the 'show modal' button to open a modal, then the 'Close' button to close it. See console for messages. The critical point is the final display of the modal artefact count which appears after a 2 second delay, allowing for transitions to complete. We want a zero - what will it be?
</p>

<p>
  <button id='b1'>Show a modal</button> <span>Count of DOM artifacts after close should be zero - value is >>>>> </span><span id='info'>[value will appear here after modal close]</span>
</p>

<div id='modalTemplate' style='display: none;'>
  <div class='modalContent'>
    <div class='modalHeading'>
       I am the heading
    </div>
    <div class='modalBody'>
      I am the body
    </div>
    
    <div class='modalButtons'>
    </div>
    
  </div>
</div>

</body>

1 Ответ

0 голосов
/ 17 января 2020

Ответ состоит в том, чтобы использовать в настоящее время недокументированные функции модального ('уничтожить') и модального ('удалить') после анимация закрытия завершена.

.modal('setting', 'onVisible', function(){
  ele
    .on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
     function(e){
        console.log('Animation complete')
        $(this).off(e);    // remove this listener
        $(this).modal('destroy');  // take down the modal object
        $(this).remove();    // remove the modal element, at last.
     });
  })

Если вы не наблюдаете завершение закрывающего перехода, тогда FUI выдает предупреждение о переходах на отсутствующие элементы.

Modal.Destroy очищает модальный объект, который FUI присоединяет к JQuery модальный элемент. Ele.remove () - это стандартная JQuery функция удаления . В результате, согласно моему требованию, ранее сделанный модальный элемент удаляется из DOM.

будет одним артефактом, который представляет собой DU-диммер FUI, но мое тестирование на сегодняшний день показывает, что это не проблема, то есть они не видны и не сгущаются со временем.

См. Фрагмент ниже для рабочего примера. Посмотрите в конце раздела JS для решения.

var fnSpecial = function(){
	console.log('Close button click function - return true to hide');
  // ... do function activity here....
  return true;
}

$('#b1').on('click', function(){
	
  makeModal({
  	title: 'I be modal',
    content: 'Modal be I !',
    actions: [
      { text: 'Close', fn: fnSpecial}, // for more buttons in the modal add more entries here. 
    ]    
  })

})



function makeModal(opts){
  // create your modal element - I grab the modal template
  var tplt = $('#modalTemplate').html();

  // defaults for modal create
  var obj = {
    title: 'No title !',
    content: 'No content',
    actions: [
    ]
  }

  // Merge the above defaults with the user-supplied options
  obj = $.extend(obj, opts);

  // Apply modal options to the soon-to-be modal element 
  var ele = $(tplt);
  ele.find('.modalHeading').html(obj.title);
  ele.find('.modalBody').html(obj.content);
  ele.addClass('modalContentCopy');

	var modalButtons = ele.find('.modalButtons');
	for (var i =0, max = obj.actions.length; i < max; i = i + 1 ){
  
  	var btn = $('<button >' + obj.actions[i].text + '</button>');
    var fn = obj.actions[i].fn;
    btn.data('fn', fn); // store the callback on the element to avoid closures.
    
    btn.appendTo(modalButtons);
    
    btn.on('click', function(e){    
    	var fn = $(this).data('fn');
      
      if (typeof fn === "function"){
      
        var hide = fn(); // IMPORTANT: the function triggered for the button must return true to close the modal or false to keep it open !

        console.log('Button says hide=' + hide)

        if (hide){

            ele.modal('destroy');
            ele.modal('hide');

              $('#info')
                .html('***');
                
            // wait 2 secs and see if the DOM element has gone
            setTimeout( function(){
              var num = $('#theBody').find('.modalContentCopy').length;
              $('#info')
                .html(num)
                .css({ backgroundColor: (num === 0 ? 'lime' : 'red')});
              }, 2000);
        }
      }
      
    });  
  }

 
	// Simple example of how to reveal the modal element as a f-ui modal 
  ele
    .appendTo($('body'))

    .modal('setting', 'transition', "vertical flip")
    .modal('setting', 'onHide', function(){ return false; }) // stop any button closing the modal

    // <solution starts>
    .modal('setting', 'onVisible', function(){
      ele
        .on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
         function(e){
            console.log('Animation complete')
            $(this).off(e);
            $(this).modal('destroy');
            $(this).remove();
         });
      })
    // <solution ends>
    
	  .modal('show'); // finally show the modal
    


 

}
p {
  padding: 10px;
}

.modalContent {
  border: 1px solid lime;
  margin: 5px;
  padding: 5px;
}

.modalHeading {
  border: 1px solid cyan;
  margin: 5px;
  padding: 5px;
}

.modalBody {
  border: 1px solid magenta;
  margin: 5px;
  padding: 5px;
}

.modalContent {
  background-color: white;
}

.ipt {
  margin: 5px 20px;
  display: block;
}
<link href="https://fomantic-ui.com/dist/semantic.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://fomantic-ui.com/dist/semantic.js"></script>

<body id='theBody'>
<p>Click the 'show modal' button to open a modal, then the 'Close' button to close it. See console for messages. The critical point is the final display of the modal artefact count which appears after a 2 second delay, allowing for transitions to complete. We want a zero - what will it be?
</p>

<p>
  <button id='b1'>Show a modal</button> <span>Count of DOM artifacts after close should be zero - value is >>>>> </span><span id='info'>[value will appear here after modal close]</span>
</p>

<div id='modalTemplate' style='display: none;'>
  <div class='modalContent'>
    <div class='modalHeading'>
       I am the heading
    </div>
    <div class='modalBody'>
      I am the body
    </div>
    
    <div class='modalButtons'>
    </div>
    
  </div>
</div>

</body>
...