Jump to content

Равномерное распределение элементов меню.


mishka
 Share

Recommended Posts

Исходный код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>autoscalingNav</title>
<style type="text/css">
.menu {
width: 800px;
margin: 50px auto;
padding: 0;
list-style: none;
border: 2px solid #2d67f9;
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
font: 18px/24px Verdana, Arial, Helvetica, sans-serif;
}
.menu:after {
content: '';
display: block;
clear: both;
}
.menu li {
float: left;
white-space: nowrap;
}
.menu a {
zoom: 1;
display: block;
text-align: center;
border-left: 2px solid #2d67f9;
background: #aee6ff;
color: #000;
padding: 5px 0;
text-decoration: none;
}
.menu a:hover { background: #0087ff; color: #fff; }
.menu .first-child a {
border: 0;
border-radius: 8px 0 0 8px;
-webkit-border-radius: 8px 0 0 8px;
-moz-border-radius: 8px 0 0 8px;
-o-border-radius: 8px 0 0 8px;
}
.menu .last-child a {
border-radius: 0 8px 8px 0;
-webkit-border-radius: 0 8px 8px 0;
-moz-border-radius: 0 8px 8px 0;
-o-border-radius: 0 8px 8px 0;
}
.js-init .menu a { display: inline; }
</style>
<script type="text/javascript">
var autoscalingNav = {
init: function ( o ) {
var settings = {
list: 'nav',
fill: 'rateably', // rateably | equally
minSide: 10,
sideClass: false // false | true
}

if ( typeof ( o ) == 'object' ) for ( var key in o ) settings[key] = o[key];

this.list = ( typeof settings.list === 'object' ) ? settings.list : document.getElementById ( settings.list );
this.fill = settings.fill;
this.minSide = settings.minSide;
this.elem = this.list.children;

if ( settings.sideClass ) {
if ( this.elem[0].className.indexOf ( 'first-child' ) < 0 ) this.elem[0].className += ' first-child';
if ( this.elem[this.elem.length - 1].className.indexOf ( 'last-child' ) < 0 ) this.elem[this.elem.length - 1].className += ' last-child';
}

this.scaling ();
},
scaling: function () {
document.body.className += ' js-init';
var _listWidth = this.list.clientWidth,
_elWidth = 0,
_newWidth = 0,
_equally = 0,
_equallyNum = this.elem.length,
_equallyW = parseInt ( _listWidth / _equallyNum, 10 ),
_equallySumW = _listWidth;

for ( var i = this.elem.length - 1; i >= 0; i-- ) {
_elWidth += this.elem[i].clientWidth;
if ( this.elem[i].clientWidth + this.minSide * 2 >= _equallyW && this.fill == 'equally' ) {
this.elem[i].style.width = this.elem[i].clientWidth + this.minSide * 2 + 'px';
this.elem[i].maxEqu = true;
_equallySumW -= this.elem[i].clientWidth;
_equallyNum--;
}
}

var _Kw = _listWidth / _elWidth,
_postW = _listWidth - _elWidth;

if ( _Kw < 0 ) return;

switch ( this.fill ) {
case 'rateably':
var _delta = parseInt ( ( _postW / this.elem.length ), 10 );
for ( var j = this.elem.length - 1; j >= 0; j-- ) this.elem[j].style.width = this.elem[j].clientWidth + _delta + 'px';
for ( var k = this.elem.length - 1; k >= 0; k-- ) _newWidth += this.elem[k].clientWidth;
var _pW = _listWidth - _newWidth, l = 0;
while ( _pW > 0 ) {
this.elem[l].style.width = ( this.elem[l].clientWidth + Math.ceil ( ( _listWidth - _newWidth ) / this.elem.length ) ) + 'px';
_pW -= Math.ceil ( ( _listWidth - _newWidth ) / this.elem.length );
l++;
}
break;

case 'equally':
var _addEquallyW = parseInt ( _equallySumW / _equallyNum, 10 );
for ( var m = this.elem.length - 1; m >= 0; m-- ) if ( !this.elem[m].maxEqu ) this.elem[m].style.width = _addEquallyW + 'px';
for ( var k = this.elem.length - 1; k >= 0; k-- ) _newWidth += this.elem[k].clientWidth;
var _pWe = _listWidth - _newWidth, l = 0;
while ( _pWe > 0 ) {
this.elem[l].style.width = ( this.elem[l].clientWidth + Math.ceil ( ( _listWidth - _newWidth ) / this.elem.length ) ) + 'px';
_pWe -= Math.ceil ( ( _listWidth - _newWidth ) / this.elem.length );
l++;
}
break;
}
document.body.className = document.body.className.replace ( ' js-init', '' );
}
}

function initPage () {
autoscalingNav.init ({
list: 'nav',
sideClass: true,
fill: 'rateably'
});
autoscalingNav.init ({
list: 'nav2',
sideClass: true,
fill: 'equally'
});
}

if (window.addEventListener) window.addEventListener("load", initPage, false);
else if (window.attachEvent && !window.opera) window.attachEvent("onload", initPage);
</script>
</head>
<body>
<ul id="nav" class="menu">
<li><a href="#">lik</a></li>
<li><a href="#">lins</a></li>
<li><a href="#">li</a></li>
<li><a href="#">linkasaa</a></li>
<li><a href="#">linkss</a></li>
<li><a href="#">linkss</a></li>
<li><a href="#">linkasasaafghdt</a></li>
</ul>
<ul id="nav2" class="menu">
<li><a href="#">lik</a></li>
<li><a href="#">lins</a></li>
<li><a href="#">li</a></li>
<li><a href="#">linkasaa</a></li>
<li><a href="#">linkss</a></li>
<li><a href="#">linkss</a></li>
<li><a href="#">linkasasaafghdt</a></li>
</ul>
</body>
</html>

Замечания:

init - я бы сделал не так. У тебя есть перечень дефолтных значений. Пусть это будет объект, но находиться он должен на одном уровне с init.

Перебирай потом список дефолтных значений и присваивай нужные значения из объекта o. Так будет гораздо понятнее, чем то, что есть сейчас.

Изменения:

Пока что менял только init и settings.

Правильно ли сделал?

var autoscalingNav = {
settings: {
list: 'nav',
fill: 'rateably', // rateably | equally
minSide: 10,
sideClass: false // false | true
},
init: function ( o ) {
if ( typeof o !== 'object' ) o = {};
if ( o.list ) this.settings.list = o.list;
if ( o.fill ) this.settings.fill = o.fill;
if ( o.minSide ) this.settings.minSide = o.minSide;
if ( o.sideClass ) this.settings.sideClass = o.sideClass;

this.list = ( typeof this.settings.list === 'object' ) ? this.settings.list : document.getElementById ( this.settings.list );
this.elem = this.list.children;

if ( this.settings.sideClass ) {
if ( this.elem[0].className.indexOf ( 'first-child' ) < 0 ) this.elem[0].className += ' first-child';
if ( this.elem[this.elem.length - 1].className.indexOf ( 'last-child' ) < 0 ) this.elem[this.elem.length - 1].className += ' last-child';
}

this.scaling ();
},
scaling: function () {
// тут считаем ширины
}
}

Замечания:

Формулы нечитабельны. Разобраться, что и как происходит, нереально. Портят все подчеркивания в названиях переменных.

Подчеркивания привык ставить, дабы не попасть в зарезервированное слово. Буду стараться избавиться от этой привычки.

Замечания:

Следующие вещи стоит выносить в отдельные библиотечные функции


if (window.addEventListener) window.addEventListener("load", initPage, false);
else if (window.attachEvent && !window.opera) window.attachEvent("onload", initPage);

Снова же, нужно вчитываться, чтобы понять, что тут написано.

Как вынести, куда?

Обично у меня это внизу кода, там запускается ф-ция initPage, а в ней уже запускаются нужные функции в нужном порядке.

Как это делать лучше? И чем так лучше?

Link to comment
Share on other sites

Пока что менял только init и settings.

Правильно ли сделал?

Не совсем. Меняем только init


if ( typeof o === 'object' ) { // нижеследующий код имеет смысл только когда [font="Courier New"]o[/font] является объектом настроек. Но его может вообне не быть
var sets = this.settings; // для упрощения доступа
for ( var i in sets ){ // перебираем свойства объекта
if ( !sets.hasOwnProperty(i) ) continue; // не перебираем свойства прототипа
switch ( i ) {
case "list":
if ( o[i] ) sets[i] = o[i];
sets[i] = ( typeof sets[i] === 'object' ) ? sets[i] : document.getElementById ( sets[i] ); // для этого я обычно пишу функцию $(sets[i])
break;

case "sideClass":
if ( sets.sideClass ) {
// че тут вообще происходит??? о_О
if ( this.elem[0].className.indexOf ( 'first-child' ) < 0 ) this.elem[0].className += ' first-child';
if ( this.elem[this.elem.length - 1].className.indexOf ( 'last-child' ) < 0 ) this.elem[this.elem.length - 1].className += ' last-child';
};
break;

default: // по умолчанию присваиваем свойства
if ( o[i] !== undefined ) sets[i] = o[i];

}
}
}
this.scaling (); // выполняем в любом случае

Как вынести, куда?

Обично у меня это внизу кода, там запускается ф-ция initPage, а в ней уже запускаются нужные функции в нужном порядке.

Как это делать лучше? И чем так лучше?

Вот, например, вот так


addEvent( window, 'load', function(){} );

Link to comment
Share on other sites

  • 2 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy