As the major browsers render the select element is different, so under each browser displays is different also, the mainest is by default UI is too rough, even through the CSS to beautify can't achieve the result that is very beautiful. This for those of us who focus on UX front-end developer is intolerable. So at the time of project are not too busy, just planning to write a simulation of the select control. Then put the details of the implementation, the problems and how to use and share.
1. Implementation details

globalEvent: function () {
//document to add the click event, the user processing each jselect closed
var target element,
the className,
elem,
wrapper,
the status,
that=this;

squid.on(document, 'click', function(event) {
target=event.target,
className=target.className;

switch(className) {
case 'select-icon':
case 'select-default unselectable':
elem=target.tagName.toLowerCase()==='div' ? target : target.previousSibling
wrapper=elem.nextSibling.nextSibling

//firefox 鼠标右键会触发click事件
//鼠标左键点击执行
if(event.button===0) {
//初始化选中元素
that.initSelected(elem)
if(squid.isHidden(wrapper)) {
status='block'
//关闭所有展开jselect
that.closeSelect()
}else{
status='none'
}
wrapper.style.display=status
elem.focus()
}else if(event.button===2){
wrapper.style.display='none'
}
that.zIndex(wrapper)
break
case 'select-option':
case 'select-option selected':
if(event.button===0) {
that.fireSelected(target, target.parentNode.parentNode.previousSibling.previousSibling)
wrapper.style.display='none'
}
break
default:
while(target &&target.nodeType !==9) {
if(target.nodeType===1) {
if(target.className==='select-wrapper') {
return
}
}
target=target.parentNode
}
that.closeSelect()
break
}
})
}

globalEvent实现了在document绑定click事件,然后在页面上触发点击事件的时候通过事件代理来判断当前点击元素是否是需要进行处理的目标元素,判断条件是通过元素的class,代码中语句的分支分别是:展开当前点击的jselect元素下拉、选中点击列表项、判断是否需要关闭jselect。

initView method is as follows:

initView: function (elems) {
var I=0,
elem,
length=elems. Length,
enabled.

the for (; I <length; i++) {
elem=elems [I]
enabled=elem. GetAttribute (' data - enabled)
//system is used to select the
if (! Enabled | | enabled==='true')
the continue
if (squids. IsVisible (elem))
elem. The style.css. Display='none'

this. Create (elem)
}
}

initView realized will need to use jselect replace the select elements to hide and then call the create method, the overall structure of the single jselect and inserted into the page and replace the default select location.

the create method is as follows:

create: function (elem) {
var data=http://www.script-home.com//article/[],
I=0,
length,
option,
options, value,

text,
obj,
the lis,
ul,
_default,
icon,
selectedText,
selectedValue,
div,
wrapper,
position,
left,
top,
cssText;

options=elem.getElementsByTagName('option')
length=options.length
for(; i option=options[i]
value=http://www.script-home.com//article/option.value
text=option.innerText || option.textContent

obj={
value: value,
text: text
}
if(option.selected) {
selectedValue=http://www.script-home.com//article/value
selectedText=text
obj['selected']=true
}
data.push(obj)
}

lis=this.render(this.tmpl, data)
ul='

    '
    //
    div=document.createElement('div')
    div.style.display='none'
    div.className='select-wrapper'
    //已选元素
    _default=document.createElement('div')
    _default.className='select-default unselectable'
    _default.unselectable='on'
    //让div元素能够获取焦点
    _default.setAttribute('tabindex', '1')
    _default.setAttribute('data-value', selectedValue)
    _default.setAttribute('hidefocus', true)
    _default.innerHTML=selectedText
    div.appendChild(_default)
    //选择icon
    icon=document.createElement('span')
    icon.className='select-icon'
    div.appendChild(icon)
    //下拉列表
    wrapper=document.createElement('div')
    wrapper.className='select-list hide'
    wrapper.innerHTML=ul
    //生成新的元素
    div.appendChild(wrapper)
    //插入到select元素后面
    elem.parentNode.insertBefore(div, null)
    //获取select元素left top值
    //先设置select显示,取完left, top值后重新隐藏
    elem.style.display='block'
    //事件绑定
    this.sysEvent(div)
    position=squid.position(elem)
    elem.style.display='none'
    left=position.left
    top=position.top
    cssText='left: ' + left + 'px; Top: '+ top +px; Display: block; '
    div. Style. CssText=cssText
    }

    the create method implements the system copy to the jselect drop-down list, select data jselect hierarchy is the outermost layer has a class element package for the select - wrapper, there is a class to select the default -> element is used to store the selected element, the class for the select - icon users tell users a drop-down list, this is the class for the select - div elements inside the list contains a ul element from the system inside the select copy of the text and the value of the option respectively in li element text and data - the value attribute. SysEvent method is to add click on close to jselect drop-down list events as well as the keyboard and press enter to select the drop-down selection drop-down elements. Squids. Position method is used to retrieve system select the position of the element relative to the offsetParent, here and get the select element system there is a difference between the offset. Is actually get their top offset, the left value then minus the offsetParent respectively for the offset of the top and left. The last is to put the jselect behind the select element is inserted into the system, display the page.

    jselect create basic flow is described above in this way, the rest is where details of implementation, such as: click on the drop-down displays the last selected elements, the concrete realization of the function is initSelected as follows

    initSelected: function (elem) {
    var curText=elem. The innerText | | elem. TextContent,
    curValue=http://www.script-home.com//article/elem.getAttribute (' data - the value),
    wrapper=elem. NextSibling. NextSibling,
    n=wrapper. FirstChild. FirstChild,
    text, value,

    dir,
    min=0,
    Max,
    hidden=false;

    for(; n; n=n.nextSibling) {
    text=n.innerText || n.textContent
    value=http://www.script-home.com//article/n.getAttribute('data-value')
    if(curText===text &&curValue=http://www.script-home.com//article/==value) {
    //显示已选中元素
    if(squid.isHidden(wrapper)) {
    wrapper.style.display='block'
    hidden=true
    }
    max=wrapper.scrollHeight
    if(n.offsetTop> (max/2)) {
    if(wrapper.clientHeight + wrapper.scrollTop===max)
    dir='up'
    else
    dir='down'
    }else{
    if(wrapper.scrollTop===min)
    dir='down'
    else
    dir='up'
    }
    this.inView(n, wrapper, dir)
    if(hidden)
    wrapper.style.display='none'
    this.activate(n)
    break
    }
    }
    }

    该方法接收class为select-default的div元素即用于存放用户已选择内容的元素,具体实现方式是先遍历所有选项获取class有selected的li元素,通过activate方法标示为当前已选中的元素。 Where there is a need to compute, it is every time a drop-down list will have selected elements scroll to page visual area. As possible down list content are many, but the outer layer of the select drop-down list - the list will be one of the biggest height, the maximum height of the scroll bar will appear, the default do not calculate would likely has selected elements under the scroll bar or the scroll bar, so I need to reset the container to the position of the scroll bar by calculation. Specific content is selected according to the top of the scroll bar or the following whether need according to the selected elements offsetTop values greater than the outer container, the select - half the actual height of the list to display selected elements into the visual area is inView method. InView as follows

    inView: function (elem, wrapper, dir) {
    var scrollTop=wrapper. ScrollTop,
    //selected elements offsetTop
    offsetTop=elem. OffsetTop,
    top;

    if (dir==='up') {
    if (offsetTop===0) {
    //scroll bar set-top
    wrapper. The scrollTop=offsetTop;
    } else if (offsetTop <scrollTop) {
    top=offsetTop - scrollTop
    //the scroll bar to scroll to top value
    this. ScrollInView (wrapper, top)
    }
    } else {
    var clientHeight=wrapper. ClientHeight;

    if (offsetTop + elem. OffsetHeight===wrapper. ScrollHeight) {
    wrapper. The scrollTop=wrapper. ScrollHeight - wrapper. ClientHeight
    } else if (offsetTop + elem. OffsetHeight >clientHeight + scrollTop) {
    top=(offsetTop + elem. OffsetHeight) - (scrollTop + clientHeight)
    this. ScrollInView (wrapper, top)
    }

    }}

    inView method need to decide is to scroll up and down scroll, scrollInView method code is very simple is the scrollTop outer container under the drop-down list to the specified value. Method to realize the following

    scrollInView: function (elem, top) {
    setTimeout (function () {
    elem. The scrollTop +=top
    }, 10)
    }

    this method on the setTimeout made a delay is added to the javascript execution queue, the drop-down list on the main solution is under IE8 scrollbar will eventually scroll to the top, and ignore the scrollTop of code sets (on the performance of it as the scrollTop Settings can also be effective, but in the end will reset the scroll bar to the top, don't know why IE8 will have this problem.) , can't already selected elements to the range of visual, other browsers don't have this problem.
    the implementation details about so much, the keyboard up and down key enter and closed drop-down list logic is very simple.

    the problem of how to make the div get focus in response to the keyboard keydown, keyup, keypress events, to Google (Google is bad in the very period, who can't let this is characteristic of za?) finally found need to find some information for div elements setting tabindex attribute, so that div elements get focus, in response to a user's operation. Because the browser by default double-click, or click too frequently will select the current area, in order to cancel the default action to the user a good experience needs to add an attribute unselectable div elements, but this property only applies to Internet explorer and other browsers can add a class name is unselectable to avoid this problem. Other issues are logical control, there are some position calculation, there is no longer said. Use the

    the first is hope that through jselect replacement element on the page template to hide or don't do any processing, by default jselect will get all the select page replacement, in turn, if do not want jselect replace the select element
    you need to add a custom attribute data - enabled="true". Of course add data - enabled="false" and do not have this custom attributes are jselect replacement. In the process of use for the page layout structure more complex also may have other questions, because I test page structure is very simple, so there may be no test.
    use jselect squid need to introduce the js, then introduce the jselect - 1.0, js, jselect - 1.0. The CSS file, you need to call in jselect place calls through the following ways to initialize jselect: squids. Swing. Jselect ();
    note: jselect source and demo can download through here.

    you might be interested in the article:

    • javascript code simulation effect of Ping Ping (Web)
    • select javascript simulation implementation code
    • javascript simulate the scroll bar code
    • javascript code simulation drop-down menu
    • javascript simulation scroll scroll effect script
    • javascript simulation in sleep (two way)


    This concludes the body part