


Since mainstream browsers render select elements differently, the display in each browser is also different. The most important thing is that the UI is too rough by default, and even if it is beautified through CSS, it cannot achieve a very beautiful effect. This is intolerable to us front-end developers who focus on UX. So when the project is not too busy, I plan to write a simulated select control. Next, I will share with you the implementation details, problems encountered and how to use it.
1. Implementation details
init: function(context) {
//Get all select elements of the specified context
var elems = squid.getElementsByTagName('select', context)
this.globalEvent()
this.initView(elems)
}
In a user registration application scenario, there are multiple select elements. The simulated select control (hereinafter referred to as jselect) initialization method will obtain all select elements on the page, then bind the global event globalEvent, and initialize the page to display initView. The globalEvent method is as follows:
globalEvent: function() {
//Document adds a click event, and the user handles the expansion and closing of each jselect element
var target,
className,
elem,
wrapper,
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 The right mouse button will trigger the click event
//The left mouse button clicks to execute
if(event.button === 0) {
//Initialization selection Element
that.initSelected(elem)
if(squid.isHidden(wrapper)) {
status = 'block'
//Close all expanded 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 implements binding the click event on the document, and then uses the event proxy to determine whether the currently clicked element is the target element that needs to be processed when the click event is triggered on the page. The judgment condition is based on the class of the element. The branches of the statements in the code are: expand the currently clicked jselect element drop-down, select the clicked list item, and determine whether jselect needs to be closed.
The initView method is as follows:
initView: function(elems) {
var i = 0,
elem,
length = elems.length,
enabled;
for(; i elem = elems[i]
enabled = elem.getAttribute('data-enabled')
//Use system select
if(!enabled || enabled === 'true')
continue
if(squid.isVisible(elem))
elem.style.display = 'none'
this.create(elem)
}
}
initView implements the method of hiding the select elements that need to be replaced with jselect and then calling the create method to generate the overall structure of a single jselect and insert it into the page and replace the default select position.
The create method is as follows:
create: function(elem) {
var data = [],
i = 0,
length,
option,
options,
value,
text,
obj,
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 = option.value
text = option.innerText || option.textContent
obj = {
value: value,
text: text
}
if(option.selected) {
selectedValue = value
selectedText = text
obj['selected'] = true
}
data.push(obj)
}
lis = this.render(this.tmpl, data)
ul = '
- ' lis '
//
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
}
create方法实现了将系统select数据拷贝到jselect下拉列表,jselect的层级关系是最外层有一个class为select-wrapper的元素包裹,里面有class为select-default的元素用于存放已选的元素,class为select-icon的元素用户告诉用户这是一个下拉列表,class为select-list的div元素里面包含了一个ul元素里面是从系统select拷贝的option的文本和值分别存放在li元素的文本和data-value属性。sysEvent方法是为jselect添加点击展开关闭下拉列表事件以及键盘上下选择下拉元素回车选中下拉元素事件。squid.position方法用于获取系统select元素相对于其offsetParent的位置,这里与获取系统select元素的offset是有区别。其实就是获取自己的offset得到top,left值然后分别减去offsetParent获取的offset的top,left值。最后是把jselect插入到系统select元素后面,显示到页面。
jselect创建的基本流程就是上面描述的这样,剩下就是细节地方的实现,比如说:点击展开下拉显示上次已选择的元素,具体实现该功能的是initSelected方法如下
initSelected: function(elem) {
var curText = elem.innerText || elem.textContent,
curValue = elem.getAttribute('data-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 = n.getAttribute('data-value')
if(curText === text && curValue === 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
}
}
}
This method receives the div element with class select-default, which is used to store the content that the user has selected. The specific implementation method is to first traverse all options to obtain the li element with class selected, and mark it as currently selected through the activate method. element. There is something that needs to be calculated here, that is, each time the drop-down list is expanded, the selected element must be scrolled to the visible area of the page. Because there may be a lot of content in the drop-down list, but the outer select-list of the drop-down list will have a maximum height. If the maximum height is exceeded, a scroll bar will appear. If the calculation is not performed by default, the selected element may be under the scroll bar or under the scroll bar. above the scroll bar, so calculations are needed to reset the position of the container scroll bar. Specifically, whether the selected content is displayed above or below the scroll bar depends on whether the offsetTop value of the selected element is greater than half the actual height of the outer container select-list. The way to display the selected element into the visual area is the inView method. The inView method is as follows
inView: function(elem, wrapper, dir ) {
var scrollTop = wrapper.scrollTop,
//Selected element offsetTop
offsetTop = elem.offsetTop,
top;
if(dir === 'up' ) {
if(offsetTop === 0) {
//Scroll bar to top
wrapper.scrollTop = offsetTop;
}else if(offsetTop top = offsetTop - scrollTop
//The scroll bar scrolls to the top value
this.scrollInView(wrapper, top)
}
}else{
var clientHeight = wrapper.clientHeight;
if(offsetTop elem.offsetHeight === wrapper.scrollHeight) {
wrapper.scrollTop = wrapper.scrollHeight - wrapper.clientHeight
}else if(offsetTop elem.offsetHeight > clientHeight scrollTop) {
top = (offsetTop elem.offsetHeight) - (scrollTop clientHeight)
this.scrollInView(wrapper, top)
}
}
}
The inView method needs to determine whether to scroll up Still scrolling down, the scrollInView method code is simply to set the scrollTop of the outer container of the drop-down list to the specified value. The method is implemented as follows
scrollInView: function(elem, top) {
setTimeout(function() {
elem.scrollTop = top
}, 10)
}
This method is implemented in setTimeout and a delay is added to In the javascript execution queue, the main problem is that the scroll bar of the expanded drop-down list under IE8 will eventually scroll to the top, ignoring the scrollTop set by the code (from the performance point of view, it seems that the setting of scrollTop can also take effect, but in the end the scroll bar will be reset to the top , I don’t know why IE8 has this problem.) The selected element cannot be displayed within the visual area. This problem does not occur in other browsers.
The entire implementation details are roughly this much. The logic of pressing the up and down keys on the keyboard and pressing the Enter key to close the drop-down list is very simple.
Problems encountered
How to let div get focus to respond to keyboard keydown, keyup, keypress events, to Google (Google is not easy to use in extraordinary times, there is no way who can let us Features) After searching some information, I finally found that I need to set the tabindex attribute for the div element, so that the div element can gain focus and respond to user operations. Because the browser will select the current area by double-clicking or clicking too frequently by default. In order to cancel this default operation and give users a good experience, you need to add an attribute unselectable to the div element. However, this attribute can only be applied to IE browsers. This problem can be avoided in other browsers by adding a class name that is unselectable. Other issues are logical control and some position calculations, which will not be discussed here.
How to use
First, hide the elements you want to replace with jselect in the page template or do no processing. By default, jselect will get all the selects on the page and replace them in sequence. If you don’t want jselect to replace them, The select element
needs to add the custom attribute data-enabled="true". Of course, adding data-enabled="false" will be replaced by jselect just like without this custom attribute. During use, there may be other problems with pages with more complex layout structures. Because the page structure I tested is very simple, I may not have tested it out.
To use jselect, you need to introduce squid.js first, and then import the jselect-1.0.js, jselect-1.0.css files. Where jselect needs to be called, initialize jselect through the following calling method: squid.swing.jselect();
Note: jselect source code and demo can be downloaded from here.

使用golang进行SelectChannelsGo并发式编程的异步处理方法引言:并发式编程是现代软件开发中的一个重要领域,它可以有效地提高应用程序的性能和响应能力。在Go语言中,使用Channels和Select语句可以简单而高效地实现并发编程。本文将介绍如何使用golang进行SelectChannelsGo并发式编程的异步处理方法,并提供具体的

jquery隐藏select元素的方法:1、hide()方法,在HTML页面中引入jQuery库,可以使用不同选择器来隐藏select元素,ID选择器将selectId替换为你实际使用的select元素的ID;2、css()方法,使用ID选择器选择需要隐藏的select元素,使用css()方法将display属性设置为none,并将selectId替换为select元素的ID。

jQuery是一个流行的JavaScript库,可以用来简化DOM操作、事件处理、动画效果等。在web开发中,经常会遇到需要对select元素进行改变事件绑定的情况。本文将介绍如何使用jQuery实现对select元素改变事件的绑定,并提供具体的代码示例。首先,我们需要使用标签来创建一个包含选项的下拉菜单:

因为select可以使开发者在同时等待多个文件缓冲区,可减少IO等待的时间,能够提高进程的IO效率。select()函数是IO多路复用的函数,允许程序监视多个文件描述符,等待所监视的一个或者多个文件描述符变为“准备好”的状态;所谓的”准备好“状态是指:文件描述符不再是阻塞状态,可以用于某类IO操作了,包括可读,可写,发生异常三种。select是一个计算机函数,位于头文件#include。该函数用于监视文件描述符的变化情况——读写或是异常。1.select函数介绍select函数是IO多路复用的函

1、SQL语句中的关键词对大小写不敏感,SELECT等效于SELECT,FROM等效于from。2、从users表中选择所有列的,可以用符号*代替列的名称。语法--这是注释--从FEOM指定的[表中],查询出[所有的]数据.*表示[所有列]SELECT*FROM--通过从FROM从指定的[表中],查询出指定列名称(字段)的数据SELECT列名称FROM表名称实例--注意:多个列之间,使用英文的逗号来分隔selectusername,passwordfrom

通过golang实现SelectChannelsGo并发式编程的性能优化在Go语言中,使用goroutine和channel实现并发编程是非常常见的。而在处理多个channel的情况下,我们通常会使用select语句来进行多路复用。但是,在大规模并发的情况下,使用select语句可能会导致性能下降。在本文中,我们将介绍一些通过golang实现select

使用Golang实现可靠性和鲁棒性的SelectChannelsGo并发式编程引言:在现代软件开发中,并发性已经成为了一个非常重要的主题。使用并发编程可以使得程序更具有响应性、更高效地利用计算资源,并且能够更好地处理大规模的并行计算任务。Golang是一种非常强大的并发编程语言,它通过go协程和channel机制,提供了一种简单而有效的方式来实现并发编程

select语句可以用回车分隔$sql="select*fromarticlewhereid=1"和$sql="select*fromarticlewhereid=1"都可以得到正确的结果,但有时分开写或许能更明了一点,特别是当sql语句比较长时。批量查询数据可以用in来实现$sql="select*fromarticlewhereid;in(1,3,5)"使用concat连接查询的结果$sql="selectconcat(i


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

SublimeText3 Mac version
God-level code editing software (SublimeText3)

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Dreamweaver CS6
Visual web development tools

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software
