Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Изменение свойства CSS (https://javascript.ru/forum/events/29626-izmenenie-svojjstva-css.html)

Squirr 05.07.2012 13:24

Изменение свойства CSS
 
Здравствуйте, уважаемые форумчане.
Проблема, вроде бы простая, но у меня её решить не получается. В JavaScript я не особо силён, поэтому не пинайте сильно.
Есть 2 div блока. У обоих высота не задана, т.е. зависит от количества контента в них. Причём, у одного из блоков высота динамически меняется при нажатии на ссылку в нём. Требуется сделать так, чтобы высота блоков до раскрытия динамического блока была одинаковой (вот хочется заказчику так, и ничего он слушать не хочет).
Я попытался решить проблему следующим образом:
Код:

#contentMenuPersonal
{
        display: block;
        z-index: 10;
        position: relative;
        margin: 80px 10px 30px;
        float: left;
        width: 175px;
}
#bannerBig1
{
        width: 680px;
        z-index: 10;
        position: relative;
        margin: 80px 10px 30px;
        float: left;

}

<script type="text/javascript">
		function change_visibility (block_4_close, block_4_open)
		{
			document.getElementById(block_4_close).style.display='none';
			document.getElementById(block_4_open).style.display='';
		}

		var size = document.getElementById(contentMenuPersonal).style.height;
		
		var dynamicSize = document.getElementById(bannerBig1).style.height;
		
		if (document.getElementById(block_4_close).style.display='none') {dynamicSize = size;}
	</script>

<div id="contentMenuPersonal">
    	    	<table cellspacing="10px" align="center">
               ...текст...
                </table>
          </div>
          <div id="bannerBig1" style="padding: 15px;">
		<div id="r0">
               ...текст...
		<a href="javascript:change_visibility ('r0', 'r1')">Читать далее &rarr;</a>
		</div>
		<div id="r1" style="display: none;">
               ...текст...
        	<a href="javascript:change_visibility ('r1', 'r0')">&larr; скрыть текст</a>
		</div>
         </div>

Но ни в одном из браузеров вообще ничего не произошло.

Deff 05.07.2012 13:29

Squirr,
var dynamicSize = document.getElementById(bannerBig1).style.height;
if (document.getElementById(block_4_close).style.disp lay='none') {dynamicSize = size;}

красное числовое значение, -а не объект
для объекта - так
Цитата:

var dynObj = document.getElementById(bannerBig1);
if (document.getElementById(block_4_close).style.disp lay='none') {dynObj .style.height = size;}

Squirr 05.07.2012 15:28

Deff, спасибо за помощь. Но ваш вариант работает только в FF.
Изменение конструкции на document.all.contentMenuPersonal.style.height тоже не помогло.

lord2kim 05.07.2012 15:50

Цитата:

Сообщение от Squirr (Сообщение 186506)
Deff, спасибо за помощь. Но ваш вариант работает только в FF.
Изменение конструкции на document.all.contentMenuPersonal.style.height тоже не помогло.

document.getElementById("contentMenuPersonal")...

идентификаторы в кавычки нужно ставить (contentMenuPersonal, bannerBig1), но не block_4_close, block_4_open

12 строка в первом посте в первом коде не будет работать
if (document.getElementById(block_4_close).style.display='none') {dynamicSize = size;}

block_4_close вне функции...вместо него нужно "r0" или "r1", и в условии нужно ставить не одно равно, а 2
if (document.getElementById("r0").style.display == 'none') {dynamicSize = size;}

bes 05.07.2012 16:16

Цитата:

Сообщение от Squirr
size = document.getElementById(contentMenuPersonal).style .height

Вы не получите это значение, если оно не было явно задано в атрибуте style или программно установлено в скрипте.

<style>
#but {height: 50px}
</style>
<button id="but" onclick="alert(this.style.height)">click</button>
<button style="height: 60px" onclick="alert(this.style.height)">click</button>

cyber 05.07.2012 16:29

а почему для получение высоты просто не использовать clientWidth, clientHeight ?

bes 05.07.2012 16:36

Цитата:

Сообщение от cyber
а почему для получение высоты просто не использовать clientWidth, clientHeight ?

clientHeight == height + padding
<style>
button {padding: 2px}
</style>

<button onclick="this.style.height = this.clientHeight">click</button>

cyber 05.07.2012 17:30

вот , выдрал из скрипта своего
width_drag = drag.obj.offsetWidth + parseInt(getComputed(drag.obj).marginLeft);
			  width_drag +=  parseInt(getComputed(drag.obj).marginRight);
			   
			   height_drag = drag.obj.offsetHeight  + parseInt(getComputed(drag.obj).marginTop);
			   
			     height_drag +=  parseInt(getComputed(drag.obj).marginBottom);

функция getComputed
function getComputed (obj){
	  
	  try{ 
	   return getComputedStyle(obj, null)
	   
	   } catch(e){ 
	      
		  return obj.currentStyle;
		   }
		
		};

bes 05.07.2012 18:31

Лично мне больше нравится такой вид
function getStyle(element) {
  if (window.getComputedStyle) {
    return window.getComputedStyle(element, null)
  } else {
    return element.currentStyle;
  }
}


Если величины будут не в px, то IE<9 не справится, нужно будет усложнять функцию дополнительными действиями по переводу из других единиц измерения + учесть случай, когда выдаётся значение auto.

cyber, что нужно будет устанавливать, получив приведённые вами значения width_drag и height_drag?

devote 05.07.2012 18:38

<style>
button {padding: 2px}
</style>
 
<button onclick="
    this.style.height = ( this.getBoundingClientRect().bottom - this.getBoundingClientRect().top ) + 'px';
    alert( 'Высота элемента: ' + (this.getBoundingClientRect().bottom - this.getBoundingClientRect().top))
">click</button>

cyber 05.07.2012 18:42

Цитата:

Сообщение от bes (Сообщение 186548)
Лично мне больше нравится такой вид

cyber, что нужно будет устанавливать, получив приведённые вами значения width_drag и height_drag?

не совсем понял вопрос...
епт, а о переводе в старых ие я забыл

cyber 05.07.2012 18:57

Цитата:

Сообщение от devote (Сообщение 186551)
<style>
button {padding: 2px}
</style>
 
<button onclick="
    this.style.height = ( this.getBoundingClientRect().bottom - this.getBoundingClientRect().top ) + 'px';
    alert( 'Высота элемента: ' + (this.getBoundingClientRect().bottom - this.getBoundingClientRect().top))
">click</button>

не забывайте уточнить что this.getBoundingClientRect будет работать не правильно при прокрутке=)

devote 05.07.2012 19:12

Цитата:

Сообщение от cyber
будет работать не правильно при прокрутке=)

причем тут прокрутка? когда я показал пример того как выяснить высоту элемента.. Прокрутка этому не помеха.

devote 05.07.2012 19:13

Цитата:

Сообщение от cyber
будет работать не правильно при прокрутке=)

не вижу изменений, как показывало 24 так и показывает.
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<style>
button {padding: 2px}
</style>
  
<button onclick="
    this.style.height = ( this.getBoundingClientRect().bottom - this.getBoundingClientRect().top ) + 'px';
    alert( 'Высота элемента: ' + (this.getBoundingClientRect().bottom - this.getBoundingClientRect().top))
">click</button>

bes 05.07.2012 19:57

Да, наверное это самый точный и простой способ, хотя погрешность есть (в хроме видно), но даже это прокатывает.
<style>
  button {padding: 21px; border: solid 5px;}
</style>

<button style="height: 43px" onclick="
  var h = this.getBoundingClientRect().bottom - this.getBoundingClientRect().top;
  this.nextElementSibling.style.height = h;//не для IE
  alert(h +'; ' + this.style.height);
">
click</button> 
<button disabled>click</button>

cyber 05.07.2012 19:59

хм...
getBoundingClientRect() возвращает результат без учета прокрутки, но в данном случае она и не важна.
короче я затупил , сорри =)

Squirr 06.07.2012 12:31

Всем спасибо за ответы :)
Высоту окна getBoundingClientRect() считает отлично, даже если она не была задана. Значит, то, что мне нужно решить с помощью JavaScript можно. Но не работает условие, которое я пишу. Подскажите, пожалуйста, знающие люди, что не так?
function change_visibility (block_4_close, block_4_open)
{
	document.getElementById(block_4_close).style.display='none';
	document.getElementById(block_4_open).style.display='';
}

var size = document.getElementById("contentMenuPersonal").style.height = ( document.getElementById("contentMenuPersonal").getBoundingClientRect().bottom - document.getElementById("contentMenuPersonal").getBoundingClientRect().top ) + 'px';

var dynSize = document.getElementById("bannerBig1").style.height = ( document.getElementById("bannerBig1").getBoundingClientRect().bottom - document.getElementById("bannerBig1").getBoundingClientRect().top ) + 'px';

if (document.getElementById("r0").style.display == 'none') {dynSize = size;}

Остальной код из 1-го поста остался без изменений:
#contentMenuPersonal
{
	display: block;
	z-index: 10;
	position: relative;
	margin: 80px 10px 30px;
	float: left;
	width: 175px;
}
#bannerBig1
{
	width: 680px;
	z-index: 10;
	position: relative;
	margin: 80px 10px 30px;
	float: left;

}

<div id="contentMenuPersonal">
	<table cellspacing="10px" align="center">
		...текст...
	</table>
</div>
<div id="bannerBig1" style="padding: 15px;">
	<div id="r0">
		...текст...
		<a href="javascript:change_visibility ('r0', 'r1')">Читать далее &rarr;</a>
	</div>
	<div id="r1" style="display: none;">
		...текст...
		<a href="javascript:change_visibility ('r1', 'r0')">&larr; скрыть текст</a>
	</div>
</div>

bes 06.07.2012 13:47

В данном примере способ почему-то не отрабатывает
<style>
#content {
  margin: 80px 10px 30px;
  float: left;
  width: 100px;
  background: green;
}
#banner {
  width: 200px;
  margin: 80px 10px 30px;
  float: left;
  background: lightgreen;
}
</style>

<div id="content">
  <table cellspacing="10px" align="center">
    ...текст...
  </table>
</div>

<div id="banner" style="padding: 15px;">
  <div id="r0">
    ...текст...
    <a href="#">Читать далее &rarr;</a>
  </div>
  <div id="r1" style="display: none;">
    ...текст...<br>    ...текст...<br>    ...текст...
    <a href="#">&larr; скрыть текст</a>
  </div>
</div>

<script>
window.onload = function () {
  var banner = document.getElementById('banner');
  var content = document.getElementById('content');

  banner.onclick = function (e) {
    e = e || event;
    var target = e.target || e.srcElement;

    if (target.tagName == 'A') {
      if (target.parentNode == banner.children[0]) {
        banner.children[1].style.display = 'block';
        banner.style.height = '';
      } else {
        banner.children[1].style.display = 'none';
        banner.style.height = (content.getBoundingClientRect().bottom - content.getBoundingClientRect().top) + 'px';
        alert('content: ' + (content.getBoundingClientRect().bottom - content.getBoundingClientRect().top));
        alert('banner: ' + (banner.getBoundingClientRect().bottom - banner.getBoundingClientRect().top));
      }
    }
  }

}
</script>

bes 07.07.2012 14:45

devote, как быть в этой ситуации, padding - явная проблема (хотя в примере с кнопкой прокатило), получается всё-таки getBoundingClientRect() - не лучшее решение.

Упрощённый пример
<div id="content" style="background: green;">
  text
</div>

<div id="banner" style="background: lightgreen; padding: 5px; overflow: hidden">
  <div>
   click
  </div>
  <div>
    click
  </div>
</div>

<script>
var banner = document.getElementById('banner');
var content = document.getElementById('content');

banner.onclick = function (e) {
  banner.style.height = (content.getBoundingClientRect().bottom - content.getBoundingClientRect().top) + 'px';
  alert('content: ' + (content.getBoundingClientRect().bottom - content.getBoundingClientRect().top));
  alert('banner: ' + (banner.getBoundingClientRect().bottom - banner.getBoundingClientRect().top));
}
</script>

Squirr 10.07.2012 12:49

Реакция на код в браузере появилась после того, как я скрипт переместил в сам div, который он должен изменять. На отдельно вынесенный js почему-то реакции не было. Но с getBoundingClientRect() всё равно не вышло: в разных браузерах высота разная, и ни в одном не та, которая нужна. Пресловутый padding всё портит, как мастера тут сказали.

Squirr 12.07.2012 12:17

И снова вынужден я обратиться к мудрости гуру. Проблема схожая, поэтому новую ветку заводить не стал.
На странице следующая конструкция из блоков:

Блоки div#r0 и div#r1 сменяют друг друга при нажатии на ссылку и имеют разное количество контента (высота их не задана).
Мне нужно добиться того, чтобы при нажатии на ссылку изменялась параметры "height" у div#content и "top" у div#bottom.
Я написал следующий скрипт:
<div id="content">
    	<table width="100%">
        	<tr><td>
            	<div id="contentMenuPersonal">
    	    		<table>
        	    		<tr><td class="contentMenu"><a href="/">Main</a></td></tr>
                        ...
                    </table>
                </div>
                <div id="bannerBig1">
					<div id="r0">
                    	<p>Текст</p>
						<a href="javascript:change_visibility ('r0', 'r1')">Читать далее &rarr;</a>
					</div>
					<div id="r1" style="display: none;">
                    	<p>Текст</p>
						<a href="javascript:change_visibility ('r1', 'r0')">&larr; скрыть текст</a>
					</div>
                </div>
            </td></tr>
        </table>
<script type="text/javascript">
	if (document.getElementById("r1").style.display = 'none') document.getElementById("content").style.height = "1100px";
	else document.getElementById("content").style.height = "1484px";
</script>
	</div>
    <div id="bottom">
<script type="text/javascript">
document.getElementById("content").style.height = ( document.getElementById("content").getBoundingClientRect().bottom - document.getElementById("content").getBoundingClientRect().top ) + 'px';
var h = parseInt((document.getElementById("content").getBoundingClientRect().bottom - document.getElementById("content").getBoundingClientRect().top));

//if (h == 1484.8333740234375)
if (h > 1450)
{
	document.getElementById("bottom").style.top = "1620px";
}
else
{
	document.getElementById("bottom").style.top = "1275px";
}
</script>
    </div>

Я долго пытался его отладить, но пока не смог добиться нужного результата. Скрипт вынесен в сами блоки, потому что иначе он почему-то вообще не работал, как будто браузер его не видел. Функция смены видимости блоков "r0" и "r1" работает нормально, так же как и функция, которая меняет параметр "top" у div#bottom (проверено изменением условия). А вот параметр "height" у div#content никак изменить динамически не получается.

lord2kim 12.07.2012 13:30

Цитата:

Сообщение от Squirr (Сообщение 188267)
Я долго пытался его отладить, но пока не смог добиться нужного результата. Скрипт вынесен в сами блоки, потому что иначе он почему-то вообще не работал, как будто браузер его не видел. Функция смены видимости блоков "r0" и "r1" работает нормально, так же как и функция, которая меняет параметр "top" у div#bottom (проверено изменением условия). А вот параметр "height" у div#content никак изменить динамически не получается.

во-первых в условиях
<script type="text/javascript">
    if (document.getElementById("r1").style.display = 'none') document.getElementById("content").style.height = "1100px";
    else document.getElementById("content").style.height = "1484px";
</script>

поставьте == и если изначально свойство height у элемента content не задано, то вы не сможете его изменить

Squirr 12.07.2012 14:30

lord2kim, да, я постоянно забываю ставить равенство в условии вместо присваивания. Высоту div#content я попробовал задать разными способами, но никакого результата не было. При этом значение "top" у div#bottom у меня вообще нигде не задано, однако это условие работает. Я уже не знаю, что тут ещё можно сделать. :help: А функция скрытия части текста на странице должна быть обязательно.
Кстати. Если не писать дополнительный скрипт для сдвига блоков, то значение "height" у div#content изменяется автоматически, только отдельный нижний блок остаётся на своём месте, потому что он там зафиксирован с абсолютным позиционированием.

Squirr 12.07.2012 14:40

Убрал строку с определением высоты блока content. После этого его высота стала меняться автоматически. Так что теперь загвоздка в сдвиге div#bottom. Что-то, видимо, не так в условии, но оно работает. Только отладить его надо. Если я ставлю в условии
if (h < 1450)
, то div#bottom.top = 1620px постоянно, и наоборот.

Squirr 12.07.2012 15:00

Написал функцию проверки значения "height" у div#content. При скрытом тексте 1076, при раскрытом — 1469,8333740234375. Условие, вроде бы правильно составил. Не понимаю, что тут не так.

Deff 12.07.2012 15:21

Squirr,
:) Мон чисто табличкой верстку забодать и никаких мучений
#content - это сама табла - отступы для ячеек #meny и #banner задаем cellpadding #ro0/#r1 => div блок cо style=width:100%; height:100%;

Squirr 12.07.2012 16:10

Deff, если по-другому не получится, только такой вариант и останется. А так, как я пытаюсь сделать, не получится по-вашему? Из-за различий в браузерах, конфликта внутреннего или ещё каких-то факторов.

bes 12.07.2012 17:16

Объясните подробнее какого поведения хотите добиться (опишите поведение каждого из блоков).
Например, пока не понятно представленный на рисунке вид должен оставаться таким в рамках экрана или может прокручиваться, меню имеет постоянную высоту или зависит от содержимого, то же самое про баннер и т.д., также непонятно как это всё должно вести себя при масштабировании.

Deff, таблицу тоже проблематично удержать в рамках экрана при масштабировании (ну или я может быть чего-то не догоняю).

Вот пример
<!doctype html>
<style>
  body {
    margin: 0px;
    padding: 0px;
    overflow: hidden;
  }
  table {
    position: absolute;
    left: 0px;
    top: 0px;
    width: 100%; 
    height: 100%;
  }
  td {
    border: 1px solid gray; 
  }
  table div {
    width: 100%;
    height: 100%; 
    overflow: auto;
  }
</style>

<table>
  <tr>
    <td colspan="2" height="5%">mainMenu</td>
  </tr>
  <tr >
    <td width="30%" height="90%">
      menu
    </td>
    <td width="70%">

<div>
content1<br>content1<br>content1<br>content1<br>content1<br>
content1<br>content1<br>content1<br>content1<br>content1<br>
content1<br>content1<br>content1<br>content1<br>content1<br>
content1<br>content1<br>content1<br>content1<br>content1<br>
content1<br>content1<br>content1<br>content1<br>content1<br>
content1<br>content1<br>content1<br>content1<br>content1<br>
</div>

    </td>
  </tr>
  <tr>
    <td colspan="2">bottom</td>
  </tr>
</table>

Squirr 12.07.2012 17:59

bes,
На картинке представлена структура div-ных блоков. #r0 и #r1 — это 2 разных блока с текстом разного объёма, виден в любой момент времени только 1 из них. Соответственно, должна меняться высота блока banner, в котором находится текст (это автоматом происходит, т.к. его высота не определена) и высота блока content (тоже не задана, меняется автоматически). Блок bottom находится отдельно от них. Это нужно, чтобы не нарушать дизайн. У него, соответственно, надо реализовать динамически изменяемое установленное свойство CSS top. Вот этого-то мне добиться и не удалось пока.
В блоке banner основной контент, а не баннер. Название блока перешло по наследству с главной страницы, чтобы не писать лишние стили. Здесь я оставил название, чтобы самому потом не запутаться.

bes 12.07.2012 19:06

Squirr,
Цитата:

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

не на все вопросы ответили:) (а вариантов развития много)

Как вариант
<style>
  div {
    padding: 0px;
    margin: 1%;
  }
  .menu {
   float: left;
    width: 30%;
    background: lightgrey;
  }  
  #banner {
    padding: 10px;
    float: left;
    width: 63%;
    background: green;
  }  
  #banner div {
    background: lightgrey;
  }
  .bottom {
    clear: both;
    background: gray;
  }
  
</style>

<div class="content">

  <div class="menu">
<a href="#" 
  onclick="
    banner.children[i].style.display = 'none';
    banner.children[j].style.display = 'block';
    k = i; i = j; j = k;
    return false;
">
menu</a>
</div>

  <div id="banner">
    <div>
content1<br>content1<br>content1<br>content1<br>content1<br>content1<br>content1<br>
content1<br>content1<br>content1<br>content1<br>content1<br>content1<br>content1<br>
   </div>
    <div style="display: none">content2<br>content2</div>
  </div>

</div>

<div class="bottom">
bottom
</div>

<script>
  var i = 0;
  var j = 1;
  var k;
</script>

Squirr 12.07.2012 22:51

bes,
Цитата:

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

Sorry.
В зависимости от размера экрана контент должен прокручиваться. Меню имеет постоянную высоту и зависит от количества содержимого. Баннер должен менять высоту в зависимости от того, скрыта ли часть текста. А нижний блок, отделённый от общего, должен смещаться вниз равномерно вместе с основным контентом. У этого нижнего блока изначально было фиксированное положение, т.к. я не знал при вёрстке, что придётся менять CSS.top.
Сверху страницы ещё есть шапка с логотипом, основным меню и пр. Они не вызывали у меня проблем, поэтому я их опустил. Здесь указываю, чтобы у Вас было полное представление о том, что это будет.
Спасибо за Ваш пример. Должно быть именно так, только ссылка на скрытие текста у меня в блоке #banner, и при загрузке страницы большая часть текста скрыта. Попробую с ним разобраться завтра на свежую голову :)


Часовой пояс GMT +3, время: 10:15.