layui.define(['laypage', 'form'], function (exports) { "use strict"; // 工具 const util = { // 检测类型 type: obj => Object.prototype.toString.call( obj ).slice( 8, -1 ).toLowerCase(), // 检测是否为不为空的纯对象 isNotEmptyPlainObject: obj => !!( util.type( obj ) === "object" && Object.keys( obj ).length ), // 检测是否为大于或等于零的安全整数 isCorrectNumber: ( obj, zero ) => !!( Number.isSafeInteger( obj ) && ( !zero ? obj > 0 : obj >= 0 ) ), // 检测是否为函数 isFunction: obj => util.type( obj ) === "function", // 检测是否为 Promise isPromise: obj => util.type( obj ) === "promise", // 创建唯一标识符 uid ( useSymbol ) { const random = Math.random().toString( 36 ).slice( 2, 10 ); return useSymbol ? Symbol( random ) : random; }, // 定时器 delay ( delay = 0 ) { return new Promise( resolve => { let timer = window.setTimeout( () => { window.clearTimeout( timer ); timer = null; resolve(); }, delay ) } ) }, // 合并参数 mergeParam ( params = {}, defaultParams ) { const result = {}; for ( const key in defaultParams ) { const v = params[ key ]; if ( util.type( v ) === "object" ) { result[ key ] = util.mergeParam( v, defaultParams[ key ] ); } else { result[ key ] = v === 0 ? v : ( v || defaultParams[ key ] ); } } return result; } }; // DOM 系统 const $ = ( () => { function buildDom ( domArray ) { const length = domArray[ 0 ] ? domArray.length : 0; this.length = length; for ( let i = 0; i < length; i++ ) { this[ i ] = domArray[ i ]; } return this; } buildDom.prototype = { each ( callback ) { for ( let i = 0, j = this.length; i < j; i++ ) { callback.call( this[ i ], i, this[ i ] ); } return this; }, get ( index = 0 ) { return this[ index ]; }, click ( callback ) { return this.each( function () { this.addEventListener( "click", function ( event ) { callback.call( this, event ); } ) } ) }, hasClass ( className ) { return this[ 0 ].classList.contains( className ); }, addClass ( className ) { return this.each( function () { for ( const name of className.split( " " ) ) { this.classList.add( name ); } } ) }, removeClass ( className ) { return this.each( function () { for ( const name of className.split( " " ) ) { this.classList.remove( name ); } } ) }, toggleClass ( className ) { return this.each( function () { for ( const name of className.split( " " ) ) { this.classList.toggle( name ); } } ) }, css ( name, value ) { function getStyle ( elem, prop ) { return document.defaultView.getComputedStyle( elem, null ).getPropertyValue( prop ); } function setStyle ( el, _name, _value ) { el.style[ _name ] = _value; } return ( typeof name === "string" && !value ) ? getStyle( this[ 0 ], name ) : this.each( function () { if ( name && value ) { setStyle( this, name, value ); } if ( util.isNotEmptyPlainObject( name ) && !value ) { for ( const key in name ) { setStyle( this, key, name[ key ] ); } } } ) }, html ( html ) { return this.each( function () { this.innerHTML = html; } ) }, text () { return this[ 0 ].textContent; }, val ( val ) { return this.each( function () { this.value = val; } ) }, eq ( index ) { if ( typeof index === "number" ) { const eqArr = []; if ( index < this.length ) { eqArr.push( this[ index ] ); } return $( eqArr ); } }, index () { if ( this[ 0 ] ) { let child = this[ 0 ]; let i = 0; while ( ( child = child.previousSibling ) !== null ) { child.nodeType === 1 && i++; } return i; } }, prev () { const prevArr = []; this.each( function () { const p = this.previousElementSibling; p && prevArr.push( p ); } ) return $( prevArr ); }, next () { const nextArr = []; this.each( function () { const n = this.nextElementSibling; n && nextArr.push( n ); } ) return $( nextArr ); }, nextAll () { const nextAll = []; this.each( function () { let next = this.nextElementSibling; function findNext () { if ( next ) { nextAll.push( next ); next = $( next ).get().nextElementSibling; findNext(); } } findNext(); } ); return $( nextAll ); }, parent () { const parentArr = []; this.each( function () { parentArr.push( this.parentNode ); } ) return $( parentArr ); }, find ( dom ) { const findArr = []; this.each( function () { const node = this.querySelectorAll( dom ); for ( let i = 0, j = node.length; i < j; i++ ) { ( node[ i ].nodeType === 1 ) && findArr.push( node[ i ] ); } } ) return $( findArr ); }, siblings: function () { const sibling = []; this.each( function () { const child = this.parentNode.children; for ( let i = 0, j = child.length; i < j; i++ ) { if ( child[ i ] !== this ) { sibling.push( child[ i ] ); } } } ); return $( sibling ); }, add ( elem ) { let dom = this; const addElem = $( elem ); for ( let i = 0, j = addElem.length; i < j; i++ ) { dom[ dom.length ] = addElem[ i ]; dom.length++; } return dom; }, data ( name, value ) { return ( typeof name === "string" && !value ) ? this[ 0 ].dataset[ name ] : this.each( function () { if ( name && value ) { this.dataset[ name ] = value; } else { for ( const key in name ) { this.dataset[ key ] = name[ key ]; } } } ) }, remove () { return this.each( function () { this.parentNode && this.parentNode.removeChild( this ); } ) }, show () { return this.each( function () { this.style.display = "block"; } ) }, hide () { return this.each( function () { this.style.display = ""; if ( $( this ).css( "display" ) !== "none" ) { this.style.display = "none"; } } ) } }; return function ( selector ) { let result = []; if ( typeof selector === "string" ) { result = document.querySelectorAll( selector ); } if ( selector.nodeType || selector === document ) { result.push( selector ); } else if ( selector.length > 0 && selector[ 0 ] && selector[ 0 ].nodeType ) { for ( let i = 0, j = selector.length; i < j; i++ ) { result.push( selector[ i ] ); } } return new buildDom( result ); } } )(); // 默认配置 const defaults = { theme: "select", data: { props: { code: "code", name: "name" }, source: null, when: null }, level: 6, radius: 2, width: 200, height: 34, maxHeight: 300, disabled: [], disabledItem: [], tips:'请选择', selected: [], selectedCallback: () => {}, placeholder: [ "省", "市", "区" ], placeholder1: [ "省份", "城市", "区县" ], separator: "/", clearable: false, strict: false, onlyShowLastLevel: false, icon: "arrow", onClear: () => {}, onSelect: () => {} }; // 存储组件数据 const cacheIPicker = { // 原始目标元素 >> elem: "..." originalElem: new WeakMap(), // 组件配置信息 >> elem: opt options: new WeakMap(), // 组件选中结果 >> elem: [ [], [], [] ] value: new WeakMap(), // 组件唯一标识 >> elem: uid id: new WeakMap(), // 组件目标信息 >> uid: elem target: new Map() }; // 缓存数据源 const cacheCustomData = new Map(); // 样式 id const styleId = "iPicker-default-style"; // 功能模块 const modules = { createFrame ( $target, { placeholder1,theme, level, icon, clearable }, uid ) { let frame = `
${ clearable ? "" : "" }
___
`; switch ( theme ) { case "select": frame = frame.replace( "___", "" ).repeat( level ); break; case "cascader": frame = frame.replace( "___", "".repeat( level ) ); break; case "panel": frame = frame.replace( "___", `
${placeholder1[0]}
${ level > 1 ? "
"+placeholder1[1]+"
" : "" } ${ level > 2 ? "
"+placeholder1[2]+"
" : "" } ${ level > 3 ? "
"+placeholder1[3]+"
" : "" } ${ level > 4 ? "
"+placeholder1[4]+"
" : "" } ${ level > 5 ? "
"+placeholder1[5]+"
" : "" } ${ level > 6 ? "
"+placeholder1[6]+"
" : "" }
${ "".repeat( level ) }
` ); break; } $target.addClass( "iPicker-target" ).html( frame ).data( { theme: theme, id: uid.toString().replace( /(\(|\))/g, "" ) } ); }, createList ( data, opt, isInnerData,nowlevel) { return new Promise( resolve => { let list = ""; const isCascader = opt.theme === "cascader"; if ( !isInnerData ) { const { code, name } = opt.data.props || {}; data.forEach( obj => { list += `
  • ${ obj[ name ] } ${ ( isCascader ? "" : "" ) }
  • `; } ) } else { for ( const key in data ) { list += `
  • ${ data[ key ] } ${ ( isCascader ? "" : "" ) }
  • `; } } resolve( list ); } ) }, getData ( code, level, opt, isInnerData ) { // 优先使用本地缓存的数据源 return new Promise( resolve => { // 通过 opt.data.when 函数可对数据进行一次最后的处理 function when ( data, level ) { if ( util.isFunction( opt.data.when ) ) { return opt.data.when( data, level ); } else { return data; } } // 自定义数据源 if ( !isInnerData ) { const hasCache = cacheCustomData.get( code ); if ( hasCache ) { resolve( when( hasCache, level ) ); } else { const dataSource = opt.data.source( code, level ); if ( util.type( dataSource ) === "object" && util.isFunction( dataSource.then ) ) { dataSource.then( res => { cacheCustomData.set( code, res ); resolve( when( res, level ) ); } ) } } } else { // 内置数据源 opt.data.source.then( res => { resolve( when( res[ code ], level ) ); } ) } } ) }, getSelected ( $target ) { // 根据被选中列表含有 "特征类" 来获取选中项 const $active = $target.find( ".iPicker-list-active" ); const activeSize = $active.length; const [ code, name, map ] = [ [], [], [] ]; if ( activeSize ) { $active.each( function () { const dataCode = $( this ).data( "code" ); const dataName = $( this ).data( "name" ); code.push( dataCode ); name.push( dataName ); map.push( { code: dataCode, name: dataName } ); } ) } return [ code, name, map ]; }, cacheSelected ( target, value ) { cacheIPicker.value.set( target, value ); } }; // 核心程序 const iPicker = ( target, options ) => { // 对必选参数进行校验 if ( !target || !options || typeof target !== "string" || !target.trim() || !util.isNotEmptyPlainObject( options ) || !util.isNotEmptyPlainObject( options.data ) || !options.data.source || ( !util.isFunction( options.data.source ) && !util.isPromise( options.data.source ) ) ) { return; } const $target = $( target ); const _target = $target.get(); if ( !_target ) { return; } // 合并参数 const opt = util.mergeParam( options, defaults ); // 检验并处理 level if ( !util.isCorrectNumber( opt.level ) || opt.level < 1 || opt.level > 6 ) { opt.level = 6; } // 缓存主题类型 const selectTheme = opt.theme === "select"; const cascaderTheme = opt.theme === "cascader"; const panelTheme = opt.theme === "panel"; // 缓存数据源类型 const isInnerData = util.isPromise( opt.data.source ); // 检测 onClear 和 onSelect 是否为函数 const onClearIsFunc = util.isFunction( opt.onClear ); const onSelectIsFunc = util.isFunction( opt.onSelect ); // 创建一个全局唯一标识符 const uid = _target.iPickerID || util.uid( true ); const panelwidth= opt.width; // 存储 cacheIPicker.originalElem.set( _target, target ); cacheIPicker.options.set( _target, opt ); cacheIPicker.target.set( uid, _target ); cacheIPicker.id.set( _target, uid ); _target.iPickerID = uid; // 添加样式 if ( !document.getElementById( styleId ) ) { document.head.insertAdjacentHTML( "afterbegin", ` ` ); } // 生成组件结构 modules.createFrame( $target, opt, uid ); // 缓存 dom const $container = $target.find( ".iPicker-container" ); const $result = $target.find( ".iPicker-result" ); const $input = $target.find( ".iPicker-input" ); const $list = $target.find( ".iPicker-list" ); const $ul = $list.find( "ul" ); // 添加索引标记 $ul.each( function ( i ) { $( this ).data( "level", ++i ); } ) // 设置列表最大高度 // 最小有效值是 100,如果设置了小于 100 的值则按照默认配置进行处理 if ( util.isCorrectNumber( opt.maxHeight ) && opt.maxHeight >= 100 ) { $list.css( "maxHeight", `${ opt.maxHeight }px` ); if ( cascaderTheme ) { $ul.css( "maxHeight", `${ opt.maxHeight }px` ); } if ( panelTheme ) { $list.find( ".iPicker-panel-content" ).css( "height", `${ opt.maxHeight - 38 }px` ); } } // 设置结果展示框宽度 // 当宽度是数字时最小有效值是 100,如果设置了小于 100 的值则按照默认配置进行处理 // 当宽度是字符串时必须是百分比形式 if ( util.isCorrectNumber( opt.width ) && opt.width >= 100 ) { $result.css( "width", `${ opt.width }px` ); if ( selectTheme ) { $list.css( "width", `${ opt.width }px` ); } } if ( typeof opt.width === "string" && opt.width.trim().endsWith( "%" ) ) { $result.css( "width", opt.width ); if ( selectTheme ) { $list.css( "width", opt.width ); } else { $container.css( "width", opt.width ); } } // 设置结果展示框高度 // 最小有效值是 20,如果设置了小于 20 的值则按照默认配置进行处理 if ( util.isCorrectNumber( opt.height ) && opt.height >= 20 ) { $result.css( "height", `${ opt.height }px` ); $input.css( "height", `${ opt.height - 2 }px` ); $input.next().css( "height", `${ opt.height - 2 }px` ); } // 禁用指定地区 if ( opt.disabledItem === true ) { new MutationObserver( () => { $target.find( "li" ).addClass( "iPicker-list-disabled" ); } ).observe( _target, { childList: true, subtree: true } ) } if ( Array.isArray( opt.disabledItem ) && opt.disabledItem.length ) { for ( const code of [ ...new Set( opt.disabledItem ) ] ) { new MutationObserver( () => { const li = _target.querySelector( `[data-code="${ code }"]:not(.iPicker-list-disabled)` ); if ( li ) { li.classList.add( "iPicker-list-disabled" ); } } ).observe( _target, { childList: true, subtree: true } ) } } // 禁用指定的结果展示框 if ( opt.disabled === true ) { opt.disabled = [ 1, 2, 3, 4 ].slice( 0, opt.level ); } if ( util.isCorrectNumber( opt.disabled ) ) { opt.disabled = [ opt.disabled ]; } if ( Array.isArray( opt.disabled ) && opt.disabled.length ) { for ( const level of [ ...new Set( opt.disabled ) ] ) { if ( util.isCorrectNumber( level ) && level >= 1 && level <= 6 ) { $result.eq( level - 1 ).addClass( "iPicker-disabled" ); } } } // 设置 placeholder if ( selectTheme && Array.isArray( opt.placeholder ) ) { opt.placeholder.forEach( ( v, i ) => { const input = $input.eq( i ).get(); if ( input ) { input.setAttribute( "placeholder", opt.placeholder[ i ] || defaults.placeholder[ i ] ); } } ) } if ( cascaderTheme || panelTheme ) { if ( typeof opt.placeholder !== "string" || !opt.placeholder.trim() ) { opt.placeholder = "请选择地区"; } $input.eq( 0 ).get().setAttribute( "placeholder", opt.tips ); } // 设置结果展示框的圆角值 if ( util.isCorrectNumber( opt.radius, true ) ) { $result.add( $input ).css( "borderRadius", `${ opt.radius }px` ); } // 设置清空按钮 $result.find( ".clear-icon" ).hide(); $result.each( function () { // 鼠标滑入滑出显示或隐藏清空按钮 const el = $( this ).get(); el.addEventListener( "mouseenter", () => { const input = el.querySelector( "input" ); if ( input ) { if ( input.value && !el.classList.contains( "iPicker-disabled" ) ) { $( this ).find( ".clear-icon" ).show().prev().hide(); } } } ) el.addEventListener( "mouseleave", () => { $( this ).find( ".clear-icon" ).hide().prev().show(); } ) } ) const $clear = $target.find( ".clear-icon" ); if ( !selectTheme ) { $clear.click( () => { $clear.hide().prev().show(); iPicker.clear( uid ); if ( onClearIsFunc ) { opt.onClear(); } } ) } else { $clear.each( function () { const $this = $( this ); $this.click( function () { $this.hide().prev().show(); const $parent = $this.parent(); const $ul = $parent.next().find( "ul" ); const index = +$ul.data( "index" ); $parent.find( "input" ).val( "" ); $ul.find( ".iPicker-list-active" ).removeClass( "iPicker-list-active" ); $parent .parent() .nextAll() .find( "input" ) .val( "" ) .parent() .next() .find( "ul" ) .html( "" ); getCacheShow(); closeList( $parent.next() ); if ( onClearIsFunc ) { opt.onClear(); } } ) } ) } // 通过点击展示框来展开或关闭列表 $result.each( function () { $( this ).find( "input, .arrow-icon" ).click( function () { const $this = $( this ).parent(); const $next = $this.next(); const id = $this.parent().parent().data( "id" ); // 关闭其它列表 const $otherList = $( `.iPicker-target:not([data-id="${ id }"]) .iPicker-list` ); if ( $otherList.length ) { closeList( $otherList ); } // 组件必须在 "启用" 状态下才有效 if ( !$this.hasClass( "iPicker-disabled" ) ) { // 列表中必须有数据 if ( !$next.find( "li" ).length ) { return; } $this.toggleClass( "iPicker-result-active" ); if ( $next.hasClass( "iPicker-list-show" ) ) { closeList( $next ); } else { if ( panelTheme ) { $target .find( ".iPicker-panel-tab > div:first-child" ) .addClass( "iPicker-panel-tab-active" ) .siblings() .removeClass( "iPicker-panel-tab-active" ); $target.find( ".iPicker-panel-content > ul:first-child" ).show().siblings().hide(); } /* # 自动检测展示框的位置 # 实时调整下拉列表的位置 */ let flag = false; const resultHeight = parseInt( $this.css( "height" ) ); const positionListener = () => { if ( flag ) { return; } flag = true; $next.addClass( "iPicker-list-show-temporary" ); const bottom = document.documentElement.clientHeight - $this.get().getBoundingClientRect().bottom; const height = parseInt( $next.css( "height" ) ); if ( bottom < height ) { $next.css( "marginTop", `-${ height + resultHeight }px` ).addClass( "iPicker-list-ontop" ); } else { $next.css( "marginTop", "0px" ).removeClass( "iPicker-list-ontop" ); } flag = false; $next.removeClass( "iPicker-list-show-temporary" ); } positionListener(); window.addEventListener( "scroll", positionListener ); window.addEventListener( "resize", positionListener ); $next.addClass( "iPicker-list-show" ).removeClass( "iPicker-list-hide" ); } } } ) } ) // 关闭列表函数 function closeList ( $list ) { if ( $list.hasClass( "iPicker-list-show" ) ) { $list .addClass( "iPicker-list-hide" ) .removeClass( "iPicker-list-show" ) .prev() .removeClass( "iPicker-result-active" ); $list.show(); util.delay( 200 ).then( () => { $list.get().style.removeProperty( "display" ); } ) if ( !selectTheme ) { getCacheShow(); } // 检测 strict 模式 const $target = $list.parent().parent(); const opt = cacheIPicker.options.get( $target.get() ); if ( opt.strict ) { // 利用定时器进行延时处理 // 在列表关闭动画结束后执行相关程序 util.delay( 200 ).then( () => { const [ code ] = cacheIPicker.value.get( $target.get() ); const codeLen = code.length; // 只有在至少选择了一个层级 // 但又没有完整选择全部指定的层级的情况下 // 才能执行后续程序 if ( codeLen && codeLen !== opt.level ) { new Promise( resolve => { if ( codeLen === 1 ) { if ( opt.level <= 6 ) { resolve(); } else { addList( $ul.eq( 1 ).find( "li:first-child" ).data( "code" ), 6 ).then( () => { resolve(); } ); } } else { resolve(); } } ).then( () => { $ul.each( function () { if ( !$( this ).find( ".iPicker-list-active" ).length ) { $( this ).find( "li:first-child" ).addClass( "iPicker-list-active" ); } } ) getCacheShow(); } ) } } ) } } } // 添加列表 function addList ( code, level ) { return new Promise( resolve => { modules.getData( code, !selectTheme ? level : level > 6 ? 6 : level, opt, isInnerData ).then( res => { modules.createList( res, opt, isInnerData,level ).then( content => { const $targetUL = $ul.eq( level - 1 ); $targetUL.html( content ).nextAll().html( "" ); if ( selectTheme ) { $targetUL.parent().parent().nextAll().find( "ul" ).html( "" ); } if ( cascaderTheme ) { let size = 0; $ul.each( function () { if ( this.innerHTML ) { size++; } } ) $list.css( "width", `${ 200 * size }px` ); $ul.eq( level - 1 ).show().nextAll().hide(); } if ( panelTheme ) { $ul.eq( level - 1 ).show().siblings().hide(); $target .find( `.iPicker-panel-tab > div:nth-child(${ level })` ) .addClass( "iPicker-panel-tab-active" ) .siblings() .removeClass( "iPicker-panel-tab-active" ); } selectTheme ? getCacheShow() : level <= opt.level && getCacheShow(); resolve(); } ); } ) } ) } // 获取,存储,显示结果 function getCacheShow () { util.delay( 10 ).then( () => { // 获取并存储选中结果 const getSelected = modules.getSelected( $target ); modules.cacheSelected( _target, getSelected ); // 显示选中结果 const separator = opt.separator.trim().charAt( 0 ); function showResult ( result ) { if ( result ) { if ( cascaderTheme || panelTheme ) { if ( opt.onlyShowLastLevel ) { result = result.split( separator ).slice( -1 )[ 0 ].trim(); } } } return result; } // 显示选中结果 if ( selectTheme ) { getSelected[ 1 ].forEach( ( item, index ) => { $input.eq( index ).val( showResult( item ) ); } ) } else { const name = getSelected[ 1 ].join( ` ${ separator } ` ); $input.eq( 0 ).val( showResult( name ) ); } // 执行 onSelect 事件 if ( onSelectIsFunc ) { if ( getSelected[ 1 ].length ) { opt.onSelect( ...cacheIPicker.value.get( _target ) ); } } } ) } // 自动获取第一层级的数据 // 含有对 "默认选中项" 的处理 addList( ( isInnerData ? "a86" : null ), 1 ).then( () => { _target.dataset.promise = "true"; // 设置默认选中项 // selected // 默认选中项中不能含有已被禁用的选项,即: // selected 数组中的值不能在 disabledItem 中也存在,否则无效 if ( Array.isArray( opt.selected ) && opt.selected.length ) { opt.selected = [ ...new Set( opt.selected ) ] for ( const code of opt.selected ) { if ( opt.disabledItem.includes( code ) ) { return; } } !( function selected ( i ) { addList( opt.selected[ i - 1 ], i + 1 ).then( () => { i++; if ( i < opt.level ) { selected( i ); } else { opt.selected.forEach( (item,index) => { //要考虑层级 $target.find( `li[data-code2="${(index+1)}_${ item }"]` ).addClass( "iPicker-list-active" ); // $target.find( `li[data-code="${ item }"]` ).addClass( "iPicker-list-active_"+(index+1)+"_"+item ); } ) getCacheShow(); // 执行 selectedCallback 函数 if ( util.isFunction( opt.selectedCallback ) ) { opt.selectedCallback(); } } } ) } )( 1 ); } } ); // 点击选择事件 $target.click( event => { if ( event.target.nodeName.toLowerCase() !== "li" ) { return; } const $li = $( event.target ); const $ul = $li.parent(); if ( $li.hasClass( "iPicker-list-disabled" ) ) { return; } $li.addClass( "iPicker-list-active" ).siblings().removeClass( "iPicker-list-active" ); addList( $li.data( "code" ), +$ul.data( "level" ) + 1 ); // select 主题下,点击选择后自动关闭列表 if ( selectTheme ) { closeList( $ul.parent() ); $ul.parent().parent().nextAll().find( ".iPicker-result input" ).val( "" ); } // cascader 和 panel 模式下,如果点击选择的是最后一级的数据 // 则自动关闭列表 if ( $ul.index() === opt.level - 1 ) { if ( cascaderTheme ) { closeList( $ul.parent() ); } if ( panelTheme ) { closeList( $ul.parent().parent() ); } } } ) // cascader 主题下需要强制设置高度 if ( cascaderTheme ) { $ul.css( { minHeight: `${ opt.maxHeight }px`, maxHeight: `${ opt.maxHeight }px` } ); } // panel 主题下的切换 if ( panelTheme ) { $target.find( ".iPicker-panel-tab > div" ).click( function () { const index = $( this ).index(); if ( !$( this ).parent().next().find( "ul" ).eq( index ).find( "li" ).length ) { return; } $( this ) .addClass( "iPicker-panel-tab-active" ) .siblings() .removeClass( "iPicker-panel-tab-active" ); $target .find( ".iPicker-panel-content ul" ) .eq( $( this ).index() ) .show() .siblings() .hide(); } ) } // 点击空白处隐藏列表 $( document ).click( function ( event ) { $container.each( function ( i ) { if ( event.target !== this && !this.contains( event.target ) ) { closeList( $list.eq( i ) ); } } ) } ) return uid; } // 创建组件 // 等同于 iPicker 函数 iPicker.create = ( target, options ) => iPicker( target, options ) // 设置值 // value: iPicker.set = ( id, value ) => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target || !value || !Array.isArray( value ) || !value.length ) { return; } // 清除已选项 iPicker.clear( id ); // 如果目标元素已经设置了 data-promise 属性 // 说明已经获取到了第一层级的数据 // 可直接执行 fn 函数 if ( _target.dataset.promise ) { fn(); } else { // 尚未获取到数据时 // 调用 MutationObserver 方法监听 data-promise 属性的变化 // 以此来判断是否已经获取到了第一层级的数据 // 当获取到数据时执行 fn 函数 new MutationObserver( () => { fn(); } ).observe( _target, { attributes: true } ); } function fn () { const ul = _target.querySelectorAll( "ul" ); !( function set ( i ) { const li = _target.querySelector( `[data-code="${ value[ i ] }"]` ); if ( ul[ i + 1 ] ) { // 监听 ul 子元素的变化 // 一旦已经生成了列表 // 就可以执行后续操作 new MutationObserver( () => { ++i; if ( i < value.length ) { set( i ); } } ).observe( ul[ i + 1 ], { childList: true } ); li.click(); } else { li && li.click(); } } )( 0 ); } } // 获取值 iPicker.get = ( id, type ) => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target ) { return; } const result = cacheIPicker.value.get( _target ); // 获取地区行政编码 if ( type === "code" || type === undefined ) { return result[ 0 ]; } // 获取地区名称 if ( type === "name" ) { return result[ 1 ]; } // 获取地区行政编码和名称 if ( type === "all" ) { return result[ 2 ]; } } // 清空值 iPicker.clear = id => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target ) { return; } const $target = $( _target ); const opt = cacheIPicker.options.get( _target ); // 清空值 cacheIPicker.value.set( _target, [ [], [], [] ] ); $target.find( "input" ).val( "" ); $target.find( "li" ).removeClass( "iPicker-list-active" ); $target.find( "ul" ).each( function ( i ) { const $this = $( this ); // 移除第一级以外的其它层级的内容 if ( i ) { $this.html( "" ); if ( opt.theme === "cascader" ) { $this.parent().css( "width", "200px" ); $this.get().style.removeProperty( "display" ); } } } ) if ( opt.theme === "panel" ) { $target .find( ".iPicker-panel-tab > div" ) .eq( 0 ) .addClass( "iPicker-panel-tab-active" ) .siblings() .removeClass( "iPicker-panel-tab-active" ); $target.find( ".iPicker-panel-content > ul" ).eq( 0 ).show().siblings().hide(); } // 滚动条回顶 $target.find( ".iPicker-list" ).get().scrollTop = 0; $target.find( "ul" ).get().scrollTop = 0; return id; } // 重置组件 iPicker.reset = id => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target ) { return; } return iPicker( cacheIPicker.originalElem.get( _target ), cacheIPicker.options.get( _target ) ); } // 销毁组件 iPicker.destroy = id => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target ) { return; } // 移除存储 cacheIPicker.originalElem.delete( _target ); cacheIPicker.value.delete( _target ); cacheIPicker.options.delete( _target ); cacheIPicker.id.delete( _target ); cacheIPicker.target.delete( _target.iPickerID ); // 移除自定义属性 delete _target.iPickerID; // 清空容器 _target.innerHTML = ""; // 当页面中没有 iPicker 组件时移除样式 if ( !document.querySelector( ".iPicker-container" ) ) { $( `#${ styleId }` ).remove(); } } // 启用组件 iPicker.enabled = ( id, level ) => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target || !level ) { return; } const $target = $( _target ); const $result = $target.find( ".iPicker-result" ); // 启用所有层级 if ( level === true ) { $result.removeClass( "iPicker-disabled" ); } // 启用指定的层级 if ( util.isCorrectNumber( level ) ) { level = [ level ]; } if ( Array.isArray( level ) && level.length ) { level.forEach( v => { if ( util.isCorrectNumber( v ) && v >= 1 && v <= 6 ) { $result.eq( v - 1 ).removeClass( "iPicker-disabled" ); } } ) } return id; } // 禁用组件 iPicker.disabled = ( id, level ) => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target || !level ) { return; } const $target = $( _target ); const $result = $target.find( ".iPicker-result" ); // 禁用所有层级 if ( level === true ) { $result.addClass( "iPicker-disabled" ); } // 禁用指定的层级 if ( util.isCorrectNumber( level ) ) { level = [ level ]; } if ( Array.isArray( level ) && level.length ) { level.forEach( v => { if ( util.isCorrectNumber( v ) && v >= 1 && v <= 6 ) { $result.eq( v - 1 ).addClass( "iPicker-disabled" ); } } ) } return id; } // 检测 code 合法性 // 用于 enabledItem 和 disabledItem 方法 const checkCode = code => code.filter( item => typeof item === "string" && item.match( /^\d{6,12}$/ ) ); // 启用全部或指定地区 iPicker.enabledItem = ( id, code ) => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target || !code ) { return; } // 观察器的配置 const options = { childList: true, subtree: true }; // 启用全部地区 if ( code === true ) { new MutationObserver( () => { $( _target ).find( "li" ).removeClass( "iPicker-list-disabled" ); } ).observe( _target, options ); } // 启用指定地区 if ( Array.isArray( code ) && code.length ) { // 检测与去重 code = checkCode( [ ...new Set( code ) ] ); const codeLen = code.length; new MutationObserver( () => { for ( let i = 0; i < codeLen; i++ ) { const li = _target.querySelector( `[data-code="${ code[ i ] }"]` ); if ( li ) { li.classList.remove( "iPicker-list-disabled" ); } } } ).observe( _target, options ); } return id; } // 禁用全部或指定地区 iPicker.disabledItem = ( id, code ) => { const _target = cacheIPicker.target.get( id ); if ( !id || !_target || !code ) { return; } // 观察器的配置 const options = { childList: true, subtree: true }; // 禁用全部地区 if ( code === true ) { new MutationObserver( () => { $( _target ).find( "li" ).addClass( "iPicker-list-disabled" ); } ).observe( _target, options ); } // 禁用指定地区 if ( Array.isArray( code ) && code.length ) { // 检测与去重 code = checkCode( [ ...new Set( code ) ] ); const codeLen = code.length; new MutationObserver( () => { for ( let i = 0; i < codeLen; i++ ) { const li = _target.querySelector( `[data-code="${ code[ i ] }"]` ); if ( li ) { li.classList.add( "iPicker-list-disabled" ); } } } ).observe( _target, options ); } return id; } // return iPicker; exports('iPicker', iPicker); } );