Hi all.
I decided for a bit of fun and revision I'd write a vertical scrollable menu which doesn't have a scrollbar. Anyway I thought I'd share the fruits of my labour, criticism encouraged.
includes cheep, cheerful demo.
Cheers.Code:<html> <head> <script type="text/javascript"> var $ = document; /*---------Vertical Menu---------------- @description: Create a vertical menu that is scrollable without a scroll bar. @Prerequisites CSS: .VMenu default menu container styles, inherit styles .VMenuItem Default menu item container class Static Members: menus[]: (VMenu) Array of menu objects Static Methods: generateVMId() returns a unique identifier suitable for menu objects getMenuById(id) return a menu object identified by it's VMId id = VMId scrolling(e) scroll event handler which delegates to the appropriate menu's scrollMenuItems() Members: VMId: (String) Unique element and menu item identifier formatted <VM#> width: (int) width of menu items height: (int) height of menu items containerX: (int) menu horizontal offset from container's origin containerY: (int) menu vertical offset from container's origin noOfVisible: (int) number of visible menu items menuItems[]: (VMenuItem) menu item object array className: (String) css class name for menu Methods: generateMenu() return DOM object of the menu addMenuItem(content, callback) Add menu item to the menu object content = (String) innerHTML for menu item callback = (Function)onclick event scrollMenuItems(dirFlag) Called from onscroll event updates the visibility affected elements dirFlag = (int) positive scrolls down, negative scrolls up, 0 none; setSize(width, height) set dimensions used when creating menu items width = (css measurement/int) width of menu items height = (css measurement/int) height of menu items setPosition(x, y) set offsets from the menu object's container's origin x = (int) horizontal offset y = (int) vertical offset --------------------------------------*/ /*--------- Constructor --------------*/ var VMenu = function(){ this.VMId = VMenu.generateVMId(); VMenu.menus.push(this); } /*--------- Static members -----------*/ VMenu.menus = new Array(); /*--------- Static methods -----------*/ VMenu.generateVMId = function(){ var name = null; var i = 0; while(name==null){ if(!$.getElementById("VM"+i)){ return name = "VM"+i; } i++; } } VMenu.getMenuById =function(id){ for(var i = 0;i<VMenu.menus.length;i++){ if(VMenu.menus[i].VMId == id) return VMenu.menus[i]; } return false; } VMenu.scrolling = function(e){ var menu; if(e.currentTarget){ if(menu = VMenu.getMenuById(e.currentTarget.id)){ menu.scrollMenuItems((e.wheelDelta)? e.wheelDelta*-1: e.detail); e.preventDefault(); } }else{ var id; var el = e.srcElement; while((menu = VMenu.getMenuById(VMenuItem.getParentIdFromValue(el.id)))== false&& el){ el = el.parentNode; } if(menu){ menu.scrollMenuItems(-1*e.wheelDelta); e.returnValue = false; } } } /*--------- Members ------------------*/ var VM = VMenu.prototype; VM.VMId = ""; VM.width = 0; VM.height = 0; VM.containerX = 0; VM.containerY = 0; VM.noOfVisible = 1; VM.menuItems = new Array(); VM.className = "VMenu"; /*--------- Methods -----------*/ VM.generateMenu = function(){ var menu = null; if(menu = $.getElementById(this.VMId)){ menu.parentNode.removeChild(menu); } if(this.menuItems.length>0){ var menuContainer = $.createElement("div"); menuContainer.id = this.VMId; menuContainer.className = this.className; menuContainer.style.left = this.containerX; menuContainer.style.top = this.containerY; if(menuContainer.addEventListener){ menuContainer.addEventListener('DOMMouseScroll', VMenu.scrolling, false); menuContainer.addEventListener('mousewheel', VMenu.scrolling, false); } else{ menuContainer.attachEvent("onmousewheel", VMenu.scrolling); } for(var i = 0;i<this.menuItems.length;i++){ menuItem =this.menuItems[i].createElement(); menuItem.style.width = this.width; menuItem.style.height = this.height; menuContainer.appendChild(menuItem); } return menuContainer; } return false; } VM.addMenuElement = function(content, callback){ var len = this.menuItems.length; this.menuItems.push(new VMenuItem(content,this.VMId+"-"+len.toString(), callback)); if(len<this.noOfVisible) this.menuItems[len].visible = true; else this.menuItems[len].visible = false; return this.menuItems[this.menuItems.length -1]; } VM.scrollMenuItems = function(dirFlag){ if(dirFlag>0){ for(var i=0;i<this.menuItems.length;i++){ if(this.menuItems[i].visible == true&&i+this.noOfVisible<this.menuItems.length){ this.menuItems[i].changeVisibility(false); this.menuItems[i+this.noOfVisible].changeVisibility(true); i=this.menuItems.length; } } }else{ for(var i=this.menuItems.length-1;i>-1;i--){ if(this.menuItems[i].visible == true&&i-this.noOfVisible>-1){ this.menuItems[i].changeVisibility(false); this.menuItems[i-this.noOfVisible].changeVisibility(true); i=-1; } } } } VM.setSize = function(width, height){ this.width = width; this.height = height; } VM.setPosition = function(x, y){ this.containerX = x; this.containerY = y; }; /*---------Vertical Menu Item ----------- Static Members: Static Methods: getVisibility(visible) returns css-display property block or none visible = (Bool) true:block, false:none getParentIdFromValue(str) returns a menu-compatible VMId if found in the comparison string str = (String) string for evaluation Members: id: (String) unique identifier formatted <VM#-#> content: (String) content of menu item className: (String) css Class name for menu item visible: (Bool) menu item is visible callback: (Function) onclick event Methods: changeVisibility(visible) update visiblity of menu item and DOM object visible = (Bool) true: visible, false:hidden changeClass(className) Change menu item's className if the className exists className = Name of class new item class createElement() Create menu item DOM Object /*--------- Constructor --------------*/ var VMenuItem = function(content, id, callback){ this.id = id; this.content = content; this.callback = callback; } /*--------- Static members -----------*/ /*--------- Static methods -----------*/ VMenuItem.getVisibility = function(isVisible){ if(isVisible == true) return "block"; else return "none"; } VMenuItem.getParentIdFromValue = function(str){ var matches; if(matches = /^VM+[0-9]*/.exec(str)) return matches[0]; return false; } /*--------- Members -----------*/ var VMI = VMenuItem.prototype; VMI.Id = ""; VMI.content = ""; VMI.className = "VMenuItem"; VMI.visible = true; VMI.callback = null; /*--------- Members -----------*/ VMI.changeVisibility = function(visible){ if(this.visible!=visible){ el = $.getElementById(this.id).style.display=VMenuItem.getVisibility(visible); this.visible = visible; } } VMI.changeClass = function(className){ var styleSheets = $.styleSheets; var rules; var results; var x, y; for(x=0;x<styleSheets.length;x++){ rules = (styleSheets[x].cssRules)? styleSheets[x].cssRules: styleSheets[x].rules; for(y=0;y<rules.length;y++){ if(results = /^\.?\w+/.exec((rules[y].cssText)? rules[y].cssText: rules[y].selectorText)){ if(results[0].replace(".", "").toLowerCase() == className.toLowerCase()){ this.className = className; return true; } } } } return false; } VMI.createElement = function(){ var el = $.createElement("div"); el.id = this.id; el.className = this.className; el.onclick = this.callback; el.style.display = VMenuItem.getVisibility(this.visible); el.innerHTML = this.content; return el; }; //===================================== function init(){ var test = new VMenu(); //Set menu item sizes test.setSize(150,25); test.setPosition(5,5); test.noOfVisible=5; //Add some menu items test.addMenuElement("Home",function(e){alert("Home");}); test.addMenuElement("Fire",function(){alert("Fire");}); test.addMenuElement("Happiness",function(){alert("Happiness");}); test.addMenuElement("water",function(){alert("Water");}); test.addMenuElement("rain",function(){alert("Rain");}); test.addMenuElement("Umberalla",function(){alert("Umberalla");}); test.addMenuElement("Car",function(){alert("Car");}); test.addMenuElement("Taxi",function(){alert("Taxi");}); test.addMenuElement("End",function(){alert("End");}); //Alternate menut item class var even = true; for(var i=0;i<test.menuItems.length;i++){ if(even){ test.menuItems[i].changeClass("testVM"); } even = !even; } //create and append menu to the container $.getElementById("test").appendChild(test.generateMenu()); } </script> <!-- Demo stuff --> <style> #test{ position:absolute; width:100px; height:160px; left:200px; top:50px; background-color:#2F4F4F; } .VMenu{ position:absolute; text-align:center; cursor:pointer; } div.VMenuItem{ position:relative; width:100%; margin:2px; background-color:#FDFDF0; border: 1px #008B8B solid; } div.VMenuItem:hover, div.testVM:hover{ background-color:#B4EEB4; border-width:2px; } .testVM{ position:relative; width:100%; margin:2px; background-color:#E0EEEE; border: 1px #008B8B solid; } </style> </head> <body onload="init();"> <div id="test"></div> </body> </html>


Reply With Quote
Bookmarks