Как предотвратить переполнение родительского содержимого вложенного DIV при изменении размера родительского элемента? - PullRequest
0 голосов
/ 21 февраля 2019

ОСНОВНОЙ ВОПРОС: Мне нужно правильно установить рост ребенка <div>, который вложен в изменяемый размер родительский <div>.При изменении размера родительского элемента дочерний элемент не должен выходить за пределы родительского.Сам родитель должен быть ограничен, чтобы не допустить его выхода за пределы минимальной прокручиваемой границы ребенка.

DEAD ENDS: за несколько часов исследований я узнал, что CSS, даже с функцией calc(), не в состоянии динамически устанавливать высоту и ширину <div>.Кроме того, кажется, что для предотвращения переполнения дочерним элементом <div> измерений его родителя сам родитель должен иметь фиксированный размер.В последнем случае стили, такие как height: auto; height: inherit; и height: 100%;, могут все дать одинаковые результаты.

Подобные вопросы были заданы здесь ранее, но ни один из найденных мною вопросов не отвечает на вопрос об изменении размера.,Например, решение, предоставленное для следующего вопроса, неправильно решает мою проблему.

Предотвращение переполнения дочернего элемента div родительским элементом div

В моей ситуации у меня есть <div>, размер которого будет изменен пользователем и / или перетащен в любую часть экрана.Содержимое этого <div> должно автоматически прокручиваться, если это необходимо.Ни в коем случае они не должны превышать размеры контейнера <div>, размер которого можно изменять.Моя ситуация требует, чтобы я не использовал jQuery, но решение JavaScript приветствуется.(Даже PERL может быть полезен, так как я буду обслуживать страницу и обновлять ее через AJAX с платформы Perl.)

Ниже приводится полностью рабочий пример, который показывает, как дочерний элемент <div> превосходит своего родителя,даже с включенной прокруткой, и это происходит независимо от того, как изменяется размер родительского элемента <div>.(Я проверил это в Firefox и Safari.)

Обратите внимание, что в моем реальном приложении содержимое <div> будет предоставляться через AJAX для каждого пользователя из меню <select>, и содержимое будет различатьсядлины.Независимо от возвращенной длины контейнер / родительский элемент <div> должен оставаться того же размера, что и пользовательская настройка.

<!DOCTYPE html>
<HTML lang="utf8">
<head>
<title>Example of Resizable/Draggable Container Div with Nested (Overflowing) Contents</title>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">

<style type="text/css">
.nested {
  background-color: #ffffcc;
  overflow-y: auto;
  overflow-x: hidden;
  max-height: 720px;
  height: inherit;
  color: #000;
  text-align: left;
  font-weight: normal;
  } 
.resizable {
  background: white;
  min-width: 100px;
  min-height: 120px;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 80px;
  left: 60px;
display: -webkit-box;   /* OLD - iOS 6-, Safari 3.1-6, BB7 */
display: -ms-flexbox;  /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.resizable .resizers{
  width: 100%;
  height: 100%;
  border: 3px solid #4286f4;
  box-sizing: border-box;
}
.resizable .resizers .resizer{
  width: 3px;
  height: 5px;
  border-radius: 50%;  /*magic to turn square into circle*/
  background: black;
  border: 3px solid #4286f4;
  position: absolute;
  }
.resizable .resizers .resizer.top-left {
  left: -2px;
  top: -2px;
  cursor: nwse-resize; /*resizer cursor*/
}
.resizable .resizers .resizer.top-right {
  right: -2px;
  top: -2px;
  cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-left {
  left: -2px;
  bottom: -2px;
  cursor: nesw-resize;
}
.resizable .resizers .resizer.bottom-right {
  right: -2px;
  bottom: -2px;
  cursor: nwse-resize;
}  
#dragselection {
    position: absolute;
    top: 6px;
    left: 3%;
    z-index: 8;
    background-color: #f1f1f1;
    border: 1px solid #d3d3d3;
display: -webkit-box;   /* OLD - iOS 6-, Safari 3.1-6, BB7 */
display: -ms-flexbox;  /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.header {
    padding: 4px;
    margin-left: 2px;
    margin-right: 2px;
    margin-top: 4px;
    margin-bottom: 4px;
    text-align: center;
    cursor: move;
    z-index: 10;
    background-color: #2168a8;
    color: #fff;
    font-size: 14px;
    font-weight: bold;
    }
#CV1 {
    min-width:150px; 
    min-height:150px; 
    }    
.top-banner {
display: inline-block; 
margin-top: 0px; 
margin-right: 7px; 
margin-left: 5px; 
margin-bottom: 7px; 
background-color: #afb; 
border-radius: 12px; 
opacity: 0.9; 
box-shadow: 3px 3px #878087; 
max-width: 100%; 
height: auto;
align: auto;
text-align: center;
    }     
</style>


</head>
<body onload="dragElement('dragselection');">

<div class="top-banner">
<p style="margin-top: 30px; margin-right: 60px; margin-left: 60px; margin-bottom: 30px; text-align:center; font-size: 2.0em; color:#fff;text-shadow: 2px 1px 2px #050050;">&#9840; Easy Text Reference &#9840;</p>
</div>

<form id="myform" name="nmyform" method="POST" accept-charset="utf-8" action="URL_for_CGI" >
<article>

<h1>Example:</h1>

<div id="flex-box" name="nflex-box" class="flex-container">

<div class="container" id="mainscreen" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="header flex-container-head" id="header-box" name="nheader-box">  

       
<div class='resizable' id="dragselection" style="border: 1px solid gray; font-size:18px; height: 250px; ">
  <div class='resizers'>
    <div class='resizer top-left'></div>
    <div class='resizer top-right'></div>
    <div class='resizer bottom-left'></div>
    <div class='resizer bottom-right'></div>
    
    <div id="dragselectionheader" class='header'>
    Your Text Selection
 
  <select id="get_text" name="nget_text"  onchange="getAjaxResult(['selection_text','recordnum'], 'POST'); ">
<option value="">---- Selection Menu ----</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
   
   </div>
    
  <div id="CV1" class="nested">
  A sample text:
  
  In the annals of human history, the growth of nations, the rise and fall of empires, appear as if dependent on the will and prowess of man; the shaping of events seems, to a great degree, to be determined by his power, ambition, or caprice. But in the word of God the curtain is drawn aside, and we behold, above, behind, and through all the play and counterplay of human interest and power and passions, the agencies of the All-merciful One, silently, patiently working out the counsels of His own will.  (Prophets and Kings, p. 499)
  </div>
  </div>
</div>


</div>
</div>

</div>

</article>

</form>


<script type="text/javascript">

/* Make the DIV element draggable: */
dragElement(document.getElementById(("dragselection")));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from: */
    document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  } else {
    /* otherwise, move the DIV from anywhere inside the DIV: */
    elmnt.onmousedown = dragMouseDown;
  }

  function dragMouseDown(e) {
    e = e || window.event;
    /* get the mouse cursor position at startup: */
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    /* call a function whenever the cursor moves: */
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    e = e || window.event;
    /* calculate the new cursor position: */
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    /* set the element's new position: */
    if ((elmnt.offsetTop - pos2) < 0) { 
         elmnt.style.top = '0px'
    } else {     
         elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
    }     
    if ((elmnt.offsetLeft - pos1) < 0) {
         elmnt.style.left = '0px'
    } else {
         elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    }
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;    
  }
}

/* Modeled after: 
https://medium.com/the-z/making-a-resizable-div-in-js-is-not-easy-as-you-think-bda19a1bc53d 
*/

function makeResizableDiv(div) {
  const element = document.querySelector(div);
  const resizers = document.querySelectorAll(div + ' .resizer')
  const minimum_size = 120;
  var original_width = 0;
  var original_height = 0;
  var original_x = 0;
  var original_y = 0;
  var original_mouse_x = 0;
  var original_mouse_y = 0;

  for (var i = 0;i < resizers.length; i++) {
    const currentResizer = resizers[i];
    currentResizer.addEventListener('mousedown', function(e) {
      e.preventDefault()
      original_width = parseFloat(getComputedStyle(element, null).getPropertyValue('width').replace('px', ''));
      original_height = parseFloat(getComputedStyle(element, null).getPropertyValue('height').replace('px', ''));
      original_x = element.getBoundingClientRect().left;
      original_y = element.getBoundingClientRect().top;
      original_mouse_x = e.pageX;
      original_mouse_y = e.pageY;
      window.addEventListener('mousemove', resize)
      window.addEventListener('mouseup', stopResize)
    })
    
    function resize(e) {
      if (currentResizer.classList.contains('bottom-right')) {
        const width = original_width + (e.pageX - original_mouse_x);     
        const height = original_height + (e.pageY - original_mouse_y)     
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x + 'px' 
        }
        if (height > minimum_size) {
          element.style.height = height + 'px'     
          element.style.top = original_y + 'px' 
        }
      }
      else if (currentResizer.classList.contains('bottom-left')) {
        const height = original_height + (e.pageY - original_mouse_y)     
        const width = original_width - (e.pageX - original_mouse_x)     
        if (height > minimum_size) {
          element.style.height = height + 'px'     
          element.style.top = original_y+'px' 
        }
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x+(e.pageX-original_mouse_x)+'px' 
        }
      }
      else if (currentResizer.classList.contains('top-right')) {
        const width = original_width + (e.pageX - original_mouse_x)     
        const height = original_height - (e.pageY - original_mouse_y)     
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x + 'px'
        }
        if (height > minimum_size) {
          if (original_y+(e.pageY-original_mouse_y) < 0 ) {
            element.style.top = '0px'
          } else {
            element.style.height = height + 'px'     
            element.style.top = original_y+(e.pageY-original_mouse_y)+'px' 
          }
        }
      }
      else {          /* top-left */
        const width = original_width - (e.pageX - original_mouse_x)     
        const height = original_height - (e.pageY - original_mouse_y)     
        if (width > minimum_size) {
          element.style.width = width + 'px'     
          element.style.left = original_x+(e.pageX-original_mouse_x)+'px' 
        }
        if (height > minimum_size) {
         if (original_y+(e.pageY-original_mouse_y) < 0 ) {
            element.style.top = '0px'
          } else {
            element.style.height = height + 'px'     
            element.style.top = original_y+(e.pageY-original_mouse_y)+'px' 
          }
        }
      }
    }
    
    function stopResize() {
      window.removeEventListener('mousemove', resize)
    }
  }
}
makeResizableDiv('.resizable')

</script>
</body>
</html>

ОБНОВЛЕНИЯ: я скорректировал приведенный выше код, чтобы отразить предложения, представленные на данный момент.К сожалению, я не могу, с этой конфигурацией, ограничить ширину родителя.Все, что меньше 100% (или авто), затем наследуется ребенком с неблагоприятными результатами.Однако я не хочу, чтобы родитель занимал всю ширину экрана, поэтому это решение неадекватно.

Теперь я нашел обходной путь, который может использоваться с Firefox.Мой Safari не поддерживает опции flex, поэтому кросс-браузерное решение все еще отсутствует.Для Firefox следующий код JavaScript может установить позицию <div> после загрузки страницы следующим образом:

document.getElementById('dragselection').setAttribute("style","width:320px; height:240px; font-size:18px;");

Теперь я узнал, что следующий код более кросс-браузерно совместим и заставляет Safari отображатьэто правильно.

display: -webkit-box;   /* OLD - iOS 6-, Safari 3.1-6, BB7 */
display: -ms-flexbox;  /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Safari 6.1+. iOS 7.1+, BB10 */
display: flex;         /* NEW, Spec - Firefox, Chrome, Opera */
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;

Я обновил этот код в двух местах в примере сценария.Это может быть работоспособным на этом этапе.

1 Ответ

0 голосов
/ 21 февраля 2019

Вы можете использовать flexbox css здесь.Если родительский DIV будет flex, flex-direction: column.

А также для минимального перетаскиваемого экрана высота родительского элемента равна 120px, а минимальная высота дочернего элемента равна 150px, удалите стили из # CV1.

Можете ли вы обновить эти стили и проверить?

.resizable .resizers{
  width: 100%;
  height: 100%;
  border: 3px solid #4286f4;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}

.nested {
  background-color: #ffffcc;
  overflow-y: auto;
  overflow-x: hidden;
  max-height: 720px;
  height: inherit;
  color: #000;
  text-align: left;
  font-weight: normal;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...