The method of JavaScript simulating select,jselect to realize _javascript skill

Source: Internet
Author: User
Tags wrapper
Because the main browser is different to the SELECT element rendering, so the display in each browser is not the same, the most important is by default, the UI is too rough, even through the CSS to beautify can not achieve a very beautiful effect. This is intolerable for our UX-focused front-end developers. So when the project is not too busy, plan to write a simulation of the select control out. Next, we'll share with you the details of the implementation, the problems encountered, and how to use them.
1. Implementation Details
Init:function (context) {
Gets all SELECT elements in the specified context
var elems = squid.getelementsbytagname (' select ', context)
This.globalevent ()
This.initview (Elems)
}
In a user-registered application scenario, there are multiple select elements. The emulated Select Control (hereinafter referred to as Jselect) initialization method takes all the SELECT elements on the page and then binds the global event globalevent to initialize the page to display the Initview. The Globalevent method is as follows:
Copy Code code as follows:

Globalevent:function () {
Document adds the Click event, the user processes each Jselect element to expand the shutdown
var target,
ClassName,
Elem
Wrapper,
Status
That's = 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 right mouse button triggers click event
Click to execute the left mouse button
if (Event.button = = 0) {
Initialize the selected 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 the document binding click event and then triggers the Click event on the page to determine whether the current click element is the target element that needs to be processed, judging by the element class, The branches of the statement in the code are: Expand the currently clicked Jselect element Drop-down, select the Click List item, and determine if you want to close the jselect.

The Initview method is as follows:
Copy Code code as follows:

Initview:function (Elems) {
var i = 0,
Elem
Length = Elems.length,
Enabled

for (; i < length; i++) {
Elem = Elems[i]
Enabled = Elem.getattribute (' data-enabled ')
Using System Select
if (!enabled | | enabled = = = ' true ')
Continue
if (squid.isvisible (Elem))
Elem.style.display = ' None '

This.create (Elem)
}
}

Initview implements a SELECT element that will need to be replaced with jselect to hide and then call the Create method, generating a single jselect structure and inserting it into the page and substituting the default select location.

The Create method is as follows:
Copy Code code 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 < length; 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 = ' <ul class= ' select-item ' > ' + lis + ' </ul> '
//
div = document.createelement (' div ')
Div.style.display = ' None '
Div.classname = ' Select-wrapper '
Selected elements
_default = document.createelement (' div ')
_default.classname = ' Select-default unselectable '
_default.unselectable = ' on '
Allow DIV elements to get focus
_default.setattribute (' TabIndex ', ' 1 ')
_default.setattribute (' Data-value ', SelectedValue)
_default.setattribute (' Hidefocus ', true)
_default.innerhtml = SelectedText
Div.appendchild (_default)
Select icon
icon = document.createelement (' span ')
Icon.classname = ' Select-icon '
Div.appendchild (Icon)
Drop down list
wrapper = document.createelement (' div ')
Wrapper.classname = ' select-list hide '
Wrapper.innerhtml = ul
To generate a new element
Div.appendchild (wrapper)
Insert behind a SELECT element
Elem.parentNode.insertBefore (Div, null)
Get the Select element left top value
Set Select to display, finish left and top value and then hide again
Elem.style.display = ' block '
Event Bindings
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 a copy of the system Select data to the Jselect Drop-down list, and the Jselect hierarchical relationship is the outermost element that has a class for Select-wrapper, It has class-select-default elements for the selected element, and class for Select-icon element users tell the user that this is a drop-down list, Class for Select-list div element contains a UL element inside is the text and value of the option text from the system select Copy stored in the LI element's textual and Data-value attributes. The Sysevent method is to add click Expansion for Jselect to turn off the Drop-down list event and the keyboard to select Drop-down element return to select the Drop-down element event. The Squid.position method is used to get the position of the system select element relative to its offsetparent, which is different from obtaining the offset of the system select element. The fact is to get their own offset to get the Top,left value and then subtract the top,left value of the offset offsetparent get. Finally, the jselect is inserted behind the system select element to display to the page.

Jselect created the basic process is described above, the rest is the details of the implementation of the place, such as: Click to expand Drop-down Display last selected elements, the specific implementation of the function is the Initselected method as follows
Copy Code code as follows:

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) {
Show selected elements
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
}
}
}

The method receives the class-Select-default div element, which is used to hold the elements of the user's chosen content, by traversing all the options to get the LI element with selected class, which is marked as the currently selected element by the Activate method. Here's a place to calculate, which is to scroll the selected elements to the page's viewable area each time you expand the Drop-down list. Because it's possible to get down a list of content, however, the outer select-list of the Drop-down list will have a maximum height, exceeding the maximum height will appear scroll bar, the default does not do the calculation of the element may be selected under the scroll bar or scroll bar, so you need to calculate to reset the container scroll bar position. Whether the selected element is displayed on top of the scroll bar or below is the InView method for displaying the selected elements to the viewable area based on the offsettop value of the selected element is more than half the actual height of the outer container select-list. The InView method is as follows
Copy Code code as follows:

Inview:function (Elem, Wrapper, dir) {
var scrolltop = Wrapper.scrolltop,
Element offsettop is selected
offsettop = Elem.offsettop,
Top

if (dir = = = ' Up ') {
if (offsettop = = 0) {
scroll bar Top
Wrapper.scrolltop = offsettop;
}else if (offsettop < scrolltop) {
top = Offsettop-scrolltop
scroll bar to 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 decide whether to scroll up or down, Scrollinview the method code is simply to set the scrolltop of the outer container of the Drop-down list to the specified value. method is implemented as follows
Copy Code code as follows:

Scrollinview:function (Elem, top) {
settimeout (function () {
Elem.scrolltop + + Top
}, 10)
}

The implementation of this method has been put into the settimeout with a delay added to the JavaScript execution queue, mainly to solve the IE8 under the expand Drop-down List scroll bar will eventually scroll to the top, Ignoring the scrolltop of the Code settings (as if the settings for the scrolltop will take effect, but will eventually reset the scroll bar to the top, and I don't know why IE8 has this problem.) , you cannot display the selected elements to the viewable area, which is not a problem in other browsers.
The whole implementation details are roughly the same, the keyboard keys to enter the key, and the logic to close the Drop-down list is simple.
problems encountered
How to get the focus of the div to respond to the keyboard KeyDown, KeyUp, KeyPress events, to Google (very time Google is not used, no way who let this is our characteristics) to find some data finally found that you need to set the TabIndex attribute for the DIV element, This allows the DIV element to gain focus in response to the user's actions. Because the browser by default double-click or is clicked too frequently will select the current area, in order to cancel this default action to give the user a good experience need to add a property for the DIV element unselectable, but this property can only apply to IE browser, Other browsers can avoid this problem by adding a class name to the unselectable. All the other questions are logically controlled, and there are some positions to be counted, and this is no longer said.
How to use
The first is to hide or not do any of the elements that you want to replace by Jselect in the page template, by default jselect will get all of the page's select substitutions, if you do not want the jselect to replace the SELECT element
You need to add a custom attribute data-enabled= "true". Of course, adding data-enabled= "false" and not having this custom attribute will be replaced by Jselect. There may be other problems with a page with a more complex layout, because the structure of my test page is very simple, so it may not be tested.
Using Jselect, you need to introduce squid.js and then introduce Jselect-1.0.js, JSELECT-1.0.CSS file to initialize the Jselect:squid.swing.jselect () in the place where the jselect is needed to invoke the following method;
Note: Jselect source and demo can be downloaded through here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.