Осмелюсь предложить "до кучи" и свой вариант, простой, без AJAXа - чисто для "украшения".
Постановка задачи: пусть есть несколько блоков с заданными id-ами, есть менюшка со ссылками на них как на якоря (<a href="#id">), в виде списка. Хочется, чтобы при отсутствии JS оно так и работало (это максимум возможного в такой ситуации), а при его наличии превращалось в красивый TabControl. Должна быть возможность (опциональная) заранее спрятать все блоки, кроме одного, с помощью специального CSS-класса, чтобы это все не дергалось в момент превращения (без JS этот класс не должен влиять ни на что). На странице может быть неограниченное число таких систем блоков с разными стилями.
Мой вариант решения:| Код | function tabControl(tabsContainerId, actualTabClass, hiddenTabClass) { this.tabsId = tabsContainerId; // id списка табов this.aCSS = actualTabClass; // CSS-класс активного заголовка таба this.hCSS = hiddenTabClass; // CSS-класс скрытого тела таба // добавление стилей, скрывающих тела табов, кроме нужного // если JS отключен, все тексты будут просто выведены друг за другом document.write('<style type="text/css">\n'+ 'div.'+this.hCSS+' { display: none; }\n'+ '#'+this.tabsId+' a { cursor:default; }\n'+ '<\/style>\n'); // постановка в очередь на инициализацию объекта при загрузке страницы // (спасибо AKS за помощь в технологии добавления обработчиков) (function ah(o, e, f) { o.addEventListener ? o.addEventListener(e, f, false) : o.attachEvent ? o.attachEvent('on'+e, f) : ''; }) (window, 'load', (function ii(x) { return function() {x.init() }}) (this)); }
tabControl.prototype.init = function() { this.tabs = document.getElementById(this.tabsId).getElementsByTagName('li'); // заголовки табов this.divs = []; // тела табов this.actIndex = 0; // индекс активного таба for (var i=0, hideCnt = 0, t, a; t=this.tabs[i]; i++) { // находим соответствующий заголовку блок и убираем более ненужную ссылку a = t.getElementsByTagName("a")[0]; this.divs[i] = document.getElementById(a.href.split('#')[1]); a.removeAttribute("href"); // добавляем реакцию на клик t.onclick = (function(ob,num) { return function() { ob.activate(num); return false; } })(this,i); // считаем не скрытые по умолчанию дивы if (this.divs[i].className.indexOf(this.hCSS)!=-1) hideCnt++; // активным табом станет первый из не скрытых по умолчанию if (hideCnt && !this.actIndex) this.actIndex = i; } // скрываем все табы, кроме активного (если не все они еще скрыты) if (hideCnt < this.divs.length-1) for(var i=0, d; d=this.divs[i]; i++) { if (i!=this.actIndex && d.className.indexOf(this.hCSS)==-1) d.className += ' '+this.hCSS; } // выделяем визуально заголовок активного таба this.activate(this.actIndex); }
tabControl.prototype.activate = function(i) { // Визуальная смена активного таба. По идее, тут все очевидно ;) this.tabs[this.actIndex].className = this.tabs[this.actIndex].className.replace(this.aCSS, ''); this.divs[this.actIndex].className += ' '+this.hCSS; this.tabs[i].className += ' '+this.aCSS; this.divs[i].className = this.divs[i].className.replace(this.hCSS, ''); this.actIndex = i; }
|
и пример использования (оформление табов, как и идея скрипта, пришли из http://forum.vingrad.ru/topic-120300.html):
| Код | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Еще один TabControl)</title> <style type="text/css"> #cont * { margin: 0; padding: 0; } #tabs { margin: 0 auto; list-style-type: none; display: table; border-spacing: 3px 0; } #tabs li { display: table-cell; font: normal 1em/1em courier new, monospace; background: #1A7515 url(bg0.gif) 0 -50px no-repeat; color: #A4D9A1; } #tabs li a { display: block; padding: 0.2em 1.5em; background: url(bg1.gif) 100% -50px no-repeat; } #tabs li.actual { background: #A4D9A1 url(bg0.gif) 0 0 no-repeat; color: #1A7515; } #tabs li.actual a { background: url(bg1.gif) 100% 0 no-repeat; } #main { background: #A4D9A1; margin: 0; padding: 2em 0; font: normal 0.76em/1em verdana, sans-serif; color: #1A3515; } #main div { margin: 0 2em; padding: 0.5em 0; height: 10em; } </style> <!--[if lte IE 6]> <style> #cont { position: relative; width: 100%; } #tabs, #tabs li, #tabs li span { margin: 0; float: left; display: inline; } #tabs { position: relative; left: expression((this.offsetParent.clientWidth - this.offsetWidth - 3)/2+'px'); } #tabs li { margin-left: 3px; } #main { clear: left; width: 100%; } </style> <![endif]--> <script type="text/javascript" src="tabcontrol.js"></script> <script type="text/javascript"> new tabControl('tabs', 'actual', 'hidden'); </script> </head> <body> <div id="cont"> <ul id="tabs"> <li><a href="#t1">Первая</a></li> <li><a href="#t2">Вторая</a></li> <li><a href="#t3">Последняя</a></li> </ul> </div> <div id="main"> <div id="t1" class="hidden">Текст первой вкладки.</div> <div id="t2">Текст второй вкладки. Она открывается по умолчанию, т.к. ей единственной не назначен CSS-класс <i>hidden</i>.</div> <div id="t3" class="hidden">А тут текст последней вкладки.</div> </div> </body> </html>
|
А вот так это безобразие http://silverflame.at.tut.by/tabs/tabs3.html (проверено в FF2, Opera 8-8.5-9, IE6).
Известные баги тестовой версии: пока это нельзя использовать в XHTML, отдаваемом с честным Content-type (из-за использования document.write, в принципе знаю как обойти, но цена - усложнение и ухудшение совместимости). |