Сайты - по стандартам, но не стандартные сайты!
Дано некое динамическое меню, которое по неизвестным мне причинам выглядит примерно так:
Родительский элемент
Дочерний элемент 1
Дочерний элемент 1.1
Дочерний элемент 1.1.1
Дочерний элемент 1.2
Дочерний элемент 2
Дочерний элемент 2.1
Дочерний элемент 2.2
Дочерний элемент 2.n
Дочерний элемент n
ну и так далее.
С помощью DOM пытаюсь сделать обычную вещь: если нажать на родительский элемент, то дочерние скрываются или наоборот раскрываются. Только хочется, чтобы раскрывались только прямые потомки, а потомки потомков оставались скрытыми, пока на их непосредственных родителей не ткнули. А этого пока не получается.
Скрипт у меня вот такой:
function chch(a){
var par=a.parentNode;
var spanNodes=par.getElementsByTagName("span");
if(spanNodes[0].style.display=="none"){
for(var i=0; i
}
}
else{
for(var i=0; i
}
}
}
извините, если вопрос идиотский, это мой первый опыт с DOM
Нет на форуме
вопрос не идеотский. я вот не могу на него ответить, могу лишь порекомендовать vbscript, если интересно, скажи, всё сделаю. кстати dom утяжеляет html-файл, так что не надо им злоупотреблять, если, например, в меню всего 20 элементов общей сложностью.
Нет на форуме
у меня в меню элементов очень много, потому и хочу все сворачивать-разворачивать
Отредактированно televizor (26.03.2010 15:55)
Нет на форуме
А меню из span'ов? Было бы удобней делать меню из маркированного списка, тогда бы и осуществить доступ к дочерним элементам было проще...
Нет на форуме
оно именно из спанов
но подскажите, что делать с маркированными списками - на будущее :-)
Нет на форуме
моё меню без скрипта выглядит где-то так:
Нет на форуме
+css и скрипт, разумеется:
jscript_
var openLists = [], oIcount = 0;
function compactMenu(oID,oAutoCol,oPlMn,oMinimalLink) {
if( !document.getElementsByTagName || !document.childNodes || !document.createElement ) { return; }
var baseElement = document.getElementById( oID ); if( !baseElement ) { return; }
compactChildren( baseElement, 0, oID, oAutoCol, oPlMn, baseElement.tagName.toUpperCase(), oMinimalLink && oPlMn );
}
function compactChildren( oOb, oLev, oBsID, oCol, oPM, oT, oML ) {
if( !oLev ) { oBsID = escape(oBsID); if( oCol ) { openLists[oBsID] = []; } }
for( var x = 0, y = oOb.childNodes; x //for each immediate LI child
var theNextUL = y[x].getElementsByTagName( oT )[0];
if( theNextUL ) {
//collapse the first UL/OL child
theNextUL.style.display = 'none';
//create a link for expanding/collapsing
var newLink = document.createElement('A');
newLink.setAttribute( 'href', '#' );
newLink.onclick = new Function( 'clickSmack(this,' + oLev + ',\'' + oBsID + '\',' + oCol + ',\'' + escape(oT) + '\');return false;' );
//wrap everything upto the child U/OL in the link
if( oML ) { var theHTML = ''; } else {
var theT = y[x].innerHTML.toUpperCase().indexOf(' var theA = y[x].innerHTML.toUpperCase().indexOf(' var theHTML = y[x].innerHTML.substr(0, ( theA + 1 && theA while( !y[x].childNodes[0].tagName || ( y[x].childNodes[0].tagName.toUpperCase() != oT && y[x].childNodes[0].tagName.toUpperCase() != 'A' ) ) {
y[x].removeChild( y[x].childNodes[0] ); }
}
y[x].insertBefore(newLink,y[x].childNodes[0]);
y[x].childNodes[0].innerHTML = oPM + theHTML.replace(/^\s*|\s*$/g,'');
theNextUL.MWJuniqueID = oIcount++;
compactChildren( theNextUL, oLev + 1, oBsID, oCol, oPM, oT, oML );
} } } }
function clickSmack( oThisOb, oLevel, oBsID, oCol, oT ) {
if( oThisOb.blur ) { oThisOb.blur(); }
oThisOb = oThisOb.parentNode.getElementsByTagName( unescape(oT) )[0];
if( oCol ) {
for( var x = openLists[oBsID].length - 1; x >= oLevel; x-=1 ) { if( openLists[oBsID][x] ) {
openLists[oBsID][x].style.display = 'none'; if( oLevel != x ) { openLists[oBsID][x] = null; }
} }
if( oThisOb == openLists[oBsID][oLevel] ) { openLists[oBsID][oLevel] = null; }
else { oThisOb.style.display = 'block'; openLists[oBsID][oLevel] = oThisOb; }
} else { oThisOb.style.display = ( oThisOb.style.display == 'block' ) ? 'none' : 'block'; }
}
function stateToFromStr(oID,oFStr) {
if( !document.getElementsByTagName || !document.childNodes || !document.createElement ) { return ''; }
var baseElement = document.getElementById( oID ); if( !baseElement ) { return ''; }
if( !oFStr && typeof(oFStr) != 'undefined' ) { return ''; } if( oFStr ) { oFStr = oFStr.split(':'); }
for( var oStr = '', l = baseElement.getElementsByTagName(baseElement.tagName), x = 0; l[x]; x++ ) {
if( oFStr && MWJisInTheArray( l[x].MWJuniqueID, oFStr ) && l[x].style.display == 'none' ) { l[x].parentNode.getElementsByTagName('a')[0].onclick(); }
else if( l[x].style.display != 'none' ) { oStr += (oStr?':':'') + l[x].MWJuniqueID; }
}
return oStr;
}
function MWJisInTheArray(oNeed,oHay) { for( var i = 0; i function selfLink(oRootElement,oClass,oExpand) {
if(!document.getElementsByTagName||!document.childNodes) { return; }
oRootElement = document.getElementById(oRootElement);
for( var x = 0, y = oRootElement.getElementsByTagName('a'); y[x]; x++ ) {
if( y[x].getAttribute('href') && !y[x].href.match(/#$/) && getRealAddress(y[x]) == getRealAddress(location) ) {
y[x].className = (y[x].className?(y[x].className+' '):'') + oClass;
if( oExpand ) {
oExpand = false;
for( var oEl = y[x].parentNode, ulStr = ''; oEl != oRootElement && oEl != document.body; oEl = oEl.parentNode ) {
if( oEl.tagName && oEl.tagName == oRootElement.tagName ) { ulStr = oEl.MWJuniqueID + (ulStr?(':'+ulStr):''); } }
stateToFromStr(oRootElement.id,ulStr);
} } } }
function getRealAddress(oOb) { return oOb.protocol + ( ( oOb.protocol.indexOf( ':' ) + 1 ) ? '' : ':' ) + oOb.hostname + ( ( typeof(oOb.pathname) == typeof(' ') && oOb.pathname.indexOf('/') != 0 ) ? '/' : '' ) + oOb.pathname + oOb.search; }
***
cookie_
function retrieveCookie( cookieName ) {
/* retrieved in the format
cookieName4=value; cookieName3=value; cookieName2=value; cookieName1=value
only cookies for this domain and path will be retrieved */
var cookieJar = document.cookie.split( "; " );
for( var x = 0; x var oneCookie = cookieJar[x].split( "=" );
if( oneCookie[0] == escape( cookieName ) ) { return unescape( oneCookie[1] ); }
}
return null;
}
function setCookie( cookieName, cookieValue, lifeTime, path, domain, isSecure ) {
if( !cookieName ) { return false; }
if( lifeTime == "delete" ) { lifeTime = -10; } //this is in the past. Expires immediately.
/* This next line sets the cookie but does not overwrite other cookies.
syntax: cookieName=cookieValue[;expires=dataAsString[;path=pathAsString[;domain=domainAsString[;secure]]]]
Because of the way that document.cookie behaves, writing this here is equivalent to writing
document.cookie = whatIAmWritingNow + "; " + document.cookie; */
document.cookie = escape( cookieName ) + "=" + escape( cookieValue ) +
( lifeTime ? ";expires=" + ( new Date( ( new Date() ).getTime() + ( 1000 * lifeTime ) ) ).toGMTString() : "" ) +
( path ? ";path=" + path : "") + ( domain ? ";domain=" + domain : "") +
( isSecure ? ";secure" : "");
//check if the cookie has been set/deleted as required
if( lifeTime if( typeof( retrieveCookie( cookieName ) ) == "string" ) { return true; } return false;
}
***
CSS_
LI
{
display: inLine;
}
UL, LI
{
padding: 0px;
list-style-type: none;
margin: 0;
color: mediumpurple;
font-weight: bold;
border-top: 5ps solid rgb(233,238,242);
}
LI A
{
display: block;
padding: 0px;
text-decoration: none;
width: 100%;
height: 100%;
color: midnightblue;
font-weight: bold;
font-size: 16;
background: rgb(233,238,242);
border-right: 18px solid white;
border-top: 0;
border-right: 18px solid rgb(233,238,242);
}
LI LI A
{
display: block;
background-color: transparent;
font-size: 14;
color: darkgreen;
border-top: 0;
border-right: 18px solid rgb(233,238,242);
margin-left: 8px;
}
LI LI LI A
{
display: block;
background-color: transparent;
font-size: 12;
color: steelblue;
border-top: 0;
border-right: 18px solid rgb(233,238,242);
margin-left: 16px;
}
LI A, LI LI A, LI LI LI A
{
}
LI A:HOVER
{
display: block;
color: black;
}
LI LI A:HOVER
{
display: block;
background-color: transparent;
color: black;
}
LI LI LI A:HOVER
{
display: block;
background-color: transparent;
color: royalblue;
}
LI A:HOVER, LI LI A:HOVER, LI LI LI A:HOVER
{
display: block;
;
border: 0;
}
LI A:ACTIVE, LI LI A:ACTIVE, LI LI LI A:ACTIVE
{
display: block;
color: orangered;
}
***
заодно и зацените мой новый ява-скрипт. первый блин.
Нет на форуме
забыл тег code, простите:(
Нет на форуме
ух, спасибо! буду разбираться
Нет на форуме
Wizard
Мне понравилось - интересные возможности для изменения отображения списка и маркеров (понравился вид if oMinimalLink == true)!
Чуть-чуть подправил в стилях:
LI A { height:auto!important;// для FF height:100%;// оставить для IE ... }
А что значит "первый блин"?
Нет на форуме
Меж тем, не прошло и полгода, как мной был придуман тупой костыль: в процессе присвоения потомкам дисплей:блок, я каждого проверяю - если предок его предка (то есть, дедушка) это тот самый элемент, чьим прямым детям я хочу дать блок, то значит этот элемент остается дисплей:нет. Ну, или чуть проще: если ты внук, а не сын, значит рано тебе на свет появляться.
скрипт теперь выглядит так:
function chch(a){ var par=a.parentNode; var spanNodes=par.getElementsByTagName("span"); if(spanNodes[0].style.display=="none"){ for(var i=0; i
Только это почему-то работает для первого-второго уровня, а потом опять внуки раньше времени ползут (акселераты, наверное :-))
Нет на форуме
AKS, первый сетевой java-script моего производства. Спасибо за правочку:)
Нет на форуме
televizor, поддерживаю твою любовь к всему простому;)) я вообще стараюсь обходится CSS, это возможно чаще, чем кажется на первый взгляд. ДОМ хорош тем, что его интерпретируют все браузеры, вынужденно, одинаково, мне так кажется... Если всё получится, дашь ссылку на результат?
Нет на форуме
на результат вряд ли: это мне нужно для админки одной CMS, где беспощадно разросся список категорий, то есть чисто для внутреннего пользования
а вот скрипт тут выложу, если доведу до ума (то, что сейчас он выдает, уже сильно облегчило работу) :-)
но меня все же гложут подозрения, что наверняка эта моя проблема уже неоднократно решена
Нет на форуме
веб-дизайн штука неблагодарная, зато приятно, когда всё складываеться:)
Нет на форуме
televizor
Раз уж нельзя отказаться от span'ов, тогда...
Все span'ы я поместил в div для удобства доступа:
HTML
Родительский элемент Дочерний элемент 1 Дочерний элемент 1.1 Дочерний элемент 1.1.1 Дочерний элемент 1.2 Дочерний элемент 2 Дочерний элемент 2.1 Дочерний элемент 2.2 Дочерний элемент 2.n Дочерний элемент n
Добавил стилей:
CSS
span { cursor : pointer; } .hidden { display : none; } .nothidden { display : block; }
JavaScript
function changeDisplay(el, spans) { var i = 0, len = spans.length; for(; i
Остается еще добавить в JavaScript запрет на выделение текстовых элементов,
т.к. это случается при частом кликанье...
Нет на форуме
здоровая идея, я чуть доработал и кинул в личную коллекцию динамичных списков) советую фокус и выделение с помощью сss убрать.
Нет на форуме
Wizard
А я не знаю, как с помощью CSS можно снять выделение текста...
Можно подсказку?
Нет на форуме
а у меня получилось так:
...
...
...
Home
...
или ещё так:
HTML_
Home
&
CSS_ .logo_nafir { display:block; width:252px; height:52px; margin:20px auto; } /* make the actual link ZERO size and position relative the zero size stops the dotted border from displaying */ .logo_nafir a { display:block; width:0; height:0; position:relative; } /* move the link styling to the em and make it position absolute */ .logo_nafir a em { display:block; text-indent:-10000px; width:250px; height:50px; position:absolute; background:#fff url(graphics/cssplay_logo.gif); border:1px solid #ddd; cursor:pointer; /* to set the pointer correctly as a link in IE */ } .logo_nafir a:hover em { border-color:#000; } /* for IE to make the active/focus state work correctly */ .logo_nafir a:active { color:#fff; } /* style the active/focus state */ .logo_nafir a:active em, .logo_nafir a:focus em { border-color:#c00; }
ps не ругайте за тупые имена, я прямо из готового кода брал пример.
Нет на форуме
или вы хотели без картинок?))) тогда только JS
Нет на форуме
Wizard
Да, меня как раз текстовые элементы интересовали...
Нет на форуме
ух, спасибо!
Нет на форуме
AKS, так можкт televizor другого мнения;)) Хотя я где-то видел пример, как на background текст наклеить. Ну и выделение становится, есессно, недоступно...
Нет на форуме
Wizard
Интересно было бы, конечно, узнать - как это делается. Я-то с CSS-трюками мало знаком, наверно было бы легче в стилях что-нибудь прописать, хотя и со скриптом это сделать очень просто... В любом случае - вопрос со span'ами, судя по всему, решен.
А вообще, полезная тема получилась - лично мне очень понравился Ваш скрипт - есть над чем подумать (представляю, как пришлось задуматься в процессе создания). Спасибо за исходник - буду в нем копаться время от времени...
Нет на форуме
AKS. Рад, что Вам понравился мой скрипт;) Это, как бы сказать, учебный пример, в этот скрипт я вложил почти всё, что только знаю о javascript, буду так же рад, если найдутся мною незамеченные ошибки (недочёты, баги, улучшения).
Другой вопрос: есть скрипт, привязывающий блок div к определённому месту на экране, так, что после скроллинга этот блок остаётся на прежнем месте, относительно дисплея. Мною написанные скрипты позволяют достичь данный эффект лишь рывками, а это не очень красиво и даже раздражает. Может, подскажите, как сделать плавно-плавающий блок?
Нет на форуме
Wizard
1. По-поводу скроллинга было бы удобней создать отдельную тему в форуме, т.к. вопрос этот очень и очень интересный, и заслуживает внимания (хотя в сети можно найти множество решений, но самим-то интересней). Ну что, может создадите отдельную тему?
2. По-поводу Вашего скрипта - если Вы собираетесь заниматься оптимизацией, то конечно можно было бы что-то и обсудить, но только обсудить, т.к. моей квалификации не хватает для того, чтобы обнаружить какие-то ошибки. А вот вопросы имеются, и если Вы найдете время отвечать на них, буду рад...
Нет на форуме
Найдётся, думаю, будет полезно на реальном примере углублять знания в области скрипта. На счёт сети не уверен, на тех сайтах, которым я доверяю, не нашлось удовлетворительного решения, поэтому и интересно обсудить. Сейчас создам тему...
Нет на форуме
Wizard
Есть такие вопросы:
1. Конструктор stateToFromStr() вызывается только из selfLink(), или вызывается еще где-нибудь?
2. Проверяли ли Вы корректность присвоения имени класса в выражении:
y[x].className = (y[x].className?(y[x].className+' '):'') + oClass;
3. Есть ли необходимость для каждого newLink.onclick в compactChildren() создавать новый экземпляр объекта Function?
4. Ну и конечно не могу не спросить про куки - зачем они?
Пока все вкратце...
Нет на форуме
Кук чтобы меню держалось после рефреша, он и удаляется сам с сайта, после часа неприбываения на сервере.
Поскольку всё писалось не сразу, есть изличние детали и повторяющиеся фрагменты, которых можно было избежать... Буду дорабатывать стиль когда всё будут работать чётко, есть ещё кой-какие баги.
stateToFromStr() вызывается лишь единожды.
Нет на форуме
Wizard
А зачем для передачи строки, содержащей имя тега, используется кодирование? Я просто не знаю - хотелось узнать,
с какой целью...
Остальные вопросы, какие были, вобщем-то не имеют смысла, т.к. Вы сами сказали, что будете многое переделывать.
Нет на форуме