1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485 |
- /**
- * @summary SelectPage
- * @desc 基于jQuery及使用Bootstrap环境开发的,下拉列表带输入快速查找及结果分页展示的多功能选择器
- * @file selectpage.js
- * @version 2.7
- * @author TerryZeng
- * @contact https://terryz.github.io/
- * @license MIT License
- *
- * 插件的部分功能使用、借鉴了
- * jQuery Plugin: jquery.ajax-combobox
- * 作者:Yuusaku Miyazaki <toumin.m7@gmail.com>(宮崎 雄策)
- *
- * 插件依赖:
- * jQuery1.x
- * font-awesome(图标库)
- *
- * 基本功能:
- * 可实时搜索的下拉列表
- * 对待选择的下拉项目可进行分页
- * 可使用键盘快捷分页操作
- * 使用标签的方式支持下拉项目多选
- *
- * 修改记录:
- * 2016.04.20
- * 增加参数autoSelectFirst(是否自动选择列表中的第一项内容)
- * 解决下拉分页有初始化内容,并删除部分关键字时显示的结果集列表不足一页时,分页栏没有被生成的问题
- * 增加参数autoFillResult(是否自动填充内容)
- * 增加参数noResultClean(是否清空无匹配结果的输入关键字)
- * 2016.06.29
- * 修复分页栏鼠标点击时跳转的页数不正常的问题
- * 2016.08.04
- * 修复因宽度变化导致下拉触发按钮位置在出现下拉列表后发生偏移,原因是原控件的触发按钮是在输入框外部扩展,现已移入输入框内部
- * 2016.08.10
- * 弹出下拉列表时,若有已选中的项目,则将已选中的项目进行高亮,否则对第一行进行高亮
- * 下拉列表展开时,鼠标点击列表区域外,若当前列表已有选中项目,则直接隐藏列表;若当前列表没有默认选中项目,则使用当前高亮项目的内容进行设置
- * 2016.08.12
- * 解决控件对于原始input设置的样式(bootstrap原生提供的宽度样式),宽度显示不正常的问题
- * 增加若设置了formatItem格式函数,则进行匹配的数据源从showField改为formatItem后的结果进行匹配
- * 2016.10
- * 增加光标进入输入框时,打开下拉列表的功能
- * 2017.01.16
- * 解决输入关键进行搜索并有匹配结果时,失去焦点后,没有自动选中第一项
- * 2017.01.19
- * 取消在输入状态时,判断到输入框里内容为空时,隐藏下拉列表的操作
- * 在展示下拉列表时,判断默认与输入框左对齐的列表是否会超出屏幕边界,是则右对齐,否则默认左对齐
- * 2017.01.20
- * 增加下拉列表展示之前判断列表的面板是否会超出底部区域,若超出则将列表向上对齐展示
- * 处理下拉列表显示一次操作显示多次的问题
- * 增加控件已有选中值时,在显示下拉列表时,直接跳转到该项目所在的页
- * 修复一些点击输入框出现下拉列表的Bug
- * 2017.03.24
- * 解决下拉分页插件向上浮动时位置不正确的问题
- * 解决下拉分页插件在已有选中值时,再次点击输入框后,打开的列表分页栏翻页功能无效的问题
- * 2017.04.21
- * 解决打开noResultClean参数,没有匹配输入关键词的项目时,列表不隐藏的问题
- * 2017.04.24
- * 解决控件在设置disabled="disabled"禁用状态时,点击向下的三角尖也可以打开列表的问题
- * 增加控件在已有选中项目时,直接删除输入框中的内容,作为清空控件内容的功能
- * 修改失去焦点的范围从document.body到document
- * 优化键盘输入捕捉的方式
- * 原列表有多页的情况下,再输入关键字,没有匹配到任何项目时,分页条的下一页,最后一页为可点击的样式,且分页信息的内容也不正确
- * 2017.05
- * 代码重构
- * 增加多项选择东西,并以标签(Tag)的形式展现在输入框中
- * 修正插件外框宽度问题
- * 修改选中事件回调的入参从key,value改为选中行的原始数据对象,以便更灵活的数据处理
- * 2017.06
- * 修复部分样式问题
- * 2017.06.13
- * 改名SelectPage
- * 2017.06.24
- * 增加Bootstrap3样式支持
- * 2017.08.08
- * 修复界面上排版内容较少时,列表会向上展示开的问题
- * 增加多选模式下的控制按钮区域,功能:“全选本页”、“取消本页”、“清空全部”
- * 修复最大宽度下超出父容器的宽度问题
- * 修复ajax模式报错的问题
- * 增加eAjaxSuccess请求成功后的数据处理回调
- * 2017.08.13(v2.0)
- * 代码重构
- * 修改默认样式,使用更简洁的风格
- * 增加maxSelectLimit参数,设置多选模式下最大选择个数限制
- * 增加eTagRemove回调函数,在多选模式下,移除标签时触发的回调
- * 优化错误信息展示的交互方式
- * 增加初始化选中项目时(多选模式),允许设置多个内容,例如:data-init="1,2,3,4"
- * 修复键盘操作分页部分情况下会失效的问题
- * 增加selectToCloseList参数,用于设置在多选模式下,选择项目后不关闭列表
- * 修复selectToCloseList:false状态下,键盘操作会失去焦点,操作不连贯的问题
- * 增加$.fn.selectPageClear的API,用于清空控件所有已选中的项目
- * 增加$.fn.selectPageText的API,用于获得已选择的项目文本内容
- * 增加$.fn.selectPageData的API,用于动态修改插件数据源
- * 增加$.fn.SelectedRefresh的API,用于在使用.val()的方式修改了插件的选中项目后,刷新显示在输入框中的文本内容
- * 优化控件内部对象缓存机制
- * 去除快速使用脚本b.selectpage.js
- * 初始化入口从原来的$('').bSelectPage({})修改为$('').selectPage({})
- * 重新调整参数名称
- * 修正Bootstrap3下控件宽度、高度应用的BUG
- * 2017.08.19(v2.2)
- * 增加为原始输入框的value属性设置初始化值,以初始化插件选中项目
- * 修复多选模式下关闭标签出错的问题
- * 修复输入查询关键字后失去焦点,再次获得焦点时,插件没有根据已存在的关键进行过滤
- * 增加inputDelay配置项目,设置ajax数据源模式下,延迟输入查询的时间,避免在单位时间内连续输入发起的连续ajax查询,单位:秒,默认值:0.5
- * 修正对数字类型的列进行排序时,仍然以字符串的方式进行排序
- * 2017.08.23(v2.3)
- * 修复在查询关键字状态下,分页数据没有被更新,导致分页按钮功能不正常问题
- * 清理整理内部对象
- * 修复多选模式下,若设置了最大选中项目个数,点击“全选本页”按钮时,仅选中指定的最大数量
- * 增加selectpage.base.css兼容无UI框架的方案,但建议要至少使用normalize.css
- * 2017.08.26(v2.4)
- * 增加pagination参数,指定稿件是否使用分页加载数据,以及显示分页栏
- * 增加listSize参数,指定了不使用分页的列表,显示的高度,单位为个(选项个数),默认显示10个项目的高度
- * 设置selectOnly:true的情况下,输入框为只读模式,不允许输入查询过滤
- * 修复多选模式下及设置了最大选中项目时,选中了项目再次点击“全选本页”按钮会在已选择的基础上增加最大选中项目个数的项目
- * 调整下拉列表样式及位置
- * 增加单选模式下,选中项目后,自动显示清空按钮
- * 修复多选模式下,移除本页和清除所有两个按钮点击后,回调出错的问题
- * 增加搜索无结果时显示提示信息
- * 2017.09.07(v2.5)
- * 修复多选模式下,初始化项目的显示文本没有使用formatItem回调进行格式化
- * 修复ajax数据源模式下,输入查询关键字时,翻页始终为第一页的问题
- * 2017.09.07(v2.6)
- * 修复单选模式下初始化项目的显示文本没有使用formatItem回调格式化的问题
- * 修复单选模式存在初始化项目时,再打开下拉列表时,仅显示匹配的项目一条数据的问题
- * 修复多选模式下,动态修改选中值selectPageRefresh功能无效
- * 2017.09.12(v2.7)
- * 增加eClear回调,单选模式下,清除按钮的功能回调
- * 单选,多选模式下,输入框禁用或只读状态,不显示清除按钮
- * 2017.09.23(v2.8)
- * 调整部分样式
- * 修复可视区域高度较小时,列表始终会向上展开的问题
- * 分离键盘事件处理,对键盘输入精准控制
- * 优化区域外点击处理
- * 优化数据展示渲染效率
- * 优化列表位置定位的准确性
- */
- ;
- (function (factory) {
- if (typeof define === "function" && define.amd) {
- // AMD模式
- define(["jquery"], factory);
- } else {
- // 全局模式
- factory(jQuery);
- }
- }(function ($) {
- "use strict";
- /**
- * @desc 默认参数集
- */
- var defaults = {
- /**
- * @desc 数据源(String:Ajax查询的URL|Object:JSON格式的数据源)
- * @type {string|Object}
- * @example
- * string:服务端请求的URL地址
- * Object:JSON格式数组,推荐格式:[{a:1,b:2,c:3},{...}]
- */
- data: undefined,
- /**
- * @desc 插件显示语言 ('ja', 'en', 'es', 'pt-br'等)
- * @type string 默认'cn'
- */
- lang: 'cn',
- /**
- * @desc 是否为多选模式(标签模式)
- * @type boolean 默认值false
- */
- multiple: false,
- /**
- * @desc 是否分页
- * @type boolean 默认值 true
- */
- pagination: true,
- /**
- * @desc 关闭分页的状态下,列表显示的项目个数,其它的项目以滚动条滚动方式展现
- * @type number 默认值 10
- */
- listSize: 10,
- /**
- * @desc 是否启用多选模式的控制按钮区域
- * 仅multiple: true模式下可用
- * @type boolean 默认值true
- */
- multipleControlbar: true,
- /**
- * @desc 多选模式下最大选择个数,0为不限制
- * @type number 默认0
- */
- maxSelectLimit: 0,
- /**
- * @desc 选中项目后关闭列表
- * 该设置仅在多选模式下multiple:true有效
- * @type boolean 默认值true
- */
- selectToCloseList: true,
- /**
- * @desc 插件初始值指定,该值会与option.keyField字段进行匹配,若匹配到,则自动设置选中并高亮
- * @type string
- */
- initRecord: undefined,
- /**
- * @desc 使用ajax方式获取数据时,使用该参数设置对应的数据表名
- * @type string
- */
- dbTable: 'tbl',
- /**
- * @desc 值字段,通常该字段的内容会自动保存在隐藏域中
- * @type string 默认值为'id'
- */
- keyField: 'id',
- /**
- * @desc 结果集中用于显示的属性名
- * @type string 默认字段为'name'
- */
- showField: 'name',
- /**
- * @desc 查询字段,仅为使用URL(ajax)方式查询服务端时,设置后端查询的字段,不设置则默认使用showField设置的字段
- * @type string
- */
- searchField: undefined,
- /**
- * @desc 查询方式 ('AND' or 'OR')
- * @type string 默认为'AND'
- */
- andOr: 'AND',
- /**
- * @desc 数据排序方式
- * @type array 若不设置则默认对showField指定的字段进行排序
- * @example
- * orderBy : ['id desc']//对ID字段进行降序排序
- */
- orderBy: undefined,
- /**
- * @desc 每页显示的记录数
- * @type number
- */
- pageSize: 10,
- /**
- * @desc 使用URL进行AJAX查询时,可传递查询参数
- * @type function
- * @return object
- * @example params : function(){return {'name':'aa','sex':1};}
- */
- params: undefined,
- /**
- * 列表项目显示内容格式化
- * 参数类型:function
- * @type boolean
- * @param data {object} 行数据object格式
- * @return string
- */
- formatItem: undefined,
- /**
- * 是否在输入框获得焦点时,展开下拉窗口
- * @type boolean 默认值true
- */
- focusDropList: true,
- /**
- * 是否自动选择列表中的第一项内容(输入关键字查询模式,直接使用鼠标下拉并不触发)
- * @type boolean 默认值false
- */
- autoSelectFirst: true,
- /**
- * 是否自动填充内容
- * 若有列表项目被高亮显示,在焦点离开控件后,自动设置该项为选中内容
- * @type boolean 默认值false
- */
- autoFillResult: true,
- /**
- * 是否清空输入关键字
- * 在输入框中输入内容进行查询,但没有匹配的内容返回,在焦点离开控件后,自动清空输入框输入的内容
- * @type boolean 默认值false
- */
- noResultClean: true,
- /**
- * @desc 只选择模式
- * @type boolean
- */
- selectOnly: false,
- /**
- * @desc 输入关键字查询延迟(仅ajax数据源模式下可用)
- * @type number 默认值:0.5秒
- */
- inputDelay: 0.5,
- /**
- * -----------------------------------------事件回调--------------------------------------------
- */
- /**
- * @type function
- * @param object
- * @param dom
- */
- eSelect: undefined,
- /**
- * ajax请求模式,请求成功后的数据处理回调
- * 回调的功能用于自定义处理服务端返回的数据
- * @type function
- * @param data {object} ajax服务端返回的json数据
- * @return {object} 函数返回的数据结构如下:
- * @example
- * {
- * list : [{name:'aa',sex:1},{name:'bb',sex:1}...],
- * totalRow : 100
- * }
- */
- eAjaxSuccess: undefined,
- /**
- * 多选模式下,关闭标签是的回调函数
- * @type function
- * @param removeCount 被移除的个数
- */
- eTagRemove: undefined,
- /**
- * 单选模式下,选中项目后的清除按钮功能回调
- * @type function
- */
- eClear: undefined
- };
- /**
- * @constructor
- * @classdesc 插件初始化
- * @param {Object} input - 插件的初始化输入框元素。
- * @param {Object} option - 初始化参数
- */
- var SelectPage = function (input, option) {
- var option = $.extend({}, option, $(input).data());
- //特殊字段处理
- $.each({data: 'source', keyField: 'primaryKey', showField: 'field', pageSize: 'perPage'}, function (i, j) {
- if (typeof option[j] !== 'undefined') {
- option[i] = option[j];
- delete option[j];
- }
- });
- this.setOption(option);
- this.setLanguage();
- this.setCssClass();
- this.setProp();
- this.setElem(input, option);
- this.setButtonAttrDefault();
- this.setInitRecord();
- this.eDropdownButton();
- this.eInput();
- this.eWhole();
- };
- /**
- * 插件版本号
- */
- SelectPage.version = '2.7';
- /**
- * 插件缓存内部对象的KEY
- */
- SelectPage.dataKey = 'selectPageObject';
- /**
- * 全局范围设置当前点击是否为插件自身的标识
- */
- SelectPage.objStatusKey = 'selectPage-self-mark';
- /**
- * 全局范围设置当前点击的selectpage的索引下标
- */
- SelectPage.objStatusIndex = 'selectPage-self-index';
- /**
- * @desc 参数初始化
- * @param {Object} option - 参数集
- */
- SelectPage.prototype.setOption = function (option) {
- //若没有设置搜索字段,则使用显示字段作为搜索字段
- option.searchField = (option.searchField === undefined) ? option.showField : option.searchField;
- //统一大写
- option.andOr = option.andOr.toUpperCase();
- if (option.andOr !== 'AND' && option.andOr !== 'OR')
- option.andOr = 'AND';
- //将参数内容从使用","分隔的字符串转换为数组
- var arr = ['searchField'];
- for (var i = 0; i < arr.length; i++) {
- option[arr[i]] = this.strToArray(option[arr[i]]);
- }
- //设置排序字段
- option.orderBy = (option.orderBy === undefined) ? option.searchField : option.orderBy;
- //设置多字段排序
- //例: [ ['id', 'ASC'], ['name', 'DESC'] ]
- option.orderBy = this.setOrderbyOption(option.orderBy, option.showField);
- //多选模式下,若设置了选择项目不关闭列表功能,则强制关闭自动选择第一项功能和自动选中高亮的项目功能
- //原因是打开了会总是莫明选择了第一项,体验不佳
- if (option.multiple && !option.selectToCloseList) {
- option.autoFillResult = false;
- option.autoSelectFirst = false;
- }
- if ($.type(option.data) === 'string') {
- option.autoSelectFirst = false;
- }
- //若不需要分页功能,则将所有数据都显示出来,上限200项
- if (!option.pagination)
- option.pageSize = 200;
- if ($.type(option.listSize) !== 'number' || option.listSize < 0)
- option.listSize = 10;
- this.option = option;
- };
- /**
- * @desc 字符串转换为数组
- * @param str {string} - 字符串
- * @return {Array} - 数组
- */
- SelectPage.prototype.strToArray = function (str) {
- if (!str)
- return '';
- return str.replace(/[\s ]+/g, '').split(',');
- };
- /**
- * @desc 设置多字段排序
- * @param {Array} arg_order - 排序顺序
- * @param {string} arg_field - 字段
- * @return {Array} - 处理后的排序字段内容
- */
- SelectPage.prototype.setOrderbyOption = function (arg_order, arg_field) {
- var arr = [], orders = [];
- if (typeof arg_order == 'object') {
- for (var i = 0; i < arg_order.length; i++) {
- orders = $.trim(arg_order[i]).split(' ');
- arr[i] = (orders.length == 2) ? orders : [orders[0], 'ASC'];
- }
- } else {
- orders = $.trim(arg_order).split(' ');
- arr[0] = (orders.length == 2) ? orders : (orders[0].match(/^(ASC|DESC)$/i)) ? [arg_field, orders[0]] : [orders[0], 'ASC'];
- }
- return arr;
- };
- /**
- * @desc 界面文字国际化
- */
- SelectPage.prototype.setLanguage = function () {
- var message;
- switch (this.option.lang) {
- // German
- case 'de':
- message = {
- add_btn: 'Hinzufügen-Button',
- add_title: 'Box hinzufügen',
- del_btn: 'Löschen-Button',
- del_title: 'Box löschen',
- next: 'Nächsten',
- next_title: 'Nächsten' + this.option.pageSize + ' (Pfeil-rechts)',
- prev: 'Vorherigen',
- prev_title: 'Vorherigen' + this.option.pageSize + ' (Pfeil-links)',
- first_title: 'Ersten (Umschalt + Pfeil-links)',
- last_title: 'Letzten (Umschalt + Pfeil-rechts)',
- get_all_btn: 'alle (Pfeil-runter)',
- get_all_alt: '(Button)',
- close_btn: 'Schließen (Tab)',
- close_alt: '(Button)',
- loading: 'lade...',
- loading_alt: '(lade)',
- page_info: 'num_page_top - num_page_end von cnt_whole',
- select_ng: 'Achtung: Bitte wählen Sie aus der Liste aus.',
- select_ok: 'OK : Richtig ausgewählt.',
- not_found: 'nicht gefunden',
- ajax_error: 'Bei der Verbindung zum Server ist ein Fehler aufgetreten.'
- };
- break;
- // English
- case 'en':
- message = {
- add_btn: 'Add button',
- add_title: 'add a box',
- del_btn: 'Del button',
- del_title: 'delete a box',
- next: 'Next',
- next_title: 'Next' + this.option.pageSize + ' (Right key)',
- prev: 'Prev',
- prev_title: 'Prev' + this.option.pageSize + ' (Left key)',
- first_title: 'First (Shift + Left key)',
- last_title: 'Last (Shift + Right key)',
- get_all_btn: 'Get All (Down key)',
- get_all_alt: '(button)',
- close_btn: 'Close (Tab key)',
- close_alt: '(button)',
- loading: 'loading...',
- loading_alt: '(loading)',
- page_info: 'num_page_top - num_page_end of cnt_whole',
- select_ng: 'Attention : Please choose from among the list.',
- select_ok: 'OK : Correctly selected.',
- not_found: 'not found',
- ajax_error: 'An error occurred while connecting to server.'
- };
- break;
- // 中文
- case 'cn':
- message = {
- add_btn: '添加按钮',
- add_title: '添加区域',
- del_btn: '删除按钮',
- del_title: '删除区域',
- next: '下一页',
- next_title: '下' + this.option.pageSize + ' (→)',
- prev: '上一页',
- prev_title: '上' + this.option.pageSize + ' (←)',
- first_title: '首页 (Shift + ←)',
- last_title: '尾页 (Shift + →)',
- get_all_btn: '获得全部 (↓)',
- get_all_alt: '(按钮)',
- close_btn: '关闭 (Tab键)',
- close_alt: '(按钮)',
- loading: '读取中...',
- loading_alt: '(读取中)',
- page_info: 'num_page_top - num_page_end (共 cnt_whole)',
- select_ng: '请注意:请从列表中选择.',
- select_ok: 'OK : 已经选择.',
- not_found: '无查询结果',
- ajax_error: '连接到服务器时发生错误!'
- };
- break;
- // Spanish
- case 'es':
- message = {
- add_btn: 'Agregar boton',
- add_title: 'Agregar una opcion',
- del_btn: 'Borrar boton',
- del_title: 'Borrar una opcion',
- next: 'Siguiente',
- next_title: 'Proximas ' + this.option.pageSize + ' (tecla derecha)',
- prev: 'Anterior',
- prev_title: 'Anteriores ' + this.option.pageSize + ' (tecla izquierda)',
- first_title: 'Primera (Shift + Left)',
- last_title: 'Ultima (Shift + Right)',
- get_all_btn: 'Ver todos (tecla abajo)',
- get_all_alt: '(boton)',
- close_btn: 'Cerrar (tecla TAB)',
- close_alt: '(boton)',
- loading: 'Cargando...',
- loading_alt: '(Cargando)',
- page_info: 'num_page_top - num_page_end de cnt_whole',
- select_ng: 'Atencion: Elija una opcion de la lista.',
- select_ok: 'OK: Correctamente seleccionado.',
- not_found: 'no encuentre',
- ajax_error: 'Un error ocurrió mientras conectando al servidor.'
- };
- break;
- // Brazilian Portuguese
- case 'pt-br':
- message = {
- add_btn: 'Adicionar botão',
- add_title: 'Adicionar uma caixa',
- del_btn: 'Apagar botão',
- del_title: 'Apagar uma caixa',
- next: 'Próxima',
- next_title: 'Próxima ' + this.option.pageSize + ' (tecla direita)',
- prev: 'Anterior',
- prev_title: 'Anterior ' + this.option.pageSize + ' (tecla esquerda)',
- first_title: 'Primeira (Shift + Left)',
- last_title: 'Última (Shift + Right)',
- get_all_btn: 'Ver todos (Seta para baixo)',
- get_all_alt: '(botão)',
- close_btn: 'Fechar (tecla TAB)',
- close_alt: '(botão)',
- loading: 'Carregando...',
- loading_alt: '(Carregando)',
- page_info: 'num_page_top - num_page_end de cnt_whole',
- select_ng: 'Atenção: Escolha uma opção da lista.',
- select_ok: 'OK: Selecionado Corretamente.',
- not_found: 'não encontrado',
- ajax_error: 'Um erro aconteceu enquanto conectando a servidor.'
- };
- break;
- // Japanese
- case 'ja':
- message = {
- add_btn: '追加ボタン',
- add_title: '入力ボックスを追加します',
- del_btn: '削除ボタン',
- del_title: '入力ボックスを削除します',
- next: '次へ',
- next_title: '次の' + this.option.pageSize + '件 (右キー)',
- prev: '前へ',
- prev_title: '前の' + this.option.pageSize + '件 (左キー)',
- first_title: '最初のページへ (Shift + 左キー)',
- last_title: '最後のページへ (Shift + 右キー)',
- get_all_btn: '全件取得 (下キー)',
- get_all_alt: '画像:ボタン',
- close_btn: '閉じる (Tabキー)',
- close_alt: '画像:ボタン',
- loading: '読み込み中...',
- loading_alt: '画像:読み込み中...',
- page_info: 'num_page_top - num_page_end 件 (全 cnt_whole 件)',
- select_ng: '注意 : リストの中から選択してください',
- select_ok: 'OK : 正しく選択されました。',
- not_found: '(0 件)',
- ajax_error: 'サーバとの通信でエラーが発生しました。'
- };
- break;
- }
- this.message = message;
- };
- /**
- * @desc CSS样式表名称字义
- */
- SelectPage.prototype.setCssClass = function () {
- var css_class = {
- container: 'sp_container',
- // SelectPage最外层DIV的打开状态
- container_open: 'sp_container_open',
- re_area: 'sp_result_area',
- control_box: 'sp_control_box',
- //标签及输入框的
- element_box: 'sp_element_box',
- // 分页导航
- navi: 'pagination',
- // 下拉结果列表
- results: 'sp_results',
- re_off: 'sp_results_off',
- select: 'sp_over',
- select_ok: 'sp_select_ok',
- select_ng: 'sp_select_ng',
- selected: 'sp_selected',
- input_off: 'sp_input_off',
- message_box: 'sp_message_box',
- // 多选模式的禁用状态样式
- disabled: 'sp_disabled',
- button: 'sp_button',
- btn_on: 'sp_btn_on',
- btn_out: 'sp_btn_out',
- input: 'sp_input',
- clear_btn: 'sp_clear_btn'
- };
- this.css_class = css_class;
- };
- /**
- * @desc 设置属性默认值
- */
- SelectPage.prototype.setProp = function () {
- this.prop = {
- //当前页
- current_page: 1,
- //总页数
- max_page: 1,
- //是否正在Ajax请求
- is_loading: false,
- xhr: false,
- //使用键盘进行分页
- key_paging: false,
- //使用键盘进行选择
- key_select: false,
- //上一个选择的项目值
- prev_value: '',
- //选中项目的文本内容
- selected_text: '',
- //上一次键盘输入的时间
- last_input_time: undefined
- };
- this.template = {
- tag: {
- content: '<li class="selected_tag" itemvalue="#item_value#">#item_text#<span class="tag_close">×</span></li>',
- textKey: '#item_text#',
- valueKey: '#item_value#'
- }
- };
- };
- /**
- * @desc 插件HTML结构生成
- * @param {Object} combo_input - 输入框源对象
- * @param {Object} option - 插件参数
- */
- SelectPage.prototype.setElem = function (combo_input, option) {
- // 1. 生成、替换DOM对象
- var elem = {};//本体
- var orgWidth = $(combo_input).outerWidth();
- elem.combo_input = $(combo_input).attr({'autocomplete': 'off'}).addClass(this.css_class.input).wrap('<div>');
- //只选择模式设置输入框为只读状态
- if (option.selectOnly)
- $(elem.combo_input).prop('readonly', true);
- elem.container = $(elem.combo_input).parent().addClass(this.css_class.container);
- if ($(elem.combo_input).prop('disabled')) {
- if (option.multiple)
- $(elem.container).addClass(this.css_class.disabled);
- else
- $(elem.combo_input).addClass(this.css_class.input_off);
- }
- //$(elem.container).width(orgWidth);
- elem.button = $('<div>').addClass(this.css_class.button);
- //bootstrap风格的向下三角箭头
- elem.dropdown = $('<span class="bs-caret"><span class="caret"></span></span>');
- //单选模式下清除的按钮X
- elem.clear_btn = $('<div>').append('×').addClass(this.css_class.clear_btn).attr('title', '清除内容');
- //多选模式下带标签显示及文本输入的组合框
- elem.element_box = $('<ul>').addClass(this.css_class.element_box);
- if (option.multiple && option.multipleControlbar)
- elem.control = $('<div>').addClass(this.css_class.control_box);
- //结果集列表
- elem.result_area = $('<div>').addClass(this.css_class.re_area);
- //列表中的分页栏pagination
- if (option.pagination)
- elem.navi = $('<ul>').addClass(this.css_class.navi).addClass("hide");
- elem.results = $('<ul>').addClass(this.css_class.results);
- /**
- * 将原输入框的Name交换到Hidden中,因为具体需要保存传递到后端的是ID,而非Title
- */
- var namePrefix = '_text';
- //将keyField的值放入"input:hidden"
- var input_id = ($(elem.combo_input).attr('id') !== undefined) ? $(elem.combo_input).attr('id') : $(elem.combo_input).attr('name');
- var input_name = ($(elem.combo_input).attr('name') !== undefined) ? $(elem.combo_input).attr('name') : 'selectPage';
- var hidden_name = input_name,
- hidden_id = input_id;
- // CakePHP使用的措施 例:data[search][user] -> data[search][user_primary_key]
- if (input_name.match(/\]$/))
- input_name = input_name.replace(/\]?$/, namePrefix);
- else
- input_name += namePrefix;
- if (input_id.match(/\]$/))
- input_id = input_id.replace(/\]?$/, namePrefix);
- else
- input_id += namePrefix;
- //将输入框的Name与Hidden的Name进行交换,使得可以将项目的具体ID被保存到后端进行处理
- elem.hidden = $('<input type="hidden" class="sp_hidden" />').attr({
- name: hidden_name,
- id: hidden_id
- }).val('');
- $(elem.combo_input).attr({
- name: input_name,
- id: input_id
- });
- // 2. DOM内容放置
- $(elem.container).append(elem.button).append(elem.result_area).append(elem.hidden);
- $(elem.button).append(elem.dropdown);
- $(elem.result_area).append(elem.results);
- if (option.pagination)
- $(elem.result_area).append(elem.navi);
- //多选模式下的特殊处理
- if (option.multiple) {
- if (option.multipleControlbar) {
- // $(elem.control).append('<button type="button" class="btn btn-default sp_select_all" ><i class="fa fa-check-square-o"></i> 全选本页</button>');
- $(elem.control).append('<button type="button" class="btn btn-default sp_unselect_all" ><i class="fa fa-square-o"></i> 取消本页</button>');
- $(elem.control).append('<button type="button" class="btn btn-default sp_clear_all" ><i class="fa fa-ban"></i> 清除全部</button>');
- $(elem.result_area).prepend(elem.control);
- }
- $(elem.container).addClass('sp_container_combo');
- $(elem.combo_input).addClass('sp_combo_input').before($(elem.element_box));
- var li = $('<li>').addClass('input_box');
- $(li).append($(elem.combo_input));
- $(elem.element_box).append($(li));
- if ($(elem.combo_input).attr('placeholder'))
- $(elem.combo_input).attr('placeholder_bak', $(elem.combo_input).attr('placeholder'));
- }
- this.elem = elem;
- };
- /**
- * @desc 将控件的部分内容设置为默认状态
- */
- SelectPage.prototype.setButtonAttrDefault = function () {
- /*
- if (this.option.selectOnly) {
- if ($(this.elem.combo_input).val() !== '') {
- if ($(this.elem.hidden).val() !== '') {
- //选择条件
- $(this.elem.combo_input).attr('title', this.message.select_ok).removeClass(this.css_class.select_ng).addClass(this.css_class.select_ok);
- } else {
- //输入方式
- $(this.elem.combo_input).attr('title', this.message.select_ng).removeClass(this.css_class.select_ok).addClass(this.css_class.select_ng);
- }
- } else {
- $(this.elem.hidden).val('');
- $(this.elem.combo_input).removeAttr('title').removeClass(this.css_class.select_ng);
- }
- }
- */
- $(this.elem.button).attr('title', this.message.get_all_btn);
- //按钮的title属性修改
- $(this.elem.button).attr('title', this.message.close_btn);
- };
- /**
- * @desc 为插件设置初始化的选中值(若有指定的话),执行第一步,数据匹配
- */
- SelectPage.prototype.setInitRecord = function (refresh) {
- var self = this;
- if ($.type($(self.elem.combo_input).data('init')) != 'undefined')
- self.option.initRecord = String($(self.elem.combo_input).data('init'));
- //若在输入框中放入了初始化值,则将它放到隐藏域中进行选中项目初始化
- //若输入框设置了初始值,同时又设置了data-init属性,那么以data-init属性为优先选择
- if (!self.option.initRecord)
- if ($(self.elem.combo_input).val())
- self.option.initRecord = $(self.elem.combo_input).val();
- $(self.elem.combo_input).val('');
- if ((refresh && $(self.elem.hidden).val()) || $.type(self.option.initRecord) === 'string') {
- // 初始的KEY值放入隐藏域
- if (!refresh)
- $(self.elem.hidden).val(self.option.initRecord);
- //将初始值放入控件
- if (typeof self.option.data === 'object') {//json数据源模式
- var data = new Array();
- var keyarr = refresh ? $(self.elem.hidden).val().split(',') : self.option.initRecord.split(',');
- $.each(keyarr, function (index, row) {
- for (var i = 0; i < self.option.data.length; i++) {
- if (self.option.data[i][self.option.keyField] == row) {
- data.push(self.option.data[i]);
- break;
- }
- }
- });
- //在单选模式下,若使用了多选模式的初始化值(“key1,key2,...”多选方式),则不进行初始化选中操作
- if (!self.option.multiple && data.length > 1)
- data = null;
- self.afterInit(self, data);
- } else {//ajax数据源模式
- $.ajax({
- dataType: 'json',
- type: 'POST',
- url: self.option.data,
- data: {
- searchTable: self.option.dbTable,
- searchKey: self.option.keyField,
- searchValue: refresh ? $(self.elem.hidden).val() : self.option.initRecord,
- field: self.option.showField,
- order_by: self.option.orderBy,
- pkey_name: self.option.keyField,
- pkey_value: refresh ? $(self.elem.hidden).val() : self.option.initRecord
- },
- success: function (returnData) {
- var data;
- if (self.option.eAjaxSuccess && $.isFunction(self.option.eAjaxSuccess)) {
- data = self.option.eAjaxSuccess(returnData);
- } else {
- data = returnData;
- }
- self.afterInit(self, data.list);
- },
- error: function (jqXHR, textStatus, errorThrown) {
- self.ajaxErrorNotify(self, errorThrown);
- }
- });
- }
- }
- };
- /**
- * @desc 匹配后的数据在插件中进行展示
- * @param {Object} self - 插件的内部对象
- * @param {Object} data - 列表数据
- */
- SelectPage.prototype.afterInit = function (self, data) {
- if (!data)
- return;
- if (!$.isArray(data))
- data = [data];
- if (data.length === 0)
- return;
- var getText = function (row) {
- var text = row[self.option.showField];
- if (self.option.formatItem && $.isFunction(self.option.formatItem)) {
- try {
- text = self.option.formatItem(row);
- } catch (e) {
- }
- }
- return text;
- };
- if (self.option.multiple) {//多选模式初始化
- self.clearAll(self);
- $.each(data, function (i, row) {
- var item = {text: getText(row), value: row[self.option.keyField]};
- if (!self.isAlreadySelected(self, item))
- self.addNewTag(self, item);
- });
- self.tagValuesSet(self);
- self.inputResize(self);
- } else {//单选模式初始化
- var row = data[0];
- var initval = self.option.init ? self.option.init : $(self.elem.hidden).val();
- if(initval){
- for(var i=0; i<data.length; i++){
- if(initval == data[i][self.option.keyField]){
- row = data[i];
- break;
- }
- }
- }
- $(self.elem.combo_input).val(getText(row));
- $(self.elem.hidden).val(row[self.option.keyField]);
- self.prop.prev_value = getText(row);
- self.prop.selected_text = getText(row);
- if (self.option.selectOnly) {
- $(self.elem.combo_input).attr('title', self.message.select_ok).removeClass(self.css_class.select_ng).addClass(self.css_class.select_ok);
- }
- self.putClearButton();
- }
- };
- /**
- * @desc 下拉按钮的事件处理
- */
- SelectPage.prototype.eDropdownButton = function () {
- var self = this;
- $(self.elem.button).mouseup(function (ev) {
- ev.stopPropagation();
- if ($(self.elem.result_area).is(':hidden') && !$(self.elem.combo_input).prop('disabled')) {
- $(self.elem.combo_input).focus();
- } else
- self.hideResults(self);
- }).mouseout(); // default: mouseout
- };
- /**
- * @desc 输入框的事件绑定
- */
- SelectPage.prototype.eInput = function () {
- var self = this;
- var showList = function () {
- self.prop.page_move = false;
- self.suggest(self);
- self.setCssFocusedInput(self);
- };
- $(self.elem.combo_input).keyup(function (e) {
- self.processKey(self, e);
- }).keydown(function (e) {
- self.processControl(self, e);
- }).focus(function (e) {
- //增加输入框获得焦点后,显示数据列表
- if ($(self.elem.result_area).is(':hidden')) {
- e.stopPropagation();
- self.prop.first_show = true;
- showList();
- }
- });
- $(self.elem.container).on('click.SelectPage', 'div.' + self.css_class.clear_btn, function (e) {
- e.stopPropagation();
- self.clearAll(self);
- $(self.elem.clear_btn).remove();
- if (self.option.eClear && $.isFunction(self.option.eClear))
- self.option.eClear();
- });
- if (self.option.multiple) {
- if (self.option.multipleControlbar) {
- //全选本页按钮
- $('.sp_select_all', self.elem.control).on('click.SelectPage', function (e) {
- self.selectAllLine(self);
- });
- //取消全选本页按钮
- $('.sp_unselect_all', self.elem.control).on('click.SelectPage', function (e) {
- self.unselectAllLine(self);
- });
- //清除全部按钮
- $('.sp_clear_all', self.elem.control).on('click.SelectPage', function (e) {
- self.clearAll(self);
- });
- }
- $(self.elem.element_box).on('click.SelectPage', function (e) {
- var srcEl = e.target || e.srcElement;
- if ($(srcEl).is('ul'))
- $(self.elem.combo_input).focus();
- });
- //标签关闭操作
- //关闭同时需要将该标签的key从已保存的隐藏域中删除
- $(self.elem.element_box).on('click.SelectPage', 'span.tag_close', function () {
- var li = $(this).closest('li');
- self.removeTag(self, li);
- showList();
- if (self.option.eTagRemove && $.isFunction(self.option.eTagRemove))
- self.option.eTagRemove(1);
- });
- self.inputResize(self);
- }
- };
- /**
- * 插件之外区域的事件处理
- */
- SelectPage.prototype.eWhole = function () {
- var self = this;
- /*
- //如果是点击了控件本身则不响应外部鼠标点击事件
- $(self.elem.container).mousedown(function() {
- var thisindex = $('div.sp_container').index(this);
- var lastindex = $(document.body).data(SelectPage.objStatusIndex);
- if(lastindex != undefined && thisindex != lastindex)
- $(document.body).data(SelectPage.objStatusKey,false);
- else
- $(document.body).data(SelectPage.objStatusKey,true);
- $(document.body).data(SelectPage.objStatusIndex,thisindex);
- });
- */
- //控件外部的鼠标点击事件处理
- $(document).off('mousedown.selectPage').on('mousedown.selectPage', function (e) {
- var ele = e.target || e.srcElement;
- var sm = $(ele).closest('div.' + self.css_class.container);
- //清除内容
- var cleanContent = function (obj) {
- $(obj.elem.combo_input).val('');
- if (!obj.option.multiple)
- $(obj.elem.hidden).val('');
- obj.prop.selected_text = '';
- };
- //列表是打开的状态
- $('div.' + self.css_class.container + '.' + self.css_class.container_open).each(function () {
- if (this == sm[0])
- return;
- var d = $('input.' + self.css_class.input, this).data(SelectPage.dataKey);
- //若控件已有选中的的项目,而文本输入框中清空了关键字,则清空控件已选中的项目
- if (!$(d.elem.combo_input).val() && $(d.elem.hidden).val() && !d.option.multiple) {
- d.prop.current_page = 1;//重置当前页为1
- cleanContent(d);
- d.hideResults(d);
- return true;
- }
- //匹配项且高亮时,下拉分页控件失去焦点后,自动选择该项目
- if ($('li', $(d.elem.results)).size() > 0) {
- if (d.option.autoFillResult) {//打开自动内容填充功能
- //若已有选中项目,则直接隐藏列表
- if ($('li.sp_selected', $(d.elem.results)).size() > 0) {
- d.hideResults(d);
- } else if ($('li.sp_over', $(d.elem.results)).size() > 0) {
- //若控件已有选中的值,则忽略高亮的项目
- if ($(d.elem.hidden).val())
- d.hideResults(d);
- //若没有已选中的项目,且列表中有高亮项目时,选中当前高亮的行
- else
- d.selectCurrentLine(d, true);
- } else if (d.option.autoSelectFirst) {
- //若控件已有选中的值,则忽略自动选择第一项的功能
- if ($(d.elem.hidden).val())
- d.hideResults(d);
- else {
- //对于没有选中,没有高亮的情况,若插件设置了自动选中第一项时,则选中第一项
- d.nextLine(d);
- //self.nextLine(self);
- d.selectCurrentLine(d, true);
- }
- } else
- d.hideResults(d);
- } else
- d.hideResults(d);
- } else {
- //无匹配项目时,自动清空用户输入的关键词
- if (d.option.noResultClean)
- cleanContent(d);
- else {
- if (!d.option.multiple)
- $(d.elem.hidden).val('');
- }
- d.hideResults(d);
- }
- });
- /*
- if ($(document.body).data(SelectPage.objStatusKey)) $(document.body).data(SelectPage.objStatusKey,false);
- else {
- //清除内容
- var cleanContent = function(obj){
- $(obj.elem.combo_input).val('');
- if(!obj.option.multiple) $(obj.elem.hidden).val('');
- obj.prop.selected_text = '';
- };
- //列表是打开的状态
- $('div.' + self.css_class.container + '.' + self.css_class.container_open).each(function(){
- var d = $('input.'+self.css_class.input,this).data(SelectPage.dataKey);
-
- //若控件已有选中的的项目,而文本输入框中清空了关键字,则清空控件已选中的项目
- if(!$(d.elem.combo_input).val() && $(d.elem.hidden).val() && !d.option.multiple){
- d.prop.current_page = 1;//重置当前页为1
- cleanContent(d);
- d.hideResults(d);
- return true;
- }
- //匹配项且高亮时,下拉分页控件失去焦点后,自动选择该项目
- if ($('li', $(d.elem.results)).size() > 0) {
- if(d.option.autoFillResult) {//打开自动内容填充功能
- //若已有选中项目,则直接隐藏列表
- if ($('li.sp_selected', $(d.elem.results)).size() > 0) {
- d.hideResults(d);
- }else if($('li.sp_over', $(d.elem.results)).size() > 0){
- //若控件已有选中的值,则忽略高亮的项目
- if($(d.elem.hidden).val()) d.hideResults(d);
- //若没有已选中的项目,且列表中有高亮项目时,选中当前高亮的行
- else d.selectCurrentLine(d, true);
- }else if(d.option.autoSelectFirst){
- //若控件已有选中的值,则忽略自动选择第一项的功能
- if($(d.elem.hidden).val()) d.hideResults(d);
- else{
- //对于没有选中,没有高亮的情况,若插件设置了自动选中第一项时,则选中第一项
- d.nextLine(d);
- //self.nextLine(self);
- d.selectCurrentLine(d, true);
- }
- }else d.hideResults(d);
- }else d.hideResults(d);
- } else {
- //无匹配项目时,自动清空用户输入的关键词
- if (d.option.noResultClean) cleanContent(d);
- else{
- if(!d.option.multiple) $(d.elem.hidden).val('');
- }
- d.hideResults(d);
- }
- });
- }
- */
- });
- };
- /**
- * @desc 结果列表的事件处理
- */
- SelectPage.prototype.eResultList = function () {
- var self = this;
- $(self.elem.results).children('li').mouseenter(function () {
- if (self.prop.key_select) {
- self.prop.key_select = false;
- return;
- }
- // if (!$(this).hasClass(self.css_class.selected) && !$(this).hasClass('sp_message_box')) {
- $(this).addClass(self.css_class.select);
- self.setCssFocusedResults(self);
- // }
- }).mouseleave(function () {
- $(this).removeClass(self.css_class.select);
- }).click(function (e) {
- if (self.prop.key_select) {
- self.prop.key_select = false;
- return;
- }
- e.preventDefault();
- e.stopPropagation();
- // if (!$(this).hasClass(self.css_class.selected))
- self.selectCurrentLine(self, false);
- });
- };
- /**
- * @desc 分页导航按钮的事件处理
- */
- SelectPage.prototype.ehNaviPaging = function () {
- var self = this;
- if (!self.option.pagination)
- return;
- $('li.csFirstPage', $(self.elem.navi)).off('click').on('click', function (ev) {
- //$(self.elem.combo_input).focus();
- ev.preventDefault();
- self.firstPage(self);
- });
- $('li.csPreviousPage', $(self.elem.navi)).off('click').on('click', function (ev) {
- //$(self.elem.combo_input).focus();
- ev.preventDefault();
- self.prevPage(self);
- });
- $('li.csNextPage', $(self.elem.navi)).off('click').on('click', function (ev) {
- //$(self.elem.combo_input).focus();
- ev.preventDefault();
- self.nextPage(self);
- });
- $('li.csLastPage', $(self.elem.navi)).off('click').on('click', function (ev) {
- //$(self.elem.combo_input).focus();
- ev.preventDefault();
- self.lastPage(self);
- });
- };
- /**
- * @desc Ajax请求失败的处理
- * @param {Object} self - 插件内部对象
- * @param {string} errorThrown - Ajax的错误输出内容
- */
- SelectPage.prototype.ajaxErrorNotify = function (self, errorThrown) {
- self.showMessage(self.message.ajax_error);
- };
- /**
- * @desc 交互消息显示
- * @param {Object} self - 插件内部对象
- * @param msg {string} 需要提示的文本
- */
- SelectPage.prototype.showMessage = function (self, msg) {
- if (!msg)
- return;
- var msgLi = '<li class="sp_message_box"><i class="fa fa-exclamation-triangle"></i> ' + msg + '</li>';
- $(self.elem.results).empty().append(msgLi);
- self.calcResultsSize(self);
- $(self.elem.container).addClass(self.css_class.container_open);
- $(self.elem.control).hide();
- if (self.option.pagination)
- $(self.elem.navi).hide();
- };
- /**
- * @desc 窗口滚动处理
- * @param {Object} self - 插件内部对象
- * @param {boolean} enforce - 是否定位到输入框的位置
- */
- SelectPage.prototype.scrollWindow = function (self, enforce) {
- var current_result = self.getCurrentLine(self);
- var target_top = (current_result && !enforce) ? current_result.offset().top : $(self.elem.container).offset().top;
- var target_size;
- self.prop.size_li = $(self.elem.results).children('li:first').outerHeight();
- target_size = self.prop.size_li;
- var client_height = $(window).height();
- var scroll_top = $(window).scrollTop();
- var scroll_bottom = scroll_top + client_height - target_size;
- // 滚动处理
- var gap;
- if ($(current_result).length) {
- if (target_top < scroll_top || target_size > client_height) {
- //滚动到顶部
- gap = target_top - scroll_top;
- } else if (target_top > scroll_bottom) {
- //向下滚动
- gap = target_top - scroll_bottom;
- } else
- return; //不进行滚动
- } else if (target_top < scroll_top)
- gap = target_top - scroll_top;
- window.scrollBy(0, gap);
- };
- /**
- * @desc 输入框获得焦点的样式设置
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.setCssFocusedInput = function (self) {
- //$(self.elem.results).addClass(self.css_class.re_off);
- //$(self.elem.combo_input).removeClass(self.css_class.input_off);
- };
- /**
- * @desc 设置结果列表高亮,输入框失去焦点
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.setCssFocusedResults = function (self) {
- //$(self.elem.results).removeClass(self.css_class.re_off);
- //$(self.elem.combo_input).addClass(self.css_class.input_off);
- };
- /**
- * @desc 输入框输入值的变化监控
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.checkValue = function (self) {
- var now_value = $(self.elem.combo_input).val();
- if (now_value != self.prop.prev_value) {
- self.prop.prev_value = now_value;
- self.prop.first_show = false;
- if (self.option.selectOnly)
- self.setButtonAttrDefault();
- if (!self.option.multiple && !now_value) {
- self.clearAll(self);
- $(self.elem.clear_btn).remove();
- }
- self.suggest(self);
- }
- };
- /**
- * @desc 文本输入框键盘事件处理(普通字符输入处理)
- * @param {Object} self - 插件内部对象
- * @param {Object} e - 事件event对象
- */
- SelectPage.prototype.processKey = function (self, e) {
- if ($.inArray(e.keyCode, [37, 38, 39, 40, 27, 9, 13]) === -1) {
- if (e.keyCode != 16)
- self.setCssFocusedInput(self); // except Shift(16)
- self.inputResize(self);
- if ($.type(self.option.data) === 'string') {
- self.prop.last_input_time = e.timeStamp;
- setTimeout(function () {
- if ((e.timeStamp - self.prop.last_input_time) === 0)
- self.checkValue(self);
- }, self.option.inputDelay * 1000);
- } else {
- self.checkValue(self);
- }
- }
- }
- /**
- * @desc 文本输入框键盘事件处理(控制键处理)
- * @param {Object} self - 插件内部对象
- * @param {Object} e - 事件event对象
- */
- SelectPage.prototype.processControl = function (self, e) {
- if (($.inArray(e.keyCode, [37, 38, 39, 40, 27, 9]) > -1 && $(self.elem.result_area).is(':visible')) ||
- ($.inArray(e.keyCode, [13, 9]) > -1 && self.getCurrentLine(self))) {
- e.preventDefault();
- e.stopPropagation();
- e.cancelBubble = true;
- e.returnValue = false;
- switch (e.keyCode) {
- case 37:
- // left
- if (e.shiftKey)
- self.firstPage(self);
- else
- self.prevPage(self);
- break;
- case 38:
- // up
- self.prop.key_select = true;
- self.prevLine(self);
- break;
- case 39:
- // right
- if (e.shiftKey)
- self.lastPage(self);
- else
- self.nextPage(self);
- break;
- case 40:
- // down
- if ($(self.elem.results).children('li').length) {
- self.prop.key_select = true;
- self.nextLine(self);
- } else
- self.suggest(self);
- break;
- case 9:
- // tab
- self.prop.key_paging = true;
- self.selectCurrentLine(self, true);
- //self.hideResults(self);
- break;
- case 13:
- // return
- self.selectCurrentLine(self, true);
- break;
- case 27:
- // escape
- self.prop.key_paging = true;
- self.hideResults(self);
- break;
- }
- }
- };
- /**
- * @desc 中断Ajax请求
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.abortAjax = function (self) {
- if (self.prop.xhr) {
- self.prop.xhr.abort();
- self.prop.xhr = false;
- }
- };
- /**
- * @desc 数据查询
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.suggest = function (self) {
- //搜索关键字
- var q_word;
- var val = $.trim($(self.elem.combo_input).val());
- if (self.option.multiple)
- q_word = val;
- else {
- if (val && val === self.prop.selected_text)
- q_word = '';
- else
- q_word = val;
- }
- q_word = q_word.split(/[\s ]+/);
- self.abortAjax(self);
- self.setLoading(self);
- var which_page_num = self.prop.current_page > 0 ? self.prop.current_page : 1;
- // 数据查询
- if (typeof self.option.data == 'object')
- self.searchForJson(self, q_word, which_page_num);
- else
- self.searchForDb(self, q_word, which_page_num);
- };
- /**
- * @private
- * @desc 读取中状态显示
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.setLoading = function (self) {
- //加载中的状态提示
- if ($(self.elem.results).html() === '') {
- //self.calcResultsSize(self);
- $(self.elem.container).addClass(self.css_class.container_open);
- }
- };
- /**
- * @desc 服务端数据查询
- * @param {Object} self - 插件内部对象
- * @param {Array} q_word - 查询关键字
- * @param {number} which_page_num - 目标页
- */
- SelectPage.prototype.searchForDb = function (self, q_word, which_page_num) {
- if(typeof dosomething == "function"){
- self.option.eAjaxSuccess = dosomething;
- }
- if (!self.option.eAjaxSuccess || !$.isFunction(self.option.eAjaxSuccess))
- self.hideResults(self);
- /**
- * 增加自定义查询参数
- */
- var _paramsFunc = self.option.params;
- var _params = {};
- //原始参数
- var searchKey = self.option.searchField;
- //若有查询关键字,则重置当前页码为1
- if (q_word.length > 0 && q_word[0] && q_word[0] !== self.prop.prev_value)
- which_page_num = 1;
- var _orgParams = {
- q_word: q_word,
- pageNumber: which_page_num,
- pageSize: self.option.pageSize,
- andOr: self.option.andOr,
- orderBy: self.option.orderBy,
- searchTable: self.option.dbTable,
- page: which_page_num,
- per_page: self.option.pageSize,
- and_or: self.option.andOr,
- order_by: self.option.orderBy,
- field: self.option.showField,
- pkey_name: self.option.keyField,
- search_field: searchKey
- };
- _orgParams[searchKey] = q_word[0];
- if (_paramsFunc) {
- var result = $.isFunction(_paramsFunc) ? _paramsFunc() : _paramsFunc;
- if (result && $.isPlainObject(result)) {
- _params = $.extend({}, _orgParams, result);
- } else {
- _params = _orgParams;
- }
- } else {
- _params = _orgParams;
- }
- //增加自定义查询参数End
- self.prop.xhr = $.ajax({
- dataType: 'json',
- url: self.option.data,
- type: 'POST',
- data: _params,
- success: function (returnData) {
- if (!returnData || !$.isPlainObject(returnData)) {
- self.hideResults(self);
- self.ajaxErrorNotify(self);
- return;
- }
- var data;
- if (self.option.eAjaxSuccess && $.isFunction(self.option.eAjaxSuccess)) {
- data = self.option.eAjaxSuccess(returnData);
- } else {
- data = returnData;
- }
- //数据结构处理
- var json = {};
- json.originalResult = data.list;
- json.cnt_whole = typeof data.total !== 'undefined' ? data.total : (typeof data.totalRow !== 'undefined' ? data.totalRow : data.list.length);
- json.candidate = [];
- json.keyField = [];
- if (typeof json.originalResult != 'object') {
- self.prop.xhr = null;
- self.notFoundSearch(self);
- return;
- }
- json.cnt_page = json.originalResult.length;
- for (var i = 0; i < json.cnt_page; i++) {
- for (var key in json.originalResult[i]) {
- if (key == self.option.keyField) {
- json.keyField.push(json.originalResult[i][key]);
- }
- if (key == self.option.showField) {
- json.candidate.push(json.originalResult[i][key]);
- }
- }
- }
- self.prepareResults(self, json, q_word, which_page_num);
- },
- error: function (jqXHR, textStatus, errorThrown) {
- if (textStatus != 'abort') {
- self.hideResults(self);
- self.ajaxErrorNotify(self, errorThrown);
- }
- },
- complete: function () {
- self.prop.xhr = null;
- }
- });
- };
- /**
- * @desc 对JSON源数据进行搜索
- * @param {Object} self - 插件内部对象
- * @param {Array} q_word - 搜索关键字
- * @param {number} which_page_num - 目标页数
- */
- SelectPage.prototype.searchForJson = function (self, q_word, which_page_num) {
- var matched = [];
- var esc_q = [];
- var sorted = [];
- var json = {};
- var i = 0;
- var arr_reg = [];
- //查询条件过滤
- do {
- //'/\W/g'正则代表全部不是字母,数字,下划线,汉字的字符
- //将非法字符进行转义
- esc_q[i] = q_word[i].replace(/\W/g, '\\$&').toString();
- arr_reg[i] = new RegExp(esc_q[i], 'gi');
- i++;
- } while (i < q_word.length);
- // SELECT * FROM data WHERE field LIKE q_word;
- for (i = 0; i < self.option.data.length; i++) {
- var flag = false;
- var row = self.option.data[i];
- for (var j = 0; j < arr_reg.length; j++) {
- var itemText = row[self.option.showField];//默认获取showField字段的文本
- if (self.option.formatItem && $.isFunction(self.option.formatItem))
- itemText = self.option.formatItem(row);
- if (itemText.match(arr_reg[j])) {
- flag = true;
- if (self.option.andOr == 'OR')
- break;
- } else {
- flag = false;
- if (self.option.andOr == 'AND')
- break;
- }
- }
- if (flag)
- matched.push(row);
- }
- // (CASE WHEN ...) 然后 く order 指定列
- var reg1 = new RegExp('^' + esc_q[0] + '$', 'gi');
- var reg2 = new RegExp('^' + esc_q[0], 'gi');
- var matched1 = [];
- var matched2 = [];
- var matched3 = [];
- for (i = 0; i < matched.length; i++) {
- var orderField = self.option.orderBy[0][0];
- var orderValue = String(matched[i][orderField]);
- if (orderValue.match(reg1)) {
- matched1.push(matched[i]);
- } else if (orderValue.match(reg2)) {
- matched2.push(matched[i]);
- } else {
- matched3.push(matched[i]);
- }
- }
- if (self.option.orderBy[0][1].match(/^asc$/i)) {
- matched1 = self.sortAsc(self, matched1);
- matched2 = self.sortAsc(self, matched2);
- matched3 = self.sortAsc(self, matched3);
- } else {
- matched1 = self.sortDesc(self, matched1);
- matched2 = self.sortDesc(self, matched2);
- matched3 = self.sortDesc(self, matched3);
- }
- sorted = sorted.concat(matched1).concat(matched2).concat(matched3);
- //若没有匹配项目,则结束搜索
- /*
- if (sorted.length === undefined || sorted.length === 0 ) {
- self.notFoundSearch(self);
- return;
- }
- */
- json.cnt_whole = sorted.length;
- //page_move参数用于区别数据加载是在初始化列表还是在进行分页的翻页操作
- if (!self.prop.page_move) {
- //仅单选模式进行选中项目定位页功能
- if (!self.option.multiple) {
- //若控件当前已有选中值,则获得该项目所在的页数,并跳转到该页进行显示
- var currentValue = $(self.elem.hidden).val();
- if ($.type(currentValue) !== 'undefined' && $.trim(currentValue) !== '') {
- var index = 0;
- $.each(sorted, function (i, row) {
- if (row[self.option.keyField] == currentValue) {
- index = i + 1;
- return false;
- }
- });
- which_page_num = Math.ceil(index / self.option.pageSize);
- if (which_page_num < 1)
- which_page_num = 1;
- self.prop.current_page = which_page_num;
- }
- }
- } else {
- //过滤后的数据个数不足一页显示的个数时,强制设置页码
- if (sorted.length <= ((which_page_num - 1) * self.option.pageSize)) {
- which_page_num = 1;
- self.prop.current_page = 1;
- }
- }
- // LIMIT xx OFFSET xx
- var start = (which_page_num - 1) * self.option.pageSize;
- var end = start + self.option.pageSize;
- //储存原始行数据,包括所有属性
- json.originalResult = [];
- // 查询后的数据处理
- for (i = start; i < end; i++) {
- if (sorted[i] === undefined)
- break;
- json.originalResult.push(sorted[i]);
- for (var key in sorted[i]) {
- if (key == self.option.keyField) {
- if (json.keyField === undefined)
- json.keyField = [];
- json.keyField.push(sorted[i][key]);
- }
- if (key == self.option.showField) {
- if (json.candidate === undefined)
- json.candidate = [];
- json.candidate.push(sorted[i][key]);
- }
- }
- }
- if (json.candidate === undefined)
- json.candidate = [];
- json.cnt_page = json.candidate.length;
- self.prepareResults(self, json, q_word, which_page_num);
- };
- /**
- * @desc 升序排序
- * @param {Object} self - 插件内部对象
- * @param {Array} arr - 结果集数组
- */
- SelectPage.prototype.sortAsc = function (self, arr) {
- arr.sort(function (a, b) {
- var valA = a[self.option.orderBy[0][0]];
- var valB = b[self.option.orderBy[0][0]];
- return $.type(valA) === 'number' ? valA - valB : String(valA).localeCompare(String(valB));
- });
- return arr;
- };
- /**
- * @desc 降序排序
- * @param {Object} self - 插件内部对象
- * @param {Array} arr - 结果集数组
- */
- SelectPage.prototype.sortDesc = function (self, arr) {
- arr.sort(function (a, b) {
- var valA = a[self.option.orderBy[0][0]];
- var valB = b[self.option.orderBy[0][0]];
- return $.type(valA) === 'number' ? valB - valA : String(valB).localeCompare(String(valA));
- });
- return arr;
- };
- /**
- * @desc 查询无结果的处理
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.notFoundSearch = function (self) {
- $(self.elem.results).empty();
- self.calcResultsSize(self);
- $(self.elem.container).addClass(self.css_class.container_open);
- self.setCssFocusedInput(self);
- };
- /**
- * @desc 查询结果处理
- * @param {Object} self - 插件内部对象
- * @param {Object} json - 数据结果
- * @param {Array} q_word - 查询关键字
- * @param {number} which_page_num - 目标页
- */
- SelectPage.prototype.prepareResults = function (self, json, q_word, which_page_num) {
- //处理分页栏
- if (self.option.pagination)
- self.setNavi(self, json.cnt_whole, json.cnt_page, which_page_num);
- if (!json.keyField)
- json.keyField = false;
- //仅选择模式
- if (self.option.selectOnly && json.candidate.length === 1 && json.candidate[0] == q_word[0]) {
- $(self.elem.hidden).val(json.keyField[0]);
- this.setButtonAttrDefault();
- }
- //是否是输入关键词进行查找
- var is_query = false;
- if (q_word && q_word.length > 0 && q_word[0])
- is_query = true;
- //显示结果列表
- self.displayResults(self, json, is_query);
- };
- /**
- * @desc 生成分页栏
- * @param {Object} self - 插件内部对象
- * @param {number} cnt_whole - 数据总条数
- * @param {number} cnt_page - 页面显示记录数
- * @param {number} page_num - 当前页数
- */
- SelectPage.prototype.setNavi = function (self, cnt_whole, cnt_page, page_num) {
- /**
- * 生成分页条
- */
- var buildPageNav = function (self, pagebar, page_num, last_page) {
- if ($('li', $(pagebar)).size() == 0) {
- $(pagebar).empty();
- //处理当当前页码为1时,首页和上一页按钮不允许点击
- var btnclass = '', isNewFontAwesome = true;
- //判断是否使用了font-awesome3.2.1
- $.each(document.styleSheets, function (i, n) {
- if (n && n.href && n.href.indexOf('font-awesome-3.2.1') != -1) {
- isNewFontAwesome = false;
- return false;
- }
- });
- //为不同版本图标设置样式
- var iconFist = 'fa fa-angle-double-left', iconPrev = 'fa fa-angle-left', iconNext = 'fa fa-angle-right', iconLast = 'fa fa-angle-double-right';
- if (!isNewFontAwesome) {
- iconFist = 'icon-step-backward';
- iconPrev = 'icon-backward';
- iconNext = 'icon-forward';
- iconLast = 'icon-step-forward';
- }
- if (page_num == 1)
- btnclass = ' disabled ';
- //首页
- $(pagebar).append('<li class="csFirstPage' + btnclass + '" title="' + self.message.first_title + '" ><a href="javascript:void(0);"> <i class="' + iconFist + '"></i> </a></li>');
- //上一页
- $(pagebar).append('<li class="csPreviousPage' + btnclass + '" title="' + self.message.prev_title + '" ><a href="javascript:void(0);"><i class="' + iconPrev + '"></i></a></li>');
- var pageInfo = '第 ' + page_num + ' 页(共' + last_page + '页)';
- //设置分页信息
- $(pagebar).append('<li class="pageInfoBox"><a href="javascript:void(0);"> ' + pageInfo + ' </a></li>');
- if (page_num == last_page)
- btnclass = ' disabled ';
- else
- btnclass = '';
- //首页
- $(pagebar).append('<li class="csNextPage' + btnclass + '" title="' + self.message.next_title + '" ><a href="javascript:void(0);"><i class="' + iconNext + '"></i></a></li>');
- //上一页
- $(pagebar).append('<li class="csLastPage' + btnclass + '" title="' + self.message.last_title + '" ><a href="javascript:void(0);"> <i class="' + iconLast + '"></i> </a></li>');
- }
- };
- var pagebar = $(self.elem.navi);
- var last_page = Math.ceil(cnt_whole / self.option.pageSize); //计算总页数
- if (last_page == 0)
- page_num = 0;
- else {
- if (last_page < page_num)
- page_num = last_page;
- else if (page_num == 0)
- page_num = 1;
- }
- self.prop.current_page = page_num;//更新当前页参数
- self.prop.max_page = last_page;//更新总页数参数
- buildPageNav(self, pagebar, page_num, last_page);
- //刷新分页信息
- var pageInfoBox = $('li.pageInfoBox', $(pagebar));
- var pageInfo = '第 ' + page_num + ' 页(共' + last_page + '页)';
- $(pageInfoBox).html('<a href="javascript:void(0);"> ' + pageInfo + ' </a>');
- //更新分页样式
- var dClass = 'disabled';
- var first = $('li.csFirstPage', $(pagebar));
- var previous = $('li.csPreviousPage', $(pagebar));
- var next = $('li.csNextPage', $(pagebar));
- var last = $('li.csLastPage', $(pagebar));
- //处理首页,上一页按钮样式
- if (page_num === 1 || page_num === 0) {
- if (!$(first).hasClass(dClass))
- $(first).addClass(dClass);
- if (!$(previous).hasClass(dClass))
- $(previous).addClass(dClass);
- } else {
- if ($(first).hasClass(dClass))
- $(first).removeClass(dClass);
- if ($(previous).hasClass(dClass))
- $(previous).removeClass(dClass);
- }
- //处理下一页,最后一页按钮的样式
- if (page_num == last_page || last_page == 0) {
- if (!$(next).hasClass(dClass))
- $(next).addClass(dClass);
- if (!$(last).hasClass(dClass))
- $(last).addClass(dClass);
- } else {
- if ($(next).hasClass(dClass))
- $(next).removeClass(dClass);
- if ($(last).hasClass(dClass))
- $(last).removeClass(dClass);
- }
- if (last_page > 1)
- self.ehNaviPaging(); //导航按钮的事件设置
- };
- /**
- * @desc 显示结果集列表
- * @param {Object} self - 插件内部对象
- * @param {Object} json 源数据
- * @param {boolean} is_query - 是否是通过关键字搜索(用于区分是鼠标点击下拉还是输入框输入关键字进行查找)
- */
- SelectPage.prototype.displayResults = function (self, json, is_query) {
- $(self.elem.results).empty();
- if (self.option.multiple && $.type(self.option.maxSelectLimit) === 'number' && self.option.maxSelectLimit > 0) {
- var selectedSize = $('li.selected_tag', self.elem.element_box).size();
- if (selectedSize > 0 && selectedSize >= self.option.maxSelectLimit) {
- self.showMessage(self, '最多只能选择 ' + self.option.maxSelectLimit + ' 个项目');
- return;
- }
- }
- if (json.candidate.length > 0) {
- var arr_candidate = json.candidate;
- var arr_primary_key = json.keyField;
- var keystr = $(self.elem.hidden).val();
- var keyArr = keystr ? keystr.split(',') : new Array();
- for (var i = 0; i < arr_candidate.length; i++) {
- var itemText = '';
- if (self.option.formatItem && $.isFunction(self.option.formatItem)) {
- try {
- itemText = self.option.formatItem(json.originalResult[i]);
- } catch (e) {
- console.error('formatItem内容格式化函数内容设置不正确!');
- itemText = arr_candidate[i];
- }
- } else
- itemText = arr_candidate[i];
- //XSS対策
- var list = $('<li>').html(itemText).attr({
- pkey: arr_primary_key[i],
- title: itemText
- });
- //选中项目设置高亮样式
- if ($.inArray(arr_primary_key[i].toString(), keyArr) !== -1) {
- $(list).addClass(self.css_class.selected);
- }
- //缓存原始行对象
- $(list).data('dataObj', json.originalResult[i]);
- $(self.elem.results).append(list);
- }
- } else {
- var li = '<li class="sp_message_box"><i class="fa fa-exclamation-triangle"></i> ' + self.message.not_found + '</li>';
- $(self.elem.results).append(li);
- }
- if (self.option.multiple && self.option.multipleControlbar)
- $(self.elem.control).show();
- if (self.option.pagination)
- $(self.elem.navi).toggleClass("hide", json.cnt_whole <= json.cnt_page);
- //显示结果集列表并调整位置
- self.calcResultsSize(self);
- $(self.elem.container).addClass(self.css_class.container_open);
- //结果集列表事件绑定
- self.eResultList();
- //若是键盘输入关键字进行查询且有内容时,列表自动选中第一行(autoSelectFirst为true时)
- if (is_query && json.candidate.length > 0 && self.option.autoSelectFirst)
- self.nextLine(self);
- };
- /**
- * @desc 处理结果列表尺寸及位置
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.calcResultsSize = function (self) {
- var rePosition = function () {
- if ($(self.elem.container).css('position') === 'static') {
- // position: static
- var offset = $(self.elem.combo_input).offset();
- $(self.elem.result_area).css({
- top: offset.top + $(self.elem.combo_input).outerHeight() + 'px',
- left: offset.left + 'px'
- });
- } else {
- if (!self.option.pagination) {
- var itemHeight = $('li:first', self.elem.results).outerHeight(true);
- var listHeight = itemHeight * self.option.listSize;
- $(self.elem.results).css({
- 'max-height': listHeight,
- 'overflow-y': 'auto'
- });
- }
- //在展示下拉列表时,判断默认与输入框左对齐的列表是否会超出屏幕边界,是则右对齐,否则默认左对齐
- var docWidth = $(document).width();
- var docHeight = $(document).height();//文档全部高度
- var viewHeight = $(window).height();//可视区域高度
- var offset = $(self.elem.container).offset();
- var screenScrollTop = $(window).scrollTop();
- var listWidth = $(self.elem.result_area).outerWidth();
- //当前状态,列表并未被显示,数据未被填充,列表并未展现最终高度,所以只能使用默认一页显示10条数据的固定高度进行计算
- var listHeight = $(self.elem.result_area).outerHeight();
- //默认方向的坐标,在多选模式下,因为外框架是DIV,所以需要向左靠一个像素
- var defaultLeft = self.option.multiple ? -1 : 0;
- //输入框高度
- var inputHeight = $(self.elem.container).outerHeight();
- var left = (offset.left + listWidth) > docWidth ? -(listWidth - $(self.elem.container).outerWidth()) : defaultLeft;
- //控件在全文档范围中的实际TOP(非当前可视区域中的相对TOP)
- var screenTop = offset.top;//$(self.elem.container).scrollTop();//offset.top - screenScrollTop;
- var top = 0, dist = 5;//设置偏移量,让列表与输入框有5px的间距
- //列表展开后的坐标高度
- var listBottom = screenTop + inputHeight + listHeight + dist;
- var hasOverflow = docHeight > viewHeight;
- if ((screenTop - screenScrollTop - dist > listHeight) &&
- (hasOverflow && listBottom > (viewHeight + screenScrollTop)) ||
- (!hasOverflow && listBottom > viewHeight)) {
- //控件当前位置+控件高度+列表高度超过实际body高度
- //列表则需要向上展示
- top = -(listHeight + 1) - dist;
- $(self.elem.result_area).removeClass('shadowUp shadowDown').addClass('shadowUp');
- } else {
- //列表正常向下展示
- top = self.option.multiple ? $(self.elem.container).innerHeight() + 1 : $(self.elem.container).outerHeight();
- $(self.elem.result_area).removeClass('shadowUp shadowDown').addClass('shadowDown');
- top += dist;
- }
- /*
- $(self.elem.result_area).css({
- top : top + 'px',
- left: left + 'px'
- });
- */
- return {
- top: top + 'px',
- left: left + 'px'
- };
- }
- };
- if ($(self.elem.result_area).is(':visible')) {
- $(self.elem.result_area).css(rePosition());
- } else {
- $(self.elem.result_area).show(1, function () {
- $(this).css(rePosition());
- });
- }
- };
- /**
- * @desc 隐藏结果列表
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.hideResults = function (self) {
- if (self.prop.key_paging) {
- self.scrollWindow(self, true);
- self.prop.key_paging = false;
- }
- self.setCssFocusedInput(self);
- if (self.option.autoFillResult) {
- //self.selectCurrentLine(self, true);
- }
- $(self.elem.results).empty();
- $(self.elem.result_area).hide();
- $(self.elem.container).removeClass(self.css_class.container_open);
- self.abortAjax(self);
- self.setButtonAttrDefault(); // 按钮title属性初期化
- };
- /**
- * @desc 跳转到首页
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.firstPage = function (self) {
- if (self.prop.current_page > 1) {
- self.prop.current_page = 1;
- self.prop.page_move = true;
- self.suggest(self);
- }
- };
- /**
- * @desc 跳转到上一页
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.prevPage = function (self) {
- if (self.prop.current_page > 1) {
- self.prop.current_page--;
- self.prop.page_move = true;
- self.suggest(self);
- }
- };
- /**
- * @desc 跳转到下一页
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.nextPage = function (self) {
- if (self.prop.current_page < self.prop.max_page) {
- self.prop.current_page++;
- self.prop.page_move = true;
- self.suggest(self);
- }
- };
- /**
- * @desc 跳转到尾页
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.lastPage = function (self) {
- if (self.prop.current_page < self.prop.max_page) {
- self.prop.current_page = self.prop.max_page;
- self.prop.page_move = true;
- self.suggest(self);
- }
- };
- /**
- * @desc 跳转到指定页
- * @param {Object} self
- * @param {number} page 目标页数
- */
- SelectPage.prototype.goPage = function (self, page) {
- if (typeof (page) === 'undefined')
- page = 1;
- if (self.prop.current_page < self.prop.max_page) {
- self.prop.current_page = page;
- self.prop.page_move = true;
- self.suggest(self);
- }
- };
- /**
- * @desc 操作结束后的一些收尾工作
- */
- SelectPage.prototype.afterAction = function (self) {
- self.inputResize(self);
- $(self.elem.combo_input).trigger("change");
- $(self.elem.hidden).trigger("change");
- self.setCssFocusedInput(self);
- if (self.option.multiple) {
- if (self.option.selectToCloseList) {
- self.hideResults(self);
- $(self.elem.combo_input).blur();
- } else {
- self.suggest(self);
- $(self.elem.combo_input).focus();
- }
- } else {
- self.hideResults(self);
- $(self.elem.combo_input).blur();
- }
- };
- /**
- * @desc 选择当前行
- * @param {Object} self - 插件内部对象
- * @param {boolean} is_enter_key - 是否为回车键
- */
- SelectPage.prototype.selectCurrentLine = function (self, is_enter_key) {
- self.scrollWindow(self, true);
- var current = self.getCurrentLine(self);
- if (current) {
- if (!self.option.multiple) {
- $(self.elem.combo_input).val($(current).text());
- $(self.elem.hidden).val($(current).attr('pkey'));
- } else {
- //多选模式的项目选择处理
- $(self.elem.combo_input).val('');
- var item = {text: $(current).text(), value: $(current).attr('pkey')};
- if (!self.isAlreadySelected(self, item)) {
- self.addNewTag(self, item);
- self.tagValuesSet(self);
- }
- }
- if (self.option.selectOnly)
- self.setButtonAttrDefault();
- //项目选择回调函数触发
- if (self.option.eSelect && $.isFunction(self.option.eSelect))
- self.option.eSelect($(current).data('dataObj'));
- self.prop.prev_value = $(self.elem.combo_input).val();
- self.prop.selected_text = $(self.elem.combo_input).val();
- self.putClearButton();
- }
- self.afterAction(self);
- };
- /**
- * 单选模式下选中项目后,显示清空按钮
- */
- SelectPage.prototype.putClearButton = function () {
- if (!this.option.multiple && !$(this.elem.combo_input).prop('disabled'))
- $(this.elem.container).append(this.elem.clear_btn);
- };
- /**
- * @desc 全选当前页的行
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.selectAllLine = function (self) {
- var jsonarr = new Array();
- $('li', self.elem.results).each(function (i, row) {
- var item = {text: $(row).text(), value: $(row).attr('pkey')};
- if (!self.isAlreadySelected(self, item)) {
- self.addNewTag(self, item);
- self.tagValuesSet(self);
- }
- jsonarr.push($(row).data('dataObj'));
- //若有最大选择数量限制,则添加最大个数后,不再添加
- if ($.type(self.option.maxSelectLimit) === 'number' &&
- self.option.maxSelectLimit > 0 &&
- self.option.maxSelectLimit === $('li.selected_tag', self.elem.element_box).size()) {
- return false;
- }
- });
- if (self.option.eSelect && $.isFunction(self.option.eSelect))
- self.option.eSelect(jsonarr);
- self.afterAction(self);
- };
- /**
- * @desc 取消选择本页全部项目
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.unselectAllLine = function (self) {
- var size = $('li', self.elem.results).size();
- $('li', self.elem.results).each(function (i, row) {
- var key = $(row).attr('pkey');
- var tag = $('li.selected_tag[itemvalue="' + key + '"]', self.elem.element_box);
- self.removeTag(self, tag);
- });
- self.afterAction(self);
- if (self.option.eTagRemove && $.isFunction(self.option.eTagRemove))
- self.option.eTagRemove(size);
- };
- /**
- * @desc 清除所有选中的项目
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.clearAll = function (self) {
- var size = 0;
- if (self.option.multiple) {
- size = $('li.selected_tag', self.elem.element_box).size();
- $('li.selected_tag', self.elem.element_box).remove();
- }
- $(self.elem.combo_input).val('');
- $(self.elem.hidden).val('');
- self.afterAction(self);
- if (self.option.multiple) {
- if (self.option.eTagRemove && $.isFunction(self.option.eTagRemove))
- self.option.eTagRemove(size);
- }
- };
- /**
- * @desc 获得当前行对象
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.getCurrentLine = function (self) {
- if ($(self.elem.result_area).is(':hidden'))
- return false;
- var obj = $('li.' + self.css_class.select, self.elem.results);
- if ($(obj).size())
- return obj;
- else
- return false;
- };
- /**
- * @desc 多选模式下判断当前选中项目是否已经存在已选中列表中
- * @param {Object} self - 插件内部对象
- * @param {Object} item - 选中行对象
- */
- SelectPage.prototype.isAlreadySelected = function (self, item) {
- var isExist = false;
- if (item.value) {
- var keys = $(self.elem.hidden).val();
- if (keys) {
- var karr = keys.split(',');
- if (karr && karr.length > 0 && $.inArray(item.value, karr) != -1)
- isExist = true;
- }
- }
- return isExist;
- };
- /**
- * @desc 多选模式下增加一个标签
- * @param {Object} self - 插件内部对象
- * @param {Object} item - 选中行对象
- */
- SelectPage.prototype.addNewTag = function (self, item) {
- if (!self.option.multiple || !item)
- return;
- var tmp = self.template.tag.content, tag;
- tmp = tmp.replace(self.template.tag.textKey, item.text);
- tmp = tmp.replace(self.template.tag.valueKey, item.value);
- tag = $(tmp);
- if ($(self.elem.combo_input).prop('disabled'))
- $('span.tag_close', tag).hide();
- $(self.elem.combo_input).closest('li').before(tag);
- };
- /**
- * @desc 多选模式下移除一个标签
- * @param {Object} self - 插件内部对象
- * @param {Object} item - 标签对象
- */
- SelectPage.prototype.removeTag = function (self, item) {
- var key = $(item).attr('itemvalue');
- var keys = $(self.elem.hidden).val();
- //从已保存的key列表中删除该标签对应的项目
- if ($.type(key) != 'undefined' && keys) {
- var keyarr = keys.split(',');
- var index = $.inArray(key.toString(), keyarr);
- if (index != -1) {
- keyarr.splice(index, 1);
- $(self.elem.hidden).val(keyarr.toString());
- }
- }
- $(item).remove();
- self.inputResize(self);
- };
- /**
- * @desc 多选模式下标签结果值放入隐藏域
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.tagValuesSet = function (self) {
- if (!self.option.multiple)
- return;
- var tags = $('li.selected_tag', $(self.elem.element_box));
- if (tags && $(tags).size() > 0) {
- var result = new Array();
- $.each(tags, function (i, li) {
- var v = $(li).attr('itemvalue');
- if ($.type(v) !== 'undefined')
- result.push(v);
- });
- if (result.length > 0) {
- $(self.elem.hidden).val(result.join(','));
- }
- }
- };
- /**
- * @desc 多选模式下输入框根据输入内容调整输入框宽度
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.inputResize = function (self) {
- if (!self.option.multiple)
- return;
- var width = '';
- var inputLi = self.elem.combo_input.closest('li');
- //设置默认宽度
- var setDefaultSize = function (self, inputLi) {
- inputLi.removeClass('full_width');
- var minimumWidth = self.elem.combo_input.val().length + 1;
- var width = (minimumWidth * 0.75) + 'em';
- self.elem.combo_input.css('width', width);
- self.elem.combo_input.removeAttr('placeholder');
- };
- if ($('li.selected_tag', $(self.elem.element_box)).size() === 0) {
- if (self.elem.combo_input.attr('placeholder_bak')) {
- if (!inputLi.hasClass('full_width'))
- inputLi.addClass('full_width');
- self.elem.combo_input.attr('placeholder', self.elem.combo_input.attr('placeholder_bak'));
- self.elem.combo_input.removeAttr('style');
- } else
- setDefaultSize(self, inputLi);
- } else
- setDefaultSize(self, inputLi);
- };
- /**
- * @desc 选择下一行
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.nextLine = function (self) {
- var obj = self.getCurrentLine(self);
- var idx;
- if (!obj)
- idx = -1;
- else {
- idx = $(self.elem.results).children('li').index(obj);
- $(obj).removeClass(self.css_class.select);
- }
- idx++;
- if (idx < $(self.elem.results).children('li').length) {
- var next = $(self.elem.results).children('li').eq(idx);
- $(next).addClass(self.css_class.select);
- self.setCssFocusedResults(self);
- } else
- self.setCssFocusedInput(self);
- self.scrollWindow(self, false);
- };
- /**
- * @desc 选择上一行
- * @param {Object} self - 插件内部对象
- */
- SelectPage.prototype.prevLine = function (self) {
- var obj = self.getCurrentLine(self);
- var idx;
- if (!obj)
- idx = $(self.elem.results).children('li').length;
- else {
- idx = $(self.elem.results).children('li').index(obj);
- $(obj).removeClass(self.css_class.select);
- }
- idx--;
- if (idx > -1) {
- var prev = $(self.elem.results).children('li').eq(idx);
- $(prev).addClass(self.css_class.select);
- self.setCssFocusedResults(self);
- } else
- self.setCssFocusedInput(self);
- self.scrollWindow(self, false);
- };
- /**
- * @desc 下拉分页查询控件初始化入口
- * @global
- * @memberof jQuery,bootstrap2,bootstrap3
- * @param option {Object} 初始化参数集
- */
- function Plugin(option) {
- return this.each(function () {
- var $this = $(this),
- data = $this.data(SelectPage.dataKey),
- params = $.extend({}, defaults, $this.data(), data && data.option, typeof option === 'object' && option);
- if (!data)
- $this.data(SelectPage.dataKey, (data = new SelectPage(this, params)));
- });
- }
- /**
- * 获得稿件内部对象
- * @param {object} obj
- * @returns
- */
- function getPlugin(obj) {
- var container = $(obj).closest('div.sp_container');
- return $('input.sp_input', container);
- }
- /**
- * @desc 清除所有模式下选择的项目
- */
- function ClearSelected() {
- return this.each(function () {
- var $this = getPlugin(this),
- data = $this.data(SelectPage.dataKey);
- if (data)
- data.clearAll(data);
- });
- }
- /**
- * 刷新选中项目内容
- * 使用场景:使用$().val('xxx')修改插件的选中项目ID,此时需要刷新插件在输入框中的显示文本
- */
- function SelectedRefresh() {
- return this.each(function () {
- var $this = getPlugin(this),
- data = $this.data(SelectPage.dataKey);
- if (data && data.elem.hidden.val())
- data.setInitRecord(true);
- });
- }
- /**
- * 修改插件数据源
- * 仅在json数据源模式有效
- * @param {array} data
- * @example
- * [{name:'aa',sex:1},{name:'bb',sex:0},{...}]
- */
- function ModifyDataSource(data) {
- return this.each(function () {
- if (data && $.isArray(data) && data.length > 0) {
- var $this = getPlugin(this),
- plugin = $this.data(SelectPage.dataKey);
- if (plugin) {
- plugin.clearAll(plugin);
- plugin.option.data = data;
- }
- }
- });
- }
- /**
- * @desc 获得选中项目的文本
- * @returns {string}
- */
- function GetInputText() {
- var str = '';
- this.each(function () {
- var $this = getPlugin(this), data = $this.data(SelectPage.dataKey);
- if (data)
- str += data.elem.combo_input.val();
- });
- return str;
- }
- /**
- * @desc 获得选中项目的数据
- * @returns {String}
- */
- function GetInputValue() {
- var str = '';
- this.each(function () {
- var $this = getPlugin(this), data = $this.data(SelectPage.dataKey);
- if (data)
- str += data.elem.hidden.val();
- });
- return str;
- }
- var old = $.fn.selectPage;
- $.fn.selectPage = Plugin;
- $.fn.selectPage.Constructor = SelectPage;
- $.fn.selectPageClear = ClearSelected;
- $.fn.selectPageRefresh = SelectedRefresh;
- $.fn.selectPageData = ModifyDataSource;
- $.fn.selectPageText = GetInputText;
- $.fn.selectPageValue = GetInputValue;
- // 处理新旧版本冲突
- // =================
- $.fn.selectPage.noConflict = function () {
- $.fn.selectPage = old;
- return this;
- };
- }));
|