Начну с того, что я бросил заниматься программирование уже давно, порядка 6 лет назад. Но если быть честным, иногда тешил себе вечерами программируя разные мелкие программки для собственных нужд. Т.е. программирование для меня перешло в разряд хобби.

И вот, на днях я решил взяться за один интернет проект.

Стоит отметить, что я один из тех программистов которые любят изобретать велосипед, каждый раз, когда берутся за что-то новое. Многие скажут, что работая над проектом в первую очередь необходимо учитывать время на разработку и многие будут использовать готовые фреймворки или библиотеки, даже если они будут не удобны и медленнее. Главное — они быстро компенсируют время на разработку. Для меня же в, первую очередь, важно качество, а не количество, важна скорость работы приложения и количество потребляемых им ресурсов.

Встала задача: реализовать свой скроллбар, вписывающийся в дизайн сайта, для div элемента фиксированного по ширине и высоте.

Погуглив немного я не нашел подходящего для себя решения, кроме как использовать jQuery плагин JscrollPane. Меня смутило, что для достижения цели мне придется цеплять сразу три библиотеки: jquery, jquery.mousewheel и jScrollPane. А как же трафик? ;)

В общем я решил накидать решение задачи самостоятельно.

В процессе работы выделились подзадачи:
  • кроссбраузерность;
  • скролл колесиком мыши;
  • возможность добавлять скроллбар нескольким элементам на одной страничке.

Результат:
image

И вот моё решение:

scroller.css

Тут указываем ширину сроллбара и фоновую картинку, ширину, высоту и картинки для стрелочек.

.scrollUp
 {
  width: 24px;
  height: 28px;
  position: absolute;
  left: 0px;
  top: 0px;
  cursor: pointer;
  background-image: url(../imgs/maininterface/scroller_top_i.png);
 }
 .scrollUp:hover
 {
  background-image: url(../imgs/maininterface/scroller_top_s.png);
 }
 .scrollDown
 {
  width: 24px;
  height: 28px;
  position: absolute;
  left: 0px;
  bottom: 0px;
  cursor: pointer;
  background-image: url(../imgs/maininterface/scroller_bottom_i.png);
 
 }
 .scrollDown:hover
 {
  background-image: url(../imgs/maininterface/scroller_bottom_s.png);
 }
 .scroller
 {
  width: 24px;
  height: 5px;
  position: absolute;
  left: 0px;
  top: 28px;
  cursor: pointer;
  background-image: url(../imgs/maininterface/scroller_i.png);
 }
 .scroller:hover
 {
  background-image: url(../imgs/maininterface/scroller_s.png);
 }
 
 .scrollBody
 {
  width: 24px;
  min-height: 100%;
  cursor: pointer;
  background-image: url(../imgs/maininterface/scroller_body.png);
 }
 
 .scrollBox
 {
  float: right;
  width: 24px;
  height: 100%;
  position: absolute;
  top: 0px;
  right: 0px;
  background-color: #000000;
 }


scroller.js

function getTrueOffsetLeft(ele)
{
 var n = 0;
 while (ele)
 {
  n += ele.offsetLeft || 0;
  ele = ele.offsetParent;
 }
 return n;
}
    
function getTrueOffsetTop(ele)
{
 var n = 0;
 while (ele)
 {
  n += ele.offsetTop || 0;
  ele = ele.offsetParent;
 }
 return n;
}

function getMouse(e, obj)
{
 var x = e.clientX - getTrueOffsetLeft(obj) + window.pageXOffset;
 var y = e.clientY - getTrueOffsetTop(obj) + window.pageYOffset;
 return [x,y];
}
    
function scrollDown(id)
{
 document.getElementById(id).scrollTop += 10;
 scrollYdelta = (document.getElementById(id).scrollHeight-(document.getElementById(id).offsetHeight));
 widthScrollArrows = document.getElementById(id+'ScrollDown').offsetHeight*2;
 posYScroller = ((document.getElementById(id).offsetHeight-widthScrollArrows)/scrollYdelta)*
                  document.getElementById(id).scrollTop +document.getElementById(id+'ScrollDown').offsetHeight;
 
 if (posYScroller>(document.getElementById(id).offsetHeight - 
                   document.getElementById(id+'ScrollDown').offsetHeight -
                   document.getElementById(id+'Scroller').offsetHeight))
     posYScroller=document.getElementById(id).offsetHeight-document.getElementById(id+'ScrollDown').offsetHeight-document.getElementById(id+'Scroller').offsetHeight;
 
 document.getElementById(id+'Scroller').style.top = posYScroller+"px";
 document.getElementById(id+'ScrollBox').style.top = document.getElementById(id).scrollTop + "px";

}

function scrollUp()
{
 document.getElementById(id).scrollTop -= 10;
 scrollYdelta = (document.getElementById(id).scrollHeight-(document.getElementById(id).offsetHeight));
 widthScrollArrows = document.getElementById(id+'ScrollDown').offsetHeight*2;
 posYScroller = ((document.getElementById(id).offsetHeight-widthScrollArrows)/scrollYdelta)*
                  document.getElementById(id).scrollTop + document.getElementById(id+'ScrollDown').offsetHeight;
 document.getElementById(id+'Scroller').style.top = posYScroller+"px";
 document.getElementById(id+'ScrollBox').style.top = document.getElementById(id).scrollTop + "px";
}
   
function onMouseWheelScroll(e)
{
 id = this.id;       
 e = e || event;   
 if (!e.wheelDelta)
 {
  e.wheelDelta = -40*e.detail; // для Firefox
 }
 document.getElementById(id).scrollTop -= e.wheelDelta;
 widthScrollArrows = document.getElementById(id+'ScrollDown').offsetHeight*2;
 scrollYdelta = (document.getElementById(id).scrollHeight-(document.getElementById(id).offsetHeight));
 posYScroller = ((document.getElementById(id).offsetHeight-widthScrollArrows)/scrollYdelta)*
                  document.getElementById(id).scrollTop + document.getElementById(id+'ScrollDown').offsetHeight;
 
 if (posYScroller>(document.getElementById(id).offsetHeight - 
                   document.getElementById(id+'ScrollDown').offsetHeight -
                   document.getElementById(id+'Scroller').offsetHeight))
     posYScroller=document.getElementById(id).offsetHeight-document.getElementById(id+'ScrollDown').offsetHeight-document.getElementById(id+'Scroller').offsetHeight;
 
 document.getElementById(id+'ScrollBox').style.top = document.getElementById(id).scrollTop + "px";
 document.getElementById(id+'Scroller').style.top =  posYScroller+"px";
}
   
function onMouseScrollDown (e,id)
{
 e = e || event;   
 mouse = getMouse(e, document.getElementById(id+'ScrollBody'));
 mouse[1]= mouse[1]+document.getElementById(id).scrollTop;
 posYScroller = mouse[1];
 widthScrollArrows = document.getElementById(id+'ScrollDown').offsetHeight*2;
 scrollYdelta = (document.getElementById(id).scrollHeight-(document.getElementById(id).offsetHeight-widthScrollArrows));
 document.getElementById(id).scrollTop = (posYScroller-document.getElementById(id+'ScrollDown').offsetHeight)/
                                         ((document.getElementById(id).offsetHeight-widthScrollArrows)/scrollYdelta);
 document.getElementById(id+'ScrollBox').style.top = document.getElementById(id).scrollTop + "px";
 document.getElementById(id+'Scroller').style.top =  posYScroller+"px";
}    
    
function addScroller(element)
{
 id=element.id;
 src='<div id="'+id+'ScrollBox" class="scrollBox">\n\
      <div id="'+id+'Scroller" class="scroller"></div>\n\
      <div id="'+id+'ScrollUp" class="scrollUp" onmousedown="scrollUp(\''+id+'\')"></div>\n\
      <div id="'+id+'ScrollBody" class="scrollBody" onmousedown="onMouseScrollDown(event,\''+id+'\')"></div>\n\
      <div id="'+id+'ScrollDown" class="scrollDown" onmousedown="scrollDown(\''+id+'\')"></div>';  

 jsText = 'document.getElementById("'+id+'").addEventListener ("mousewheel", onMouseWheelScroll, false);\n\
 document.getElementById("'+id+'").addEventListener ("DOMMouseScroll", onMouseWheelScroll, false);';

 js = document.createElement('script');
 js.setAttribute('type', 'text/javascript');
 js.setAttribute('defer', 'defer');
 js.innerHTML = jsText;
 element.innerHTML=element.innerHTML+src;
 element.appendChild(js);
}


Прописываем элемент

<div id="boxxx" style=" height: 300px; width: 200px; background-color: #aaaaaa; overflow: hidden; position: relative; left: 300px;" >
Длинный текст
</div>


И добовляем наш скроллбар на него:

 <script type='text/javascript'>
    addScroller(document.getElementById("boxxx"));
</script>



Данный код работает во всех последних браузерах.