PDA

View Full Version : tip:menu overflow



vahid4134
11 Aug 2008, 11:24 PM
hello my friends
at first i must say that my language is Persian and my English is too bad.
I was working with Extjs I faced to a trouble and it was menu overflowing.
i resolve this problem with my code but because I'm not a professional in JavaScript my code is not optimized. for this I prefer it to you like a tip.
please help me to make a better code
javascript

=================================================================================
Latest code & bugfixes :
- mousewhell navigation
- submenu bug fixed



Ext.override(Ext.menu.Menu, {
MaxHeight:undefined,
SaveState:true,
scrollRepeatInterval:100,
onScrollTop:function(){
var items = this.ul.dom.childNodes;
var h=0
for(var i=0;i<this.lastChild-1;i++){
h+=Ext.get(items[i]).getHeight();
}
if(this.lastChild!=0){
this.lastChild--;
this.nextChild--;
}

this.ul.scrollTo("top",h,true);
},
onScrollBottom:function(){
var items = this.ul.dom.childNodes;
if(this.nextChild>=items.length)return false;
var h=0;
for(var i=0;i<this.nextChild+1;i++){
h+=Ext.get(items[i]).getHeight();
}
h-=this.ul.getHeight();
if(this.nextChild<items.length){
this.nextChild++;
this.lastChild++;
}
this.ul.scrollTo("top",h,true);
return true;
},
onWheel:function(e){
w=e.getWheelDelta();
if(w==1) this.onScrollTop();
else if(w==-1)this.onScrollBottom();
}
, showAt : function(xy, parentMenu, /* private: */_e){
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
if(this.MaxHeight==undefined){
if(Ext.isIE)var maxHeight=document.documentElement.clientHeight-xy[1]-14;
else var maxHeight=window.innerHeight-xy[1]-14;
}
else{
maxHeight=this.MaxHeight-14;
}
var last_ul_height=this.ul.getHeight();
var items = this.ul.dom.childNodes;
if((last_ul_height>maxHeight || this.scrolled==true) && items.length>1){
var addWidth=0;
if(this.SaveState)
for(var i=0;i<this.lastChild;i++){
addWidth+=Ext.get(items[i]).getHeight();
}
var h=0;
for(var i = 0, len = items.length; i >= 0 && i < len; i++){
var iEl = Ext.get(items[i]);
h+=iEl.getHeight();
if(h>(maxHeight+addWidth)){
this.ul.setHeight(h-iEl.getHeight());
this.nextChild=i;
break;
}
}

if(!this.SaveState){
this.ul.scrollTo("top",0);
this.lastChild=0;
}
}

if((last_ul_height>maxHeight && this.scrolled!=true) && items.length>1){
var sb = this.el.createChild({
tag: "div", cls: "menu-scroll-bottom"
});
sb.addClassOnOver('x-menu-item-active menu-scroll-over');
this.BottomRepeater = new Ext.util.ClickRepeater(sb, {
interval : this.scrollRepeatInterval,
handler: this.onScrollBottom,
scope: this
});
var st = this.el.insertFirst({
tag: "div", cls: "menu-scroll-top"
});
st.addClassOnOver('x-menu-item-active menu-scroll-over');
this.TopRepeater = new Ext.util.ClickRepeater(st, {
interval : this.scrollRepeatInterval,
handler: this.onScrollTop,
scope: this
});
this.ul.on('mousewheel', this.onWheel, this);

this.scrollBottom = sb;
this.scrollTop = st;
this.scrolled=true;
this.lastChild=0;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}
});

css


.menu-scroll-bottom{
background-image:url(../../resources/images/default/layout/mini-bottom.gif);
background-repeat:no-repeat;
background-position:center;
height:7px;
cursor:pointer
}
.menu-scroll-top{
background-image:url(../../resources/images/default/layout/mini-top.gif);
background-repeat:no-repeat;
background-position:center;
height:7px;
cursor:pointer
}
.x-menu-list{
overflow:hidden
}
.menu-scroll-over {
height:5px;
}


thank you

Animal
11 Aug 2008, 11:39 PM
Well, it looks good, but I'm getting a strange effect.

Once I have scrolled the menu once, from then on it scrolls just on mouseover of the tip area.

BTW, can you post the images up here so we can test the look?

If we can get this optimized, I think it should go back into Ext.

vahid4134
12 Aug 2008, 12:48 AM
Well, it looks good, but I'm getting a strange effect.

Once I have scrolled the menu once, from then on it scrolls just on mouseover of the tip area.

BTW, can you post the images up here so we can test the look?

If we can get this optimized, I think it should go back into Ext.

Thanks Animal
i use this effect in some pages that I don't want page have scrolling in web browser such as http://www.extjs.com/deploy/dev/examples/layout/complex.html.
if menu be very large then like example page scrolls
I use the default image from layout image Extjs in resources/images/default/layout

Animal
12 Aug 2008, 3:50 AM
Yes, it looks very good now I am using the right path to the images. It was scrolling on mouseover because it focussed the half-hidden menu entry which scrolls it into view. Basically it all works well, so I think Jack should think about putting this in.

galdaka
12 Aug 2008, 4:42 AM
Excellent addon!!!


Live example: http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

Is posible pass max height by config?

Thanks in advance,

vahid4134
13 Aug 2008, 7:57 AM
Excellent addon!!!


Live example: http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

Is posible pass max height by config?

Thanks in advance,

Thanks galdaka for Live example;
I changed my code and I add some features:
1- size of ul is better
2- added SaveState config (if this config was not true scroll ul to top when menu shows again)
3- when menu show again if window size changed, ul height will change too
js code


Ext.override(Ext.menu.Menu, {
MaxHeight:undefined,
SaveState:false,

onScrollTop:function(){
this.ul.scroll("t",50,true);
},
onScrollBottom:function(){
this.ul.scroll("b",50,true);
}
, showAt : function(xy, parentMenu, /* private: */_e){
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
if(this.MaxHeight==undefined){
var maxHeight=Ext.lib.Dom.getViewHeight()-xy[1];
}
else{
maxHeight=this.MaxHeight
}
var last_ul_height=this.ul.getHeight();
if(last_ul_height>maxHeight || this.scrolled==true){
this.ul.setHeight(maxHeight-60);
if(!this.SaveState){
this.ul.scrollTo("top",1);
}
}

if(last_ul_height>maxHeight){
var sb = this.el.createChild({
tag: "div", cls: "menu_scroll_b"
});
sb.addClassOnOver('x-tab-scroller-left-over');
this.TopRepeater = new Ext.util.ClickRepeater(sb, {
interval : 200,
handler: this.onScrollBottom,
scope: this
});
var st = this.el.insertFirst({
tag: "div", cls: "menu_scroll_top"
});
st.addClassOnOver('x-tab-scroller-left-over');
this.leftRepeater = new Ext.util.ClickRepeater(st, {
interval : 200,
handler: this.onScrollTop,
scope: this
});


this.scrollBottom = sb;
this.scrollTop = st;
this.scrolled=true;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}
});

euchiyama
13 Aug 2008, 8:35 AM
That's interesting...

I required a similar solution for our project and went with creating a scrollbar on the menu...now I'm wondering whether I like your solution better.

http://img367.imageshack.us/img367/8118/ext1bl8.jpg

galdaka
13 Aug 2008, 10:19 AM
Thanks galdaka for Live example;
I changed my code and I add some features:
1- size of ul is better
2- added SaveState config (if this config was not true scroll ul to top when menu shows again)
3- when menu show again if window size changed, ul height will change too
js code


Ext.override(Ext.menu.Menu, {
MaxHeight:undefined,
SaveState:false,

onScrollTop:function(){
this.ul.scroll("t",50,true);
},
onScrollBottom:function(){
this.ul.scroll("b",50,true);
}
, showAt : function(xy, parentMenu, /* private: */_e){
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
if(this.MaxHeight==undefined){
var maxHeight=Ext.lib.Dom.getViewHeight()-xy[1];
}
else{
maxHeight=this.MaxHeight
}
var last_ul_height=this.ul.getHeight();
if(last_ul_height>maxHeight || this.scrolled==true){
this.ul.setHeight(maxHeight-60);
if(!this.SaveState){
this.ul.scrollTo("top",1);
}
}

if(last_ul_height>maxHeight){
var sb = this.el.createChild({
tag: "div", cls: "menu_scroll_b"
});
sb.addClassOnOver('x-tab-scroller-left-over');
this.TopRepeater = new Ext.util.ClickRepeater(sb, {
interval : 200,
handler: this.onScrollBottom,
scope: this
});
var st = this.el.insertFirst({
tag: "div", cls: "menu_scroll_top"
});
st.addClassOnOver('x-tab-scroller-left-over');
this.leftRepeater = new Ext.util.ClickRepeater(st, {
interval : 200,
handler: this.onScrollTop,
scope: this
});


this.scrollBottom = sb;
this.scrollTop = st;
this.scrolled=true;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}
});




Thanks!! Excellent work!!!

I update live example with your latest code!!

Various points:

1) Extra CSS for view any color on over arrows.

2) Automatic scroll on over in last item of menu when are more items.

Sorry for my English and thanks again,

wm003
14 Aug 2008, 12:17 PM
Perfect Solution! Thank you very much for sharing!:D

areichman
14 Aug 2008, 5:07 PM
I ended up doing the same thing as euchiyama noted above and just added a scrollbar. I did it using a simple CSS tweak, instead of adding new JS functionality.

http://extjs.com/forum/showthread.php?t=33475&page=2

Is there a reason for these attempts to do this sort of scrolling via JS? Something as simple as a scrollbar can easily be created by the browser. I'm just wondering why it could be an advantage to have Ext fully render the scroll using images like this when CSS works like it should.

Regardless, nice job on the plugin. It looks nice.

vahid4134
15 Aug 2008, 4:56 AM
Thanks!! Excellent work!!!

I update live example with your latest code!!

Various points:

1) Extra CSS for view any color on over arrows.

2) Automatic scroll on over in last item of menu when are more items.

Sorry for my English and thanks again,

Thanks galdaka;
my code is changed.
please use and help me to complete it


Ext.override(Ext.menu.Menu, {
MaxHeight:undefined,
SaveState:true,

onScrollTop:function(){
var items = this.ul.dom.childNodes;
var h=0
for(var i=0;i<this.lastChild-1;i++){
h+=Ext.get(items[i]).getHeight();
}
if(this.lastChild!=0){
this.lastChild--;
this.nextChild--;
}

this.ul.scrollTo("top",h,true);
},
onScrollBottom:function(){
var items = this.ul.dom.childNodes;
if(this.nextChild>=items.length)return false;
var h=0;
for(var i=0;i<this.nextChild+1;i++){
h+=Ext.get(items[i]).getHeight();
}
h-=this.ul.getHeight();
if(this.nextChild<items.length){
this.nextChild++;
this.lastChild++;
}
this.ul.scrollTo("top",h,true);
return true;
}
, showAt : function(xy, parentMenu, /* private: */_e){
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
if(this.MaxHeight==undefined){
var maxHeight=Ext.lib.Dom.getViewHeight()-xy[1]-10;
}
else{
maxHeight=this.MaxHeight-10
}
var last_ul_height=this.ul.getHeight();
if(last_ul_height>maxHeight || this.scrolled==true){
var items = this.ul.dom.childNodes;
var addWidth=0;
if(this.SaveState)
for(var i=0;i<this.lastChild;i++){
addWidth+=Ext.get(items[i]).getHeight();
}
var h=0;
for(var i = 0, len = items.length; i >= 0 && i < len; i++){
var iEl = Ext.get(items[i]);
h+=iEl.getHeight();
if(h>(maxHeight+addWidth)){
this.ul.setHeight(h-iEl.getHeight());
this.nextChild=i;
break;
}
}

if(!this.SaveState){
this.ul.scrollTo("top",0);
this.lastChild=0;
}
}

if(last_ul_height>maxHeight && this.scrolled!=true){
var sb = this.el.createChild({
tag: "div", cls: "menu_scroll_b"
});
sb.addClassOnOver('x-menu-item-active');
this.BottomRepeater = new Ext.util.ClickRepeater(sb, {
interval : 200,
handler: this.onScrollBottom,
scope: this
});
var st = this.el.insertFirst({
tag: "div", cls: "menu_scroll_top"
});
st.addClassOnOver('x-menu-item-active');
this.TopRepeater = new Ext.util.ClickRepeater(st, {
interval : 200,
handler: this.onScrollTop,
scope: this
});


this.scrollBottom = sb;
this.scrollTop = st;
this.scrolled=true;
this.lastChild=0;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}
});

vahid4134
15 Aug 2008, 5:08 AM
I ended up doing the same thing as euchiyama noted above and just added a scrollbar. I did it using a simple CSS tweak, instead of adding new JS functionality.

http://extjs.com/forum/showthread.php?t=33475&page=2

Is there a reason for these attempts to do this sort of scrolling via JS? Something as simple as a scrollbar can easily be created by the browser. I'm just wondering why it could be an advantage to have Ext fully render the scroll using images like this when CSS works like it should.

Regardless, nice job on the plugin. It looks nice.
hi areichman
I can`t exactly answer your question.
I only ask one question from you.
why we should use Ext.button instead input button and etc?

jelt
16 Aug 2008, 1:35 AM
Lot of thanks for sharing this great code !

But please, update the first post with modification list.

galdaka
17 Aug 2008, 12:11 PM
Thanks galdaka;
my code is changed.
please use and help me to complete it


Ext.override(Ext.menu.Menu, {
MaxHeight:undefined,
SaveState:true,

onScrollTop:function(){
var items = this.ul.dom.childNodes;
var h=0
for(var i=0;i<this.lastChild-1;i++){
h+=Ext.get(items[i]).getHeight();
}
if(this.lastChild!=0){
this.lastChild--;
this.nextChild--;
}

this.ul.scrollTo("top",h,true);
},
onScrollBottom:function(){
var items = this.ul.dom.childNodes;
if(this.nextChild>=items.length)return false;
var h=0;
for(var i=0;i<this.nextChild+1;i++){
h+=Ext.get(items[i]).getHeight();
}
h-=this.ul.getHeight();
if(this.nextChild<items.length){
this.nextChild++;
this.lastChild++;
}
this.ul.scrollTo("top",h,true);
return true;
}
, showAt : function(xy, parentMenu, /* private: */_e){
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
if(this.MaxHeight==undefined){
var maxHeight=Ext.lib.Dom.getViewHeight()-xy[1]-10;
}
else{
maxHeight=this.MaxHeight-10
}
var last_ul_height=this.ul.getHeight();
if(last_ul_height>maxHeight || this.scrolled==true){
var items = this.ul.dom.childNodes;
var addWidth=0;
if(this.SaveState)
for(var i=0;i<this.lastChild;i++){
addWidth+=Ext.get(items[i]).getHeight();
}
var h=0;
for(var i = 0, len = items.length; i >= 0 && i < len; i++){
var iEl = Ext.get(items[i]);
h+=iEl.getHeight();
if(h>(maxHeight+addWidth)){
this.ul.setHeight(h-iEl.getHeight());
this.nextChild=i;
break;
}
}

if(!this.SaveState){
this.ul.scrollTo("top",0);
this.lastChild=0;
}
}

if(last_ul_height>maxHeight && this.scrolled!=true){
var sb = this.el.createChild({
tag: "div", cls: "menu_scroll_b"
});
sb.addClassOnOver('x-menu-item-active');
this.BottomRepeater = new Ext.util.ClickRepeater(sb, {
interval : 200,
handler: this.onScrollBottom,
scope: this
});
var st = this.el.insertFirst({
tag: "div", cls: "menu_scroll_top"
});
st.addClassOnOver('x-menu-item-active');
this.TopRepeater = new Ext.util.ClickRepeater(st, {
interval : 200,
handler: this.onScrollTop,
scope: this
});


this.scrollBottom = sb;
this.scrollTop = st;
this.scrolled=true;
this.lastChild=0;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}
});


I

vahid4134
17 Aug 2008, 10:41 PM
[QUOTE=galdaka;210507]I

galdaka
18 Aug 2008, 12:24 AM
Thanks,


View the results in IE6 and FF2. In IE6 when you maintain the arrow clicked for scroll menu, produced a strange effect. IN FF2 works fine. Is there a 1px defect in FF2 over arrows images.

Excellent work!! I think this extension must be added to a Ext base core!!!

Greetings,

galdaka
27 Aug 2008, 1:41 PM
Bump!!!

Several bug with submenus!!!

View bug in action: http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

View image

vahid4134
29 Aug 2008, 10:22 AM
Hi,

The code is updated :
- Mouse wheel action is added to the script. You can now navigate up and down using your mouse wheel!
- Submenu problem fixed

Todo :
- IE still can't show the arrows as a small image ( this must be a problem with the CSS ). I have no idea how to correct it. If you're familiar with IE, try to fix the problem please!

JS


Ext.override(Ext.menu.Menu, {
MaxHeight:undefined,
SaveState:true,
scrollRepeatInterval:100,
onScrollTop:function(){
var items = this.ul.dom.childNodes;
var h=0
for(var i=0;i<this.lastChild-1;i++){
h+=Ext.get(items[i]).getHeight();
}
if(this.lastChild!=0){
this.lastChild--;
this.nextChild--;
}

this.ul.scrollTo("top",h,true);
},
onScrollBottom:function(){
var items = this.ul.dom.childNodes;
if(this.nextChild>=items.length)return false;
var h=0;
for(var i=0;i<this.nextChild+1;i++){
h+=Ext.get(items[i]).getHeight();
}
h-=this.ul.getHeight();
if(this.nextChild<items.length){
this.nextChild++;
this.lastChild++;
}
this.ul.scrollTo("top",h,true);
return true;
},
onWheel:function(e){
w=e.getWheelDelta();
if(w==1) this.onScrollTop();
else if(w==-1)this.onScrollBottom();
}
, showAt : function(xy, parentMenu, /* private: */_e){
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
if(this.MaxHeight==undefined){
if(Ext.isIE)var maxHeight=document.documentElement.clientHeight-xy[1]-14;
else var maxHeight=window.innerHeight-xy[1]-14;
}
else{
maxHeight=this.MaxHeight-14;
}
var last_ul_height=this.ul.getHeight();
var items = this.ul.dom.childNodes;
if((last_ul_height>maxHeight || this.scrolled==true) && items.length>1){
var addWidth=0;
if(this.SaveState)
for(var i=0;i<this.lastChild;i++){
addWidth+=Ext.get(items[i]).getHeight();
}
var h=0;
for(var i = 0, len = items.length; i >= 0 && i < len; i++){
var iEl = Ext.get(items[i]);
h+=iEl.getHeight();
if(h>(maxHeight+addWidth)){
this.ul.setHeight(h-iEl.getHeight());
this.nextChild=i;
break;
}
}

if(!this.SaveState){
this.ul.scrollTo("top",0);
this.lastChild=0;
}
}

if((last_ul_height>maxHeight && this.scrolled!=true) && items.length>1){
var sb = this.el.createChild({
tag: "div", cls: "menu-scroll-bottom"
});
sb.addClassOnOver('x-menu-item-active menu-scroll-over');
this.BottomRepeater = new Ext.util.ClickRepeater(sb, {
interval : this.scrollRepeatInterval,
handler: this.onScrollBottom,
scope: this
});
var st = this.el.insertFirst({
tag: "div", cls: "menu-scroll-top"
});
st.addClassOnOver('x-menu-item-active menu-scroll-over');
this.TopRepeater = new Ext.util.ClickRepeater(st, {
interval : this.scrollRepeatInterval,
handler: this.onScrollTop,
scope: this
});
this.ul.on('mousewheel', this.onWheel, this);

this.scrollBottom = sb;
this.scrollTop = st;
this.scrolled=true;
this.lastChild=0;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}
});


css


.menu-scroll-bottom{
background-image:url(../../resources/images/default/layout/mini-bottom.gif);
background-repeat:no-repeat;
background-position:center;
height:7px;
cursor:pointer
}
.menu-scroll-top{
background-image:url(../../resources/images/default/layout/mini-top.gif);
background-repeat:no-repeat;
background-position:center;
height:7px;
cursor:pointer
}
.x-menu-list{
overflow:hidden
}
.menu-scroll-over {
height:5px;
}

galdaka
30 Aug 2008, 4:08 AM
Hi,

Last version uploaded in: http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

P.D: strange effect in IE6 on scroll menu. In FF2 works perfect!!

Thanks in advance,

jelt
30 Aug 2008, 11:16 PM
Hi,

Scroll with wheel work good on IE7 but Date & color panels are truncated (width=same as regular menu width)

KRavEN
5 Sep 2008, 11:42 AM
Here is a simpler override that uses the standard scrollbar and works with mouse wheel.


Ext.override(Ext.menu.Menu, {
showAt : function(xy, parentMenu, /* private: */_e)
{
this.parentMenu = parentMenu;
if (!this.el)
{
this.render();
}
if (_e !== false)
{
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
this.el.setXY(xy);
this.assertMenuHeight(this);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
},

assertMenuHeight : function(m)
{
var maxHeight = Ext.getBody().getHeight() - 20;
if (m.el.getHeight() > maxHeight)
{
m.el.setHeight(maxHeight);
m.el.applyStyles('overflow-y:auto;');
}
}
});

galdaka
6 Sep 2008, 1:10 AM
Here is a simpler override that uses the standard scrollbar and works with mouse wheel.


Ext.override(Ext.menu.Menu, {
showAt : function(xy, parentMenu, /* private: */_e)
{
this.parentMenu = parentMenu;
if (!this.el)
{
this.render();
}
if (_e !== false)
{
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
this.el.setXY(xy);
this.assertMenuHeight(this);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
},

assertMenuHeight : function(m)
{
var maxHeight = Ext.getBody().getHeight() - 20;
if (m.el.getHeight() > maxHeight)
{
m.el.setHeight(maxHeight);
m.el.applyStyles('overflow-y:auto;');
}
}
});

I Know this solution but I prefer the extension. You have more posibilities with this extension. For example, this extension would be the first step for collapse / expand "not used items" in a menu like MS Office style.

Greetings,

Greetings,

cazzadori
16 Sep 2008, 6:05 AM
Ok, fixed.



Ext.override(Ext.menu.Menu, {
MaxHeight:undefined
,SaveState:true
,scrollRepeatInterval:100
,TopAndBottomSpace:24
,scrollRunner:new Ext.util.TaskRunner()
,scrollTask:undefined
,clientHeight:undefined
,fnScrollTop:function(){
var items = this.ul.dom.childNodes;
var h = 0;
for(var i = 0; i < this.lastChild - 1; i++){
h += Ext.get(items[i]).getHeight();
}
if(this.lastChild!=0){
this.lastChild--;
this.nextChild--;
}
this.ul.scrollTo("top",h,true);
}
,fnScrollBottom:function(){
var items = this.ul.dom.childNodes;
if(this.nextChild >= items.length){
return false;
}
var h=0;
for(var i=0;i<this.nextChild+1;i++){
h += Ext.get(items[i]).getHeight();
}
h -= this.ul.getHeight();
if(this.nextChild < items.length){
this.nextChild++;
this.lastChild++;
}
this.ul.scrollTo("top", h, true);
return true;
}
,onWheel:function(e){
w = e.getWheelDelta();
if (w == 1){
this.fnScrollTop();
}
else{
if(w==-1){
this.fnScrollBottom();
}
}
}
,startScrollBottom:function(){
this.scrollTask = {
run:this.fnScrollBottom
,interval:200 //0.2 second
,scope:this
}
this.scrollRunner.start(this.scrollTask);
}
,startScrollTop:function(){
this.scrollTask = {
run:this.fnScrollTop
,interval:200 //0.2 second
,scope:this
}
this.scrollRunner.start(this.scrollTask);
}
,stopScrolling:function(){
if (!Ext.isEmpty(this.scrollTask)){
this.scrollRunner.stop(this.scrollTask);
}
scrolTask = undefined;
}
,showAt:function(xy, parentMenu, _e){
var maxHeight;
this.parentMenu = parentMenu;
if(!this.el){
this.render();
}
if(_e !== false){
this.fireEvent("beforeshow", this);
xy = this.el.adjustForConstraints(xy);
}
this.clientHeight = ((Ext.isIE) ? document.documentElement.clientHeight : window.innerHeight);
if(this.MaxHeight == undefined){
maxHeight = this.clientHeight - xy[1] - this.TopAndBottomSpace;
}
else{
maxHeight = this.MaxHeight - this.TopAndBottomSpace;
}
var last_ul_height = this.ul.getHeight();
var items = this.ul.dom.childNodes;
if((last_ul_height > maxHeight || this.addedScrolling == true) && items.length > 1){
var addWidth = 0;
if(this.SaveState){
for(var i = 0; i < this.lastChild; i++){
addWidth += Ext.get(items[i]).getHeight();
}
}
var h = 0;
for(var i = 0, len = items.length; i >= 0 && i < len; i++){
var iEl = Ext.get(items[i]);
h += iEl.getHeight();
if(h > (maxHeight + addWidth)){
this.ul.setHeight(h - iEl.getHeight());
this.nextChild = i;
break;
}
}
if(!this.SaveState){
this.ul.scrollTo("top",0);
this.lastChild=0;
}
}
if((last_ul_height > maxHeight && this.addedScrolling != true) && items.length > 1){
var sb = this.el.createChild({
tag:"div"
,cls:"menu-scroll-bottom"
});
sb.addClassOnOver('x-menu-item-active menu-scroll-over');
sb.on({
'mouseover':{
fn:this.startScrollBottom
,scope:this
,options:{
delay:this.scrollRepeatInterval
,scope:this
}
}
,'mouseout':{
fn:this.stopScrolling
,scope:this
,options:{
scope:this
}
}
});
var st = this.el.insertFirst({
tag:"div"
,cls: "menu-scroll-top"
});
st.addClassOnOver('x-menu-item-active menu-scroll-over');
st.on({
'mouseover':{
fn:this.startScrollTop
,scope:this
,options:{
delay:this.scrollRepeatInterval
,scope:this
}
}
,'mouseout':{
fn:this.stopScrolling
,scope:this
,options:{
scope: this
}
}
});

this.ul.on('mousewheel', this.onWheel, this);
this.scrollBottom = sb;
this.scrollTop = st;
this.addedScrolling = true;
this.lastChild = 0;
}
this.el.setXY(xy);
this.el.show();
this.hidden = false;
this.focus();
this.fireEvent("show", this);
}

});


some minor changes also to the css



.menu-scroll-bottom{
background-image:url(/testExtJS/js/ext-js/resources/images/default/layout/mini-bottom.gif);
background-repeat:no-repeat;
background-position:center;
height:12px;
cursor:pointer
}
.menu-scroll-top{
background-image:url(/testExtJS/js/ext-js/resources/images/default/layout/mini-top.gif);
background-repeat:no-repeat;
background-position:center;
height:12px;
cursor:pointer
}
.x-menu-list{
overflow:hidden;
}
.menu-scroll-over {
height:10px;
}


I've changed the height of the menu-scroll-top and menu-scroll-bottom to make it easyer for the user to scroll

cazzadori
16 Sep 2008, 6:10 AM
Sorry I've made an error while cerating the post.
I'll correct indentation the code section as soon as possible (about 3 hours)

galdaka
16 Sep 2008, 7:02 AM
Sorry I've made an error while cerating the post.
I'll correct indentation the code section as soon as possible (about 3 hours)

I upload Your code. But there are some errors in IE6...

http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

Greetings,

cazzadori
16 Sep 2008, 7:12 AM
I upload Your code. But there are some errors in IE6...

http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

Greetings,

I've to correct the code in the post, from where I'm i can't reach the edit/preview page.
I've made some test in IE6 and i think I think there's something wrong with
clientHeight.

I'll modify the post as soon as possible.

cazzadori
16 Sep 2008, 9:57 AM
Ok, I've corrected the code in my previous post.

Let me know what you think.
:D

galdaka
16 Sep 2008, 11:29 AM
Ok, I've corrected the code in my previous post.

Let me know what you think.
:D

Same problems than last version in IE6

http://extjs.com/forum/showthread.php?p=210684#post210684

And strange effect when scroll in IE6.

Greetings,

kmbarr
4 Oct 2008, 7:30 PM
This looks really good in Firefox, but it looks like the IE6 problem was never fixed, it is incorrectly calculating the maxHeight when not specified. The current clientHeight reference is returning "0" as-is.

Borrowing from some earlier code modifications, I was able to get this working well in both FF3 and IE6 by changing this line:

this.clientHeight = ((Ext.isIE) ? document.documentElement.clientHeight : window.innerHeight);

to:

this.clientHeight = Ext.lib.Dom.getViewHeight();

galdaka
5 Oct 2008, 1:42 AM
This looks really good in Firefox, but it looks like the IE6 problem was never fixed, it is incorrectly calculating the maxHeight when not specified. The current clientHeight reference is returning "0" as-is.

Borrowing from some earlier code modifications, I was able to get this working well in both FF3 and IE6 by changing this line:

this.clientHeight = ((Ext.isIE) ? document.documentElement.clientHeight : window.innerHeight);

to:

this.clientHeight = Ext.lib.Dom.getViewHeight();

I upload your modification to: http://www.jadacosta.es/extjs/examples/scrollmenu/menus.html

[B]In IE7 the submenu

karieanis
9 Oct 2008, 4:11 PM
Thanks for the code - I was thinking I was going to have to code something similar to this myself, certainly saves me a lot of time, and it looks very nice.

Keep up the good work :)

shade
17 Oct 2008, 10:01 AM
This extension is great, but auto-width of the menu is not working correctly in IE7 because of the "overflow: none". It renders as a fixed-with and will cut off anything beyond that width. Switching "overflow-y: none" doesn't help either.

Has anyone come up with a fix other than to specify a static width?

mjlecomte
18 Oct 2008, 4:16 AM
Why not post this to repository instead of all the manual updates? Easier to find later...blah blah blah...

shade
20 Oct 2008, 9:55 AM
For anyone else who is having issues with autowidth on IE7, I fixed it by removing the CSS for x-menu-list from the extension, and adding "this.ul.applyStyles('overflow-y: hidden;');" right before "this.el.show();" in showAt().

galdaka
20 Oct 2008, 10:05 AM
For anyone else who is having issues with autowidth on IE7, I fixed it by removing the CSS for x-menu-list from the extension, and adding "this.ul.applyStyles('overflow-y: hidden;');" right before "this.el.show();" in showAt().

Please post the corrections in a file and upload here. I put the corrections in www.galdaka.es (http://www.galdaka.es) for test all!

Thanks in advance,

felsangom
19 Aug 2009, 3:15 AM
Hey!
Nice work.
I just miss comments on your code.

Thanks

kuiava
26 Aug 2009, 11:37 AM
Hello, very nice its extension. But I have a problem: the menu is loaded from a JSON with it the first time that the menu is created, the scroll does not appear, but the second time it appears. You can tell me how I could solve this problem?

Thanks

sureshraja.crt
1 Sep 2009, 8:26 PM
Thanks lot for who giving solution for menu scroll