formSelects-v4.js 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733
  1. /**
  2. * name: formSelects
  3. * 基于Layui Select多选
  4. * version: 4.0.0.0817
  5. * http://sun.faysunshine.com/layui/formSelects-v4/dist/formSelects-v4.js
  6. */
  7. (function(layui, window, factory) {
  8. if(typeof exports === 'object') { // 支持 CommonJS
  9. module.exports = factory();
  10. } else if(typeof define === 'function' && define.amd) { // 支持 AMD
  11. define(factory);
  12. } else if(window.layui && layui.define) { //layui加载
  13. layui.define(['jquery'], function(exports) {
  14. exports('formSelects', factory());
  15. });
  16. } else {
  17. window.formSelects = factory();
  18. }
  19. })(typeof layui == 'undefined' ? null : layui, window, function() {
  20. let v = '4.0.0.0817',
  21. NAME = 'xm-select',
  22. PNAME = 'xm-select-parent',
  23. INPUT = 'xm-select-input',
  24. TDIV = 'xm-select--suffix',
  25. THIS = 'xm-select-this',
  26. LABEL = 'xm-select-label',
  27. SEARCH = 'xm-select-search',
  28. SEARCH_TYPE = 'xm-select-search-type',
  29. SHOW_COUNT = 'xm-select-show-count',
  30. CREATE = 'xm-select-create',
  31. CREATE_LONG = 'xm-select-create-long',
  32. MAX = 'xm-select-max',
  33. SKIN = 'xm-select-skin',
  34. DIRECTION = "xm-select-direction",
  35. HEIGHT = 'xm-select-height',
  36. DISABLED = 'xm-dis-disabled',
  37. DIS = 'xm-select-dis',
  38. TEMP = 'xm-select-temp',
  39. RADIO = 'xm-select-radio',
  40. LINKAGE= 'xm-select-linkage',
  41. DL = 'xm-select-dl',
  42. DD_HIDE = 'xm-select-hide',
  43. HIDE_INPUT = 'xm-hide-input',
  44. SANJIAO = 'xm-select-sj',
  45. ICON_CLOSE = 'xm-icon-close',
  46. FORM_TITLE = 'xm-select-title',
  47. FORM_SELECT = 'xm-form-select',
  48. FORM_SELECTED = 'xm-form-selected',
  49. FORM_NONE = 'xm-select-none',
  50. FORM_EMPTY = 'xm-select-empty',
  51. FORM_INPUT = 'xm-input',
  52. FORM_DL_INPUT = 'xm-dl-input',
  53. FORM_SELECT_TIPS = 'xm-select-tips',
  54. CHECKBOX_YES = 'xm-iconfont',
  55. FORM_TEAM_PID = 'XM_PID_VALUE',
  56. CZ = 'xm-cz',
  57. CZ_GROUP = 'xm-cz-group',
  58. TIPS = '请选择',
  59. data = {},
  60. events = {
  61. on: {},
  62. endOn: {},
  63. filter: {},
  64. maxTips: {},
  65. opened: {},
  66. closed: {}
  67. },
  68. ajax = {
  69. type: 'get',
  70. header: {
  71. },
  72. first: true,
  73. data: {},
  74. searchUrl: '',
  75. searchName: 'keyword',
  76. searchVal: null,
  77. keyName: 'name',
  78. keyVal: 'value',
  79. keySel: 'selected',
  80. keyDis: 'disabled',
  81. keyChildren: 'children',
  82. dataType: '',
  83. delay: 500,
  84. beforeSuccess: null,
  85. success: null,
  86. error: null,
  87. beforeSearch: null,
  88. response: {
  89. statusCode: 0,
  90. statusName: 'code',
  91. msgName: 'msg',
  92. dataName: 'data'
  93. },
  94. tree: {
  95. nextClick: function(id, item, callback){
  96. callback([]);
  97. },
  98. folderChoose: true,
  99. lazy: true
  100. }
  101. },
  102. quickBtns = [
  103. {icon: 'xm-iconfont icon-quanxuan', name: '全选', click: function(id, cm){
  104. cm.selectAll(id, true, true);
  105. }},
  106. {icon: 'xm-iconfont icon-qingkong', name: '清空', click: function(id, cm){
  107. cm.removeAll(id, true, true);
  108. }},
  109. {icon: 'xm-iconfont icon-fanxuan', name: '反选', click: function(id, cm){
  110. cm.reverse(id, true, true);
  111. }},
  112. {icon: 'xm-iconfont icon-pifu', name: '换肤', click: function(id, cm){
  113. cm.skin(id);
  114. }}
  115. ],
  116. $ = window.$ || (window.layui && window.layui.jquery),
  117. $win = $(window),
  118. ajaxs = {},
  119. fsConfig = {},
  120. fsConfigs = {},
  121. FormSelects = function(options) {
  122. this.config = {
  123. name: null, //xm-select="xxx"
  124. max: null,
  125. maxTips: (id, vals, val, max) => {
  126. let ipt = $(`[xid="${this.config.name}"]`).prev().find(`.${NAME}`);
  127. if(ipt.parents('.layui-form-item[pane]').length) {
  128. ipt = ipt.parents('.layui-form-item[pane]');
  129. }
  130. ipt.attr('style', 'border-color: red !important');
  131. setTimeout(() => {
  132. ipt.removeAttr('style');
  133. }, 300);
  134. },
  135. init: null, //初始化的选择值,
  136. on: null, //select值发生变化
  137. opened: null,
  138. closed: null,
  139. filter: (id, inputVal, val, isDisabled) => {
  140. return val.name.indexOf(inputVal) == -1;
  141. },
  142. clearid: -1,
  143. direction: 'auto',
  144. height: null,
  145. isEmpty: false,
  146. btns: [quickBtns[0], quickBtns[1], quickBtns[2]],
  147. searchType: 0,
  148. create: (id, name) => {
  149. return Date.now();
  150. },
  151. template: (name, value, selected, disabled) => {
  152. return name;
  153. },
  154. showCount: 0,
  155. isCreate: false,
  156. placeholder: TIPS,
  157. clearInput: false,
  158. };
  159. this.select = null;
  160. this.values = [];
  161. $.extend(this.config, options, {
  162. searchUrl: options.isSearch ? options.searchUrl : null,
  163. placeholder: options.optionsFirst ? (
  164. options.optionsFirst.value ? TIPS : (options.optionsFirst.innerHTML || TIPS)
  165. ) : TIPS,
  166. btns: options.radio ? [quickBtns[1]] : [quickBtns[0], quickBtns[1], quickBtns[2]],
  167. }, fsConfigs[options.name] || fsConfig);
  168. if(isNaN(this.config.showCount) || this.config.showCount <= 0) {
  169. this.config.showCount = 19921012;
  170. }
  171. };
  172. //一些简单的处理方法
  173. let Common = function(){
  174. this.appender();
  175. this.on();
  176. this.onreset();
  177. };
  178. Common.prototype.appender = function(){//针对IE做的一些拓展
  179. //拓展Array map方法
  180. if(!Array.prototype.map){Array.prototype.map=function(i,h){var b,a,c,e=Object(this),f=e.length>>>0;if(h){b=h}a=new Array(f);c=0;while(c<f){var d,g;if(c in e){d=e[c];g=i.call(b,d,c,e);a[c]=g}c++}return a}};
  181. //拓展Array foreach方法
  182. if(!Array.prototype.forEach){Array.prototype.forEach=function forEach(g,b){var d,c;if(this==null){throw new TypeError("this is null or not defined")}var f=Object(this);var a=f.length>>>0;if(typeof g!=="function"){throw new TypeError(g+" is not a function")}if(arguments.length>1){d=b}c=0;while(c<a){var e;if(c in f){e=f[c];g.call(d,e,c,f)}c++}}};
  183. //拓展Array filter方法
  184. if(!Array.prototype.filter){Array.prototype.filter=function(b){if(this===void 0||this===null){throw new TypeError()}var f=Object(this);var a=f.length>>>0;if(typeof b!=="function"){throw new TypeError()}var e=[];var d=arguments[1];for(var c=0;c<a;c++){if(c in f){var g=f[c];if(b.call(d,g,c,f)){e.push(g)}}}return e}};
  185. }
  186. Common.prototype.init = function(target){
  187. //初始化页面上已有的select
  188. $((target ? target : `select[${NAME}]`)).each((index, select) => {
  189. let othis = $(select),
  190. id = othis.attr(NAME),
  191. hasLayuiRender = othis.next(`.layui-form-select`),
  192. hasRender = othis.next(`.${PNAME}`),
  193. options = {
  194. name: id,
  195. disabled: select.disabled,
  196. max: othis.attr(MAX) - 0,
  197. isSearch: othis.attr(SEARCH) != undefined,
  198. searchUrl: othis.attr(SEARCH),
  199. isCreate: othis.attr(CREATE) != undefined,
  200. radio: othis.attr(RADIO) != undefined,
  201. skin: othis.attr(SKIN),
  202. direction: othis.attr(DIRECTION),
  203. optionsFirst: select.options[0],
  204. height: othis.attr(HEIGHT),
  205. formname: othis.attr('name') || othis.attr('_name'),
  206. layverify: othis.attr('lay-verify') || othis.attr('_lay-verify'),
  207. layverType: othis.attr('lay-verType'),
  208. searchType: othis.attr(SEARCH_TYPE) == 'dl' ? 1 : 0,
  209. showCount: othis.attr(SHOW_COUNT) - 0,
  210. },
  211. value = othis.find('option[selected]').toArray().map((option) => {//获取已选中的数据
  212. return {
  213. name: option.innerHTML,
  214. value: option.value,
  215. }
  216. }),
  217. fs = new FormSelects(options);
  218. fs.values = value;
  219. if(fs.config.init) {
  220. fs.values = fs.config.init.map(item => {
  221. if(typeof item == 'object') {
  222. return item;
  223. }
  224. return {
  225. name: othis.find(`option[value="${item}"]`).text(),
  226. value: item
  227. }
  228. }).filter(item => {
  229. return item.name;
  230. });
  231. fs.config.init = fs.values.concat([]);
  232. }else{
  233. fs.config.init = value.concat([]);
  234. }
  235. !fs.values && (fs.values = []);
  236. data[id] = fs;
  237. //先取消layui对select的渲染
  238. hasLayuiRender[0] && hasLayuiRender.remove();
  239. hasRender[0] && hasRender.remove();
  240. //构造渲染div
  241. let dinfo = this.renderSelect(id, fs.config.placeholder, select);
  242. let heightStyle = !fs.config.height || fs.config.height == 'auto' ? '' : `xm-hg style="height: 34px;"`;
  243. let inputHtml = [
  244. `<div class="${LABEL}">`,
  245. `<input type="text" fsw class="${FORM_INPUT} ${INPUT}" ${fs.config.isSearch ? '' : 'style="display: none;"'} autocomplete="off" debounce="0" />`,
  246. `</div>`
  247. ];
  248. let reElem =
  249. $(`<div class="${FORM_SELECT}" ${SKIN}="${fs.config.skin}">
  250. <input class="${HIDE_INPUT}" value="" name="${fs.config.formname}" lay-verify="${fs.config.layverify}" lay-verType="${fs.config.layverType}" type="text" style="position: absolute;bottom: 0; z-index: -1;width: 100%; height: 100%; border: none; opacity: 0;"/>
  251. <div class="${FORM_TITLE} ${fs.config.disabled ? DIS : ''}">
  252. <div class="${FORM_INPUT} ${NAME}" ${heightStyle}>
  253. ${inputHtml.join('')}
  254. <i class="${SANJIAO}"></i>
  255. </div>
  256. <div class="${TDIV}">
  257. <input type="text" autocomplete="off" placeholder="${fs.config.placeholder}" readonly="readonly" unselectable="on" class="${FORM_INPUT}">
  258. </div>
  259. <div></div>
  260. </div>
  261. <dl xid="${id}" class="${DL} ${fs.config.radio ? RADIO:''}">${dinfo}</dl>
  262. </div>`);
  263. var $parent = $(`<div class="${PNAME}" FS_ID="${id}"></div>`);
  264. $parent.append(reElem)
  265. othis.after($parent);
  266. othis.attr('lay-ignore', '');
  267. othis.removeAttr('name') && othis.attr('_name', fs.config.formname);
  268. othis.removeAttr('lay-verify') && othis.attr('_lay-verify', fs.config.layverify);
  269. //如果可搜索, 加上事件
  270. if(fs.config.isSearch){
  271. ajaxs[id] = $.extend({}, ajax, {searchUrl: fs.config.searchUrl}, ajaxs[id]);
  272. $(document).on('input', `div.${PNAME}[FS_ID="${id}"] .${INPUT}`, (e) => {
  273. this.search(id, e, fs.config.searchUrl);
  274. });
  275. if(fs.config.searchUrl){//触发第一次请求事件
  276. this.triggerSearch(reElem, true);
  277. }
  278. }else{//隐藏第二个dl
  279. reElem.find(`dl dd.${FORM_DL_INPUT}`).css('display', 'none');
  280. }
  281. });
  282. }
  283. Common.prototype.search = function(id, e, searchUrl, call){
  284. let input;
  285. if(call){
  286. input = call;
  287. }else{
  288. input = e.target;
  289. let keyCode = e.keyCode;
  290. if(keyCode === 9 || keyCode === 13 || keyCode === 37 || keyCode === 38 || keyCode === 39 || keyCode === 40) {
  291. return false;
  292. }
  293. }
  294. let inputValue = $.trim(input.value);
  295. //过滤一下tips
  296. this.changePlaceHolder($(input));
  297. let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax;
  298. searchUrl = ajaxConfig.searchUrl || searchUrl;
  299. let fs = data[id],
  300. isCreate = fs.config.isCreate,
  301. reElem = $(`dl[xid="${id}"]`).parents(`.${FORM_SELECT}`);
  302. //如果开启了远程搜索
  303. if(searchUrl){
  304. if(ajaxConfig.searchVal){
  305. inputValue = ajaxConfig.searchVal;
  306. ajaxConfig.searchVal = '';
  307. }
  308. if(!ajaxConfig.beforeSearch || (ajaxConfig.beforeSearch && ajaxConfig.beforeSearch instanceof Function && ajaxConfig.beforeSearch(id, searchUrl, inputValue))){
  309. let delay = ajaxConfig.delay;
  310. if(ajaxConfig.first){
  311. ajaxConfig.first = false;
  312. delay = 10;
  313. }
  314. clearTimeout(fs.clearid);
  315. fs.clearid = setTimeout(() => {
  316. reElem.find(`dl > *:not(.${FORM_SELECT_TIPS})`).remove();
  317. reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text('请求中');
  318. this.ajax(id, searchUrl, inputValue, false, null, true);
  319. }, delay);
  320. }
  321. }else{
  322. reElem.find(`dl .${DD_HIDE}`).removeClass(DD_HIDE);
  323. //遍历选项, 选择可以显示的值
  324. reElem.find(`dl dd:not(.${FORM_SELECT_TIPS})`).each((idx, item) => {
  325. let _item = $(item);
  326. let searchFun = events.filter[id] || data[id].config.filter;
  327. if(searchFun && searchFun(id, inputValue, this.getItem(id, _item), _item.hasClass(DISABLED)) == true){
  328. _item.addClass(DD_HIDE);
  329. }
  330. });
  331. //控制分组名称
  332. reElem.find('dl dt').each((index, item) => {
  333. if(!$(item).nextUntil('dt', `:not(.${DD_HIDE})`).length) {
  334. $(item).addClass(DD_HIDE);
  335. }
  336. });
  337. //动态创建
  338. this.create(id, isCreate, inputValue);
  339. let shows = reElem.find(`dl dd:not(.${FORM_SELECT_TIPS}):not(.${DD_HIDE})`);
  340. if(!shows.length){
  341. reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text('无匹配项');
  342. }else{
  343. reElem.find(`dd.${FORM_NONE}`).removeClass(FORM_EMPTY);
  344. }
  345. }
  346. }
  347. Common.prototype.isArray = function(obj){
  348. return Object.prototype.toString.call(obj) == "[object Array]";
  349. }
  350. Common.prototype.triggerSearch = function(div, isCall){
  351. (div ? [div] : $(`.${FORM_SELECT}`).toArray()).forEach((reElem, index) => {
  352. reElem = $(reElem);
  353. let id = reElem.find('dl').attr('xid')
  354. if((id && data[id] && data[id].config.isEmpty) || isCall){
  355. this.search(id, null, null, data[id].config.searchType == 0 ? reElem.find(`.${LABEL} .${INPUT}`) : reElem.find(`dl .${FORM_DL_INPUT} .${INPUT}`));
  356. }
  357. });
  358. }
  359. Common.prototype.clearInput = function(id){
  360. let div = $(`.${PNAME}[fs_id="${id}"]`);
  361. let input = data[id].config.searchType == 0 ? div.find(`.${LABEL} .${INPUT}`) : div.find(`dl .${FORM_DL_INPUT} .${INPUT}`);
  362. input.val('');
  363. }
  364. Common.prototype.ajax = function(id, searchUrl, inputValue, isLinkage, linkageWidth, isSearch, successCallback, isReplace){
  365. let reElem = $(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`);
  366. if(!reElem[0] || !searchUrl){
  367. return ;
  368. }
  369. let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax;
  370. let ajaxData = $.extend(true, {}, ajaxConfig.data);
  371. ajaxData[ajaxConfig.searchName] = inputValue;
  372. //是否需要对ajax添加随机时间
  373. //ajaxData['_'] = Date.now();
  374. $.ajax({
  375. type: ajaxConfig.type,
  376. headers: ajaxConfig.header,
  377. url: searchUrl,
  378. data: ajaxConfig.dataType == 'json' ? JSON.stringify(ajaxData) : ajaxData,
  379. success: (res) => {
  380. if(typeof res == 'string'){
  381. res = JSON.parse(res);
  382. }
  383. ajaxConfig.beforeSuccess && ajaxConfig.beforeSuccess instanceof Function && (res = ajaxConfig.beforeSuccess(id, searchUrl, inputValue, res));
  384. if(this.isArray(res)){
  385. let newRes = {};
  386. newRes[ajaxConfig.response.statusName] = ajaxConfig.response.statusCode;
  387. newRes[ajaxConfig.response.msgName] = "";
  388. newRes[ajaxConfig.response.dataName] = res;
  389. res = newRes;
  390. }
  391. if(res[ajaxConfig.response.statusName] != ajaxConfig.response.statusCode) {
  392. reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text(res[ajaxConfig.response.msgName]);
  393. }else{
  394. reElem.find(`dd.${FORM_NONE}`).removeClass(FORM_EMPTY);
  395. this.renderData(id, res[ajaxConfig.response.dataName], isLinkage, linkageWidth, isSearch, isReplace);
  396. data[id].config.isEmpty = res[ajaxConfig.response.dataName].length == 0;
  397. }
  398. successCallback && successCallback(id);
  399. ajaxConfig.success && ajaxConfig.success instanceof Function && ajaxConfig.success(id, searchUrl, inputValue, res);
  400. },
  401. error: (err) => {
  402. reElem.find(`dd[lay-value]:not(.${FORM_SELECT_TIPS})`).remove();
  403. reElem.find(`dd.${FORM_NONE}`).addClass(FORM_EMPTY).text('服务异常');
  404. ajaxConfig.error && ajaxConfig.error instanceof Function && ajaxConfig.error(id, searchUrl, inputValue, err);
  405. }
  406. });
  407. }
  408. Common.prototype.renderData = function(id, dataArr, linkage, linkageWidth, isSearch, isReplace){
  409. if(linkage){//渲染多级联动
  410. this.renderLinkage(id, dataArr, linkageWidth);
  411. return;
  412. }
  413. if(isReplace){
  414. this.renderReplace(id, dataArr);
  415. return;
  416. }
  417. let reElem = $(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`);
  418. let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax;
  419. let pcInput = reElem.find(`.${TDIV} input`);
  420. dataArr = this.exchangeData(id, dataArr);
  421. let values = [];
  422. reElem.find('dl').html(this.renderSelect(id, pcInput.attr('placeholder') || pcInput.attr('back'), dataArr.map((item) => {
  423. let itemVal = $.extend({}, item, {
  424. innerHTML: item[ajaxConfig.keyName],
  425. value: item[ajaxConfig.keyVal],
  426. sel: item[ajaxConfig.keySel],
  427. disabled: item[ajaxConfig.keyDis],
  428. type: item.type,
  429. name: item[ajaxConfig.keyName]
  430. });
  431. if(itemVal.sel){
  432. values.push(itemVal);
  433. }
  434. return itemVal;
  435. })));
  436. let label = reElem.find(`.${LABEL}`);
  437. let dl = reElem.find('dl[xid]');
  438. if(isSearch){//如果是远程搜索, 这里需要判重
  439. let oldVal = data[id].values;
  440. oldVal.forEach((item, index) => {
  441. dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS);
  442. });
  443. values.forEach((item, index) => {
  444. if(this.indexOf(oldVal, item) == -1){
  445. this.addLabel(id, label, item);
  446. dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS);
  447. oldVal.push(item);
  448. }
  449. });
  450. }else{
  451. values.forEach((item, index) => {
  452. this.addLabel(id, label, item);
  453. dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS);
  454. });
  455. data[id].values = values;
  456. }
  457. this.commonHandler(id, label);
  458. }
  459. Common.prototype.renderLinkage = function(id, dataArr, linkageWidth){
  460. let result = [],
  461. index = 0,
  462. temp = {"0": dataArr},
  463. ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax;
  464. db[id] = {};
  465. do{
  466. let group = result[index ++] = [],
  467. _temp = temp;
  468. temp = {};
  469. $.each(_temp, (pid, arr) => {
  470. $.each(arr, (idx, item) => {
  471. let val = {
  472. pid: pid,
  473. name: item[ajaxConfig.keyName],
  474. value: item[ajaxConfig.keyVal],
  475. };
  476. db[id][val.value] = $.extend(item, val);
  477. group.push(val);
  478. let children = item[ajaxConfig.keyChildren];
  479. if(children && children.length){
  480. temp[val.value] = children;
  481. }
  482. });
  483. });
  484. }while(Object.getOwnPropertyNames(temp).length);
  485. let reElem = $(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`);
  486. let html = ['<div class="xm-select-linkage">'];
  487. $.each(result, (idx, arr) => {
  488. let groupDiv = [`<div style="left: ${(linkageWidth-0) * idx}px;" class="xm-select-linkage-group xm-select-linkage-group${idx + 1} ${idx != 0 ? 'xm-select-linkage-hide':''}">`];
  489. $.each(arr, (idx2, item) => {
  490. let span = `<li title="${item.name}" pid="${item.pid}" xm-value="${item.value}"><span>${item.name}</span></li>`;
  491. groupDiv.push(span);
  492. });
  493. groupDiv.push(`</div>`);
  494. html = html.concat(groupDiv);
  495. });
  496. html.push('<div style="clear: both; height: 288px;"></div>');
  497. html.push('</div>');
  498. reElem.find('dl').html(html.join(''));
  499. reElem.find(`.${INPUT}`).css('display', 'none');//联动暂时不支持搜索
  500. }
  501. Common.prototype.renderReplace = function(id, dataArr){
  502. let dl = $(`.${PNAME} dl[xid="${id}"]`);
  503. let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax;
  504. dataArr = this.exchangeData(id, dataArr);
  505. db[id] = dataArr;
  506. let html = dataArr.map((item) => {
  507. let itemVal = $.extend({}, item, {
  508. innerHTML: item[ajaxConfig.keyName],
  509. value: item[ajaxConfig.keyVal],
  510. sel: item[ajaxConfig.keySel],
  511. disabled: item[ajaxConfig.keyDis],
  512. type: item.type,
  513. name: item[ajaxConfig.keyName]
  514. });
  515. return this.createDD(id, itemVal);
  516. }).join('');
  517. dl.find(`dd:not(.${FORM_SELECT_TIPS}),dt:not([style])`).remove();
  518. dl.find(`dt[style]`).after($(html));
  519. }
  520. Common.prototype.exchangeData = function(id, arr){//这里处理树形结构
  521. let ajaxConfig = ajaxs[id] ? ajaxs[id] : ajax;
  522. let childrenName = ajaxConfig['keyChildren'];
  523. let disabledName = ajaxConfig['keyDis'];
  524. db[id] = {};
  525. let result = this.getChildrenList(arr, childrenName, disabledName, [], false);
  526. return result;
  527. }
  528. Common.prototype.getChildrenList = function(arr, childrenName, disabledName, pid, disabled){
  529. let result = [], offset = 0;
  530. for(let a = 0; a < arr.length; a ++){
  531. let item = arr[a];
  532. if(item.type && item.type == 'optgroup'){
  533. result.push(item);
  534. continue;
  535. }else{
  536. offset ++;
  537. }
  538. let parentIds = pid.concat([]);
  539. parentIds.push(`${offset - 1}_E`);
  540. item[FORM_TEAM_PID] = JSON.stringify(parentIds);
  541. item[disabledName] = item[disabledName] || disabled;
  542. result.push(item);
  543. let child = item[childrenName];
  544. if(child && common.isArray(child) && child.length){
  545. item['XM_TREE_FOLDER'] = true;
  546. let pidArr = parentIds.concat([]);
  547. let childResult = this.getChildrenList(child, childrenName, disabledName, pidArr, item[disabledName]);
  548. result = result.concat(childResult);
  549. }
  550. }
  551. return result;
  552. }
  553. Common.prototype.create = function(id, isCreate, inputValue){
  554. if(isCreate && inputValue){
  555. let fs = data[id],
  556. dl = $(`[xid="${id}"]`),
  557. tips= dl.find(`dd.${FORM_SELECT_TIPS}.${FORM_DL_INPUT}`),
  558. tdd = null,
  559. temp = dl.find(`dd.${TEMP}`);
  560. dl.find(`dd:not(.${FORM_SELECT_TIPS}):not(.${TEMP})`).each((index, item) => {
  561. if(inputValue == $(item).find('span').attr('name')){
  562. tdd = item;
  563. }
  564. });
  565. if(!tdd){//如果不存在, 则创建
  566. let val = fs.config.create(id, inputValue);
  567. if(temp[0]){
  568. temp.attr('lay-value', val);
  569. temp.find('span').text(inputValue);
  570. temp.find('span').attr("name", inputValue);
  571. temp.removeClass(DD_HIDE);
  572. }else{
  573. tips.after($(this.createDD(id, {
  574. name: inputValue,
  575. innerHTML: inputValue,
  576. value: val
  577. }, `${TEMP} ${CREATE_LONG}`)));
  578. }
  579. }
  580. }else{
  581. $(`[xid=${id}] dd.${TEMP}`).remove();
  582. }
  583. }
  584. Common.prototype.createDD = function(id, item, clz){
  585. let name = $.trim(item.innerHTML);
  586. db[id][item.value] = $(item).is('option') ? {name: name, value: item.value} : item;
  587. let template = data[id].config.template(name);
  588. let pid = item[FORM_TEAM_PID];
  589. pid ? (pid = JSON.parse(pid)) : (pid = [-1]);
  590. let attr = pid[0] == -1 ? '' : `tree-id="${pid.join('-')}" tree-folder="${!!item['XM_TREE_FOLDER']}"`;
  591. return `<dd lay-value="${item.value}" class="${item.disabled ? DISABLED : ''} ${clz ? clz : ''}" ${attr}>
  592. <div class="xm-unselect xm-form-checkbox ${item.disabled ? DISABLED : ''}" style="margin-left: ${(pid.length - 1) * 30}px">
  593. <i class="${CHECKBOX_YES}"></i>
  594. <span name="${name}">${template}</span>
  595. </div>
  596. </dd>`;
  597. }
  598. Common.prototype.createQuickBtn = function(obj, right){
  599. return `<div class="${CZ}" method="${obj.name}" title="${obj.name}" ${right ? 'style="margin-right: ' + right + '"': ''}><i class="${obj.icon}"></i><span>${obj.name}</span></div>`
  600. }
  601. Common.prototype.renderBtns = function(id, show, right){
  602. let quickBtn = [];
  603. let dl = $(`dl[xid="${id}"]`);
  604. quickBtn.push(`<div class="${CZ_GROUP}" show="${show}" style="max-width: ${dl.prev().width() - 54}px;">`);
  605. $.each(data[id].config.btns, (index, item) => {
  606. quickBtn.push(this.createQuickBtn(item, right));
  607. });
  608. quickBtn.push(`</div>`);
  609. quickBtn.push(this.createQuickBtn({icon: 'xm-iconfont icon-caidan', name: ''}));
  610. return quickBtn.join('');
  611. }
  612. Common.prototype.renderSelect = function(id, tips, select){
  613. db[id] = {};
  614. let arr = [];
  615. if(data[id].config.btns.length){
  616. setTimeout(() => {
  617. let dl = $(`dl[xid="${id}"]`);
  618. dl.parents(`.${FORM_SELECT}`).attr(SEARCH_TYPE, data[id].config.searchType);
  619. dl.find(`.${CZ_GROUP}`).css('max-width', `${dl.prev().width() - 54}px`);
  620. }, 10)
  621. arr.push([
  622. `<dd lay-value="" class="${FORM_SELECT_TIPS}" style="background-color: #FFF!important;">`,
  623. this.renderBtns(id, null, '30px'),
  624. `</dd>`,
  625. `<dd lay-value="" class="${FORM_SELECT_TIPS} ${FORM_DL_INPUT}" style="background-color: #FFF!important;">`,
  626. `<i class="xm-iconfont icon-sousuo"></i>`,
  627. `<input type="text" class="${FORM_INPUT} ${INPUT}" placeholder="请搜索"/>`,
  628. `</dd>`
  629. ].join(''));
  630. }else{
  631. arr.push(`<dd lay-value="" class="${FORM_SELECT_TIPS}">${tips}</dd>`);
  632. }
  633. if(this.isArray(select)){
  634. $(select).each((index, item) => {
  635. if(item){
  636. if(item.type && item.type === 'optgroup') {
  637. arr.push(`<dt>${item.name}</dt>`);
  638. } else {
  639. arr.push(this.createDD(id, item));
  640. }
  641. }
  642. });
  643. }else{
  644. $(select).find('*').each((index, item) => {
  645. if(item.tagName.toLowerCase() == 'option' && index == 0 && !item.value){
  646. return ;
  647. }
  648. if(item.tagName.toLowerCase() === 'optgroup') {
  649. arr.push(`<dt>${item.label}</dt>`);
  650. } else {
  651. arr.push(this.createDD(id, item));
  652. }
  653. });
  654. }
  655. arr.push('<dt style="display:none;"> </dt>');
  656. arr.push(`<dd class="${FORM_SELECT_TIPS} ${FORM_NONE} ${arr.length === 2 ? FORM_EMPTY:''}">没有选项</dd>`);
  657. return arr.join('');
  658. }
  659. Common.prototype.on = function(){//事件绑定
  660. this.one();
  661. $(document).on('click', (e) => {
  662. if(!$(e.target).parents(`.${FORM_TITLE}`)[0]){//清空input中的值
  663. $(`.${PNAME} dl .${DD_HIDE}`).removeClass(DD_HIDE);
  664. $(`.${PNAME} dl dd.${FORM_EMPTY}`).removeClass(FORM_EMPTY);
  665. $(`.${PNAME} dl dd.${TEMP}`).remove();
  666. $.each(data, (key, fs) => {
  667. this.clearInput(key);
  668. if(!fs.values.length){
  669. this.changePlaceHolder($(`div[FS_ID="${key}"] .${LABEL}`));
  670. }
  671. });
  672. }
  673. $(`.${PNAME} .${FORM_SELECTED}`).each((index, item) => {
  674. this.changeShow($(item).find(`.${FORM_TITLE}`), false);
  675. }) ;
  676. });
  677. }
  678. Common.prototype.calcLabelLeft = function(label, w, call){
  679. let pos = this.getPosition(label[0]);
  680. pos.y = pos.x + label[0].clientWidth;
  681. let left = label[0].offsetLeft;
  682. if(!label.find('span').length){
  683. left = 0;
  684. }else if(call){//校正归位
  685. let span = label.find('span:last');
  686. span.css('display') == 'none' ? (span = span.prev()[0]) : (span = span[0]);
  687. let spos = this.getPosition(span);
  688. spos.y = spos.x + span.clientWidth;
  689. if(spos.y > pos.y){
  690. left = left - (spos.y - pos.y) - 5;
  691. }else{
  692. left = 0;
  693. }
  694. }else{
  695. if(w < 0){
  696. let span = label.find(':last');
  697. span.css('display') == 'none' ? (span = span.prev()[0]) : (span = span[0]);
  698. let spos = this.getPosition(span);
  699. spos.y = spos.x + span.clientWidth;
  700. if(spos.y > pos.y){
  701. left -= 10;
  702. }
  703. }else{
  704. if(left < 0){
  705. left += 10;
  706. }
  707. if(left > 0){
  708. left = 0;
  709. }
  710. }
  711. }
  712. label.css('left', left + 'px');
  713. }
  714. Common.prototype.one = function(target){//一次性事件绑定
  715. $(target ? target : document).off('click', `.${FORM_TITLE}`).on('click', `.${FORM_TITLE}`, (e) => {
  716. let othis = $(e.target),
  717. title = othis.is(FORM_TITLE) ? othis : othis.parents(`.${FORM_TITLE}`),
  718. dl = title.next(),
  719. id = dl.attr('xid');
  720. //清空非本select的input val
  721. $(`dl[xid]`).not(dl).each((index, item) => {
  722. this.clearInput($(item).attr('xid'));
  723. });
  724. $(`dl[xid]`).not(dl).find(`dd.${DD_HIDE}`).removeClass(DD_HIDE);
  725. //如果是disabled select
  726. if(title.hasClass(DIS)){
  727. return false;
  728. }
  729. //如果点击的是右边的三角或者只读的input
  730. if(othis.is(`.${SANJIAO}`) || othis.is(`.${INPUT}[readonly]`)){
  731. this.changeShow(title, !title.parents(`.${FORM_SELECT}`).hasClass(FORM_SELECTED));
  732. return false;
  733. }
  734. //如果点击的是input的右边, focus一下
  735. if(title.find(`.${INPUT}:not(readonly)`)[0]){
  736. let input = title.find(`.${INPUT}`),
  737. epos = {x: e.pageX, y: e.pageY},
  738. pos = this.getPosition(title[0]),
  739. width = title.width();
  740. while(epos.x > pos.x){
  741. if($(document.elementFromPoint(epos.x, epos.y)).is(input)){
  742. input.focus();
  743. this.changeShow(title, true);
  744. return false;
  745. }
  746. epos.x -= 50;
  747. }
  748. }
  749. //如果点击的是可搜索的input
  750. if(othis.is(`.${INPUT}`)){
  751. this.changeShow(title, true);
  752. return false;
  753. }
  754. //如果点击的是x按钮
  755. if(othis.is(`i[fsw="${NAME}"]`)){
  756. let val = this.getItem(id, othis),
  757. dd = dl.find(`dd[lay-value='${val.value}']`);
  758. if(dd.hasClass(DISABLED)){//如果是disabled状态, 不可选, 不可删
  759. return false;
  760. }
  761. this.handlerLabel(id, dd, false, val);
  762. return false;
  763. }
  764. this.changeShow(title, !title.parents(`.${FORM_SELECT}`).hasClass(FORM_SELECTED));
  765. return false;
  766. });
  767. $(target ? target : document).off('click', `dl.${DL}`).on('click', `dl.${DL}`, (e) => {
  768. let othis = $(e.target);
  769. if(othis.is(`.${LINKAGE}`) || othis.parents(`.${LINKAGE}`)[0]){//linkage的处理
  770. othis = othis.is('li') ? othis : othis.parents('li');
  771. let group = othis.parents('.xm-select-linkage-group'),
  772. id = othis.parents('dl').attr('xid');
  773. if(!id){
  774. return false;
  775. }
  776. //激活li
  777. group.find('.xm-select-active').removeClass('xm-select-active');
  778. othis.addClass('xm-select-active');
  779. //激活下一个group, 激活前显示对应数据
  780. group.nextAll('.xm-select-linkage-group').addClass('xm-select-linkage-hide');
  781. let nextGroup = group.next('.xm-select-linkage-group');
  782. nextGroup.find('li').addClass('xm-select-linkage-hide');
  783. nextGroup.find(`li[pid="${othis.attr('xm-value')}"]`).removeClass('xm-select-linkage-hide');
  784. //如果没有下一个group, 或没有对应的值
  785. if(!nextGroup[0] || nextGroup.find(`li:not(.xm-select-linkage-hide)`).length == 0){
  786. let vals = [],
  787. index = 0,
  788. isAdd = !othis.hasClass('xm-select-this');
  789. if(data[id].config.radio){
  790. othis.parents('.xm-select-linkage').find('.xm-select-this').removeClass('xm-select-this');
  791. }
  792. do{
  793. vals[index ++] = {
  794. name: othis.find('span').text(),
  795. value: othis.attr('xm-value')
  796. }
  797. othis = othis.parents('.xm-select-linkage-group').prev().find(`li[xm-value="${othis.attr('pid')}"]`);
  798. }while(othis.length);
  799. vals.reverse();
  800. let val = {
  801. name: vals.map((item) => {
  802. return item.name;
  803. }).join('/'),
  804. value: vals.map((item) => {
  805. return item.value;
  806. }).join('/'),
  807. }
  808. this.handlerLabel(id, null, isAdd, val);
  809. }else{
  810. nextGroup.removeClass('xm-select-linkage-hide');
  811. }
  812. return false;
  813. }
  814. if(othis.is('dl')){
  815. return false;
  816. }
  817. if(othis.is('dt')){
  818. othis.nextUntil(`dt`).each((index, item) => {
  819. item = $(item);
  820. if(item.hasClass(DISABLED) || item.hasClass(THIS)){
  821. }else{
  822. item.find('i:not(.icon-expand)').click();
  823. }
  824. });
  825. return false;
  826. }
  827. let dd = othis.is('dd') ? othis : othis.parents('dd');
  828. let id = dd.parent('dl').attr('xid');
  829. if(dd.hasClass(DISABLED)){//被禁用选项的处理
  830. return false;
  831. }
  832. //菜单功效
  833. if(othis.is('i.icon-caidan')){
  834. let opens = [], closes = [];
  835. othis.parents('dl').find('dd[tree-folder="true"]').each((index, item) => {
  836. $(item).attr('xm-tree-hidn') == undefined ? opens.push(item) : closes.push(item);
  837. });
  838. let arr = closes.length ? closes : opens;
  839. arr.forEach(item => item.click());
  840. return false;
  841. }
  842. //树状结构的选择
  843. let treeId = dd.attr('tree-id');
  844. if(treeId){
  845. //忽略右边的图标
  846. if(othis.is('i:not(.icon-expand)')){
  847. this.handlerLabel(id, dd, !dd.hasClass(THIS));
  848. return false;
  849. }
  850. let ajaxConfig = ajaxs[id] || ajax;
  851. let treeConfig = ajaxConfig.tree;
  852. let childrens = dd.nextAll(`dd[tree-id^="${treeId}"]`);
  853. if(childrens && childrens.length){
  854. let len = childrens[0].clientHeight;
  855. len ? (
  856. this.addTreeHeight(dd, len),
  857. len = 0
  858. ) : (
  859. len = dd.attr('xm-tree-hidn') || 36,
  860. dd.removeAttr('xm-tree-hidn'),
  861. dd.find('>i').remove(),
  862. (childrens = childrens.filter((index, item) => $(item).attr('tree-id').split('-').length - 1 == treeId.split('-').length))
  863. );
  864. childrens.animate({
  865. height: len
  866. }, 150)
  867. return false;
  868. }else{
  869. if(treeConfig.nextClick && treeConfig.nextClick instanceof Function){
  870. treeConfig.nextClick(id, this.getItem(id, dd), (res) => {
  871. if(!res || !res.length){
  872. this.handlerLabel(id, dd, !dd.hasClass(THIS));
  873. }else{
  874. dd.attr('tree-folder', 'true');
  875. let ddChilds = [];
  876. res.forEach((item, idx) => {
  877. item.innerHTML = item[ajaxConfig.keyName];
  878. item[FORM_TEAM_PID] = JSON.stringify(treeId.split('-').concat([idx]));
  879. ddChilds.push(this.createDD(id, item));
  880. db[id][item[ajaxConfig.keyVal]] = item;
  881. });
  882. dd.after(ddChilds.join(''));
  883. }
  884. });
  885. return false;
  886. }
  887. }
  888. }
  889. if(dd.hasClass(FORM_SELECT_TIPS)){//tips的处理
  890. let btn = othis.is(`.${CZ}`) ? othis : othis.parents(`.${CZ}`);
  891. if(!btn[0]){
  892. return false;
  893. }
  894. let method = btn.attr('method');
  895. let obj = data[id].config.btns.filter(bean => bean.name == method)[0];
  896. obj && obj.click && obj.click instanceof Function && obj.click(id, this);
  897. return false;
  898. }
  899. this.handlerLabel(id, dd, !dd.hasClass(THIS));
  900. return false;
  901. });
  902. }
  903. Common.prototype.addTreeHeight = function(dd, len){
  904. let treeId = dd.attr('tree-id');
  905. let childrens = dd.nextAll(`dd[tree-id^="${treeId}"]`);
  906. if(childrens.length){
  907. dd.append('<i class="xm-iconfont icon-expand"></i>');
  908. dd.attr('xm-tree-hidn', len);
  909. childrens.each((index, item) => {
  910. let that = $(item);
  911. this.addTreeHeight(that, len);
  912. })
  913. }
  914. }
  915. let db = {};
  916. Common.prototype.getItem = function(id, value){
  917. if(value instanceof $){
  918. if(value.is(`i[fsw="${NAME}"]`)){
  919. let span = value.parent();
  920. return db[id][value] || {
  921. name: span.find('font').text(),
  922. value: span.attr('value')
  923. }
  924. }
  925. let val = value.attr('lay-value');
  926. return !db[id][val] ? (db[id][val] = {
  927. name: value.find('span[name]').attr('name'),
  928. value: val
  929. }) : db[id][val];
  930. }else if(typeof(value) == 'string' && value.indexOf('/') != -1){
  931. return db[id][value] || {
  932. name: this.valToName(id, value),
  933. value: value
  934. }
  935. }
  936. return db[id][value];
  937. }
  938. Common.prototype.linkageAdd = function(id, val){
  939. let dl = $(`dl[xid="${id}"]`);
  940. dl.find('.xm-select-active').removeClass('xm-select-active');
  941. let vs = val.value.split('/');
  942. let pid, li, index = 0;
  943. let lis = [];
  944. do{
  945. pid = vs[index];
  946. li = dl.find(`.xm-select-linkage-group${index + 1} li[xm-value="${pid}"]`);
  947. li[0] && lis.push(li);
  948. index ++;
  949. }while(li.length && pid != undefined);
  950. if(lis.length == vs.length){
  951. $.each(lis, (idx, item) => {
  952. item.addClass('xm-select-this');
  953. });
  954. }
  955. }
  956. Common.prototype.linkageDel = function(id, val){
  957. let dl = $(`dl[xid="${id}"]`);
  958. let vs = val.value.split('/');
  959. let pid, li, index = vs.length - 1;
  960. do{
  961. pid = vs[index];
  962. li = dl.find(`.xm-select-linkage-group${index + 1} li[xm-value="${pid}"]`);
  963. if(!li.parent().next().find(`li[pid=${pid}].xm-select-this`).length){
  964. li.removeClass('xm-select-this');
  965. }
  966. index --;
  967. }while(li.length && pid != undefined);
  968. }
  969. Common.prototype.valToName = function(id, val){
  970. let dl = $(`dl[xid="${id}"]`);
  971. let vs = (val + "").split('/');
  972. if(!vs.length){
  973. return null;
  974. }
  975. let names = [];
  976. $.each(vs, (idx, item) => {
  977. let name = dl.find(`.xm-select-linkage-group${idx + 1} li[xm-value="${item}"] span`).text();
  978. names.push(name);
  979. });
  980. return names.length == vs.length ? names.join('/') : null;
  981. }
  982. Common.prototype.commonHandler = function(key, label){
  983. if(!label || !label[0]){
  984. return ;
  985. }
  986. this.checkHideSpan(key, label);
  987. //计算input的提示语
  988. this.changePlaceHolder(label);
  989. //计算高度
  990. this.retop(label.parents(`.${FORM_SELECT}`));
  991. this.calcLabelLeft(label, 0, true);
  992. //表单默认值
  993. this.setHidnVal(key, label);
  994. //title值
  995. label.parents(`.${FORM_TITLE} .${NAME}`).attr('title', data[key].values.map((val) => {
  996. return val.name;
  997. }).join(','));
  998. }
  999. Common.prototype.initVal = function(id){
  1000. let target = {};
  1001. if(id){
  1002. target[id] = data[id];
  1003. }else{
  1004. target = data;
  1005. }
  1006. $.each(target, (key, val) => {
  1007. let values = val.values,
  1008. div = $(`dl[xid="${key}"]`).parent(),
  1009. label = div.find(`.${LABEL}`),
  1010. dl = div.find('dl');
  1011. dl.find(`dd.${THIS}`).removeClass(THIS);
  1012. let _vals = values.concat([]);
  1013. _vals.concat([]).forEach((item, index) => {
  1014. this.addLabel(key, label, item);
  1015. dl.find(`dd[lay-value="${item.value}"]`).addClass(THIS);
  1016. });
  1017. if(val.config.radio){
  1018. _vals.length && values.push(_vals[_vals.length - 1]);
  1019. }
  1020. this.commonHandler(key, label);
  1021. });
  1022. }
  1023. Common.prototype.setHidnVal = function(key, label) {
  1024. if(!label || !label[0]) {
  1025. return;
  1026. }
  1027. label.parents(`.${PNAME}`).find(`.${HIDE_INPUT}`).val(data[key].values.map((val) => {
  1028. return val.value;
  1029. }).join(','));
  1030. }
  1031. Common.prototype.handlerLabel = function(id, dd, isAdd, oval, notOn){
  1032. let div = $(`[xid="${id}"]`).prev().find(`.${LABEL}`),
  1033. val = dd && this.getItem(id, dd),
  1034. vals = data[id].values,
  1035. on = data[id].config.on || events.on[id],
  1036. endOn = data[id].config.endOn || events.endOn[id];
  1037. if(oval){
  1038. val = oval;
  1039. }
  1040. let fs = data[id];
  1041. if(isAdd && fs.config.max && fs.values.length >= fs.config.max){
  1042. let maxTipsFun = events.maxTips[id] || data[id].config.maxTips;
  1043. maxTipsFun && maxTipsFun(id, vals.concat([]), val, fs.config.max);
  1044. return ;
  1045. }
  1046. if(!notOn){
  1047. if(on && on instanceof Function && on(id, vals.concat([]), val, isAdd, dd && dd.hasClass(DISABLED)) == false) {
  1048. return ;
  1049. }
  1050. }
  1051. let dl = $(`dl[xid="${id}"]`);
  1052. isAdd ? (
  1053. (dd && dd[0] ? (
  1054. dd.addClass(THIS),
  1055. dd.removeClass(TEMP)
  1056. ) : (
  1057. dl.find('.xm-select-linkage')[0] && this.linkageAdd(id, val)
  1058. )),
  1059. this.addLabel(id, div, val),
  1060. vals.push(val)
  1061. ) : (
  1062. (dd && dd[0] ? (
  1063. dd.removeClass(THIS)
  1064. ) : (
  1065. dl.find('.xm-select-linkage')[0] && this.linkageDel(id, val)
  1066. )),
  1067. this.delLabel(id, div, val),
  1068. this.remove(vals, val)
  1069. );
  1070. if(!div[0]) return ;
  1071. //单选选完后直接关闭选择域
  1072. if(fs.config.radio){
  1073. this.changeShow(div, false);
  1074. }
  1075. //移除表单验证的红色边框
  1076. div.parents(`.${FORM_TITLE}`).prev().removeClass('layui-form-danger');
  1077. //清空搜索值
  1078. fs.config.clearInput && this.clearInput(id);
  1079. this.commonHandler(id, div);
  1080. !notOn && endOn && endOn instanceof Function && endOn(id, vals.concat([]), val, isAdd, dd && dd.hasClass(DISABLED));
  1081. }
  1082. Common.prototype.addLabel = function(id, div, val){
  1083. if(!val) return ;
  1084. let tips = `fsw="${NAME}"`;
  1085. let [$label, $close] = [
  1086. $(`<span ${tips} value="${val.value}"><font ${tips}>${val.name}</font></span>`),
  1087. $(`<i ${tips} class="xm-iconfont icon-close"></i>`)
  1088. ];
  1089. $label.append($close);
  1090. //如果是radio模式
  1091. let fs = data[id];
  1092. if(fs.config.radio){
  1093. fs.values.length = 0;
  1094. $(`dl[xid="${id}"]`).find(`dd.${THIS}:not([lay-value="${val.value}"])`).removeClass(THIS);
  1095. div.find('span').remove();
  1096. }
  1097. //如果是固定高度
  1098. div.find('input').css('width', '50px');
  1099. div.find('input').before($label);
  1100. }
  1101. Common.prototype.delLabel = function(id, div, val){
  1102. if(!val) return ;
  1103. div.find(`span[value="${val.value}"]:first`).remove();
  1104. }
  1105. Common.prototype.checkHideSpan = function(id, div){
  1106. let parentHeight = div.parents(`.${NAME}`)[0].offsetHeight + 5;
  1107. div.find('span.xm-span-hide').removeClass('xm-span-hide');
  1108. div.find('span[style]').remove();
  1109. let count = data[id].config.showCount;
  1110. div.find('span').each((index, item) => {
  1111. if(index >= count){
  1112. $(item).addClass('xm-span-hide');
  1113. }
  1114. });
  1115. let prefix = div.find(`span:eq(${count})`);
  1116. prefix[0] && prefix.before($(`<span style="padding-right: 6px;" fsw="${NAME}"> + ${div.find('span').length - count}</span>`))
  1117. }
  1118. Common.prototype.retop = function(div){//计算dl显示的位置
  1119. let dl = div.find('dl'),
  1120. top = div.offset().top + div.outerHeight() + 5 - $win.scrollTop(),
  1121. dlHeight = dl.outerHeight();
  1122. let up = div.hasClass('layui-form-selectup') || dl.css('top').indexOf('-') != -1 || (top + dlHeight > $win.height() && top >= dlHeight);
  1123. div = div.find(`.${NAME}`);
  1124. let fs = data[dl.attr('xid')];
  1125. let base = dl.parents('.layui-form-pane')[0] && dl.prev()[0].clientHeight > 38 ? 14 : 10;
  1126. if((fs && fs.config.direction == 'up') || up){
  1127. up = true;
  1128. if((fs && fs.config.direction == 'down')){
  1129. up = false;
  1130. }
  1131. }
  1132. let reHeight = div[0].offsetTop + div.height() + base;
  1133. if(up) {
  1134. dl.css({
  1135. top: 'auto',
  1136. bottom: reHeight + 3 + 'px',
  1137. });
  1138. } else {
  1139. dl.css({
  1140. top: reHeight + 'px',
  1141. bottom: 'auto'
  1142. });
  1143. }
  1144. }
  1145. Common.prototype.changeShow = function(children, isShow){//显示于隐藏
  1146. $('.layui-form-selected').removeClass('layui-form-selected');
  1147. let top = children.parents(`.${FORM_SELECT}`),
  1148. realShow = top.hasClass(FORM_SELECTED),
  1149. id = top.find('dl').attr('xid');
  1150. $(`.${PNAME} .${FORM_SELECT}`).not(top).removeClass(FORM_SELECTED);
  1151. if(isShow){
  1152. this.retop(top);
  1153. top.addClass(FORM_SELECTED);
  1154. top.find(`.${INPUT}`).focus();
  1155. if(!top.find(`dl dd[lay-value]:not(.${FORM_SELECT_TIPS})`).length){
  1156. top.find(`dl .${FORM_NONE}`).addClass(FORM_EMPTY);
  1157. }
  1158. }else{
  1159. top.removeClass(FORM_SELECTED);
  1160. this.clearInput(id);
  1161. top.find(`dl .${FORM_EMPTY}`).removeClass(FORM_EMPTY);
  1162. top.find(`dl dd.${DD_HIDE}`).removeClass(DD_HIDE);
  1163. top.find(`dl dd.${TEMP}`).remove();
  1164. //计算ajax数据是否为空, 然后重新请求数据
  1165. if(id && data[id] && data[id].config.isEmpty){
  1166. this.triggerSearch(top);
  1167. }
  1168. this.changePlaceHolder(top.find(`.${LABEL}`));
  1169. }
  1170. if(isShow != realShow){
  1171. let openFun = data[id].config.opened || events.opened[id];
  1172. isShow && openFun && openFun instanceof Function && openFun(id);
  1173. let closeFun = data[id].config.closed || events.closed[id];
  1174. !isShow && closeFun && closeFun instanceof Function && closeFun(id);
  1175. }
  1176. }
  1177. Common.prototype.changePlaceHolder = function(div){//显示于隐藏提示语
  1178. //调整pane模式下的高度
  1179. let title = div.parents(`.${FORM_TITLE}`);
  1180. title[0] || (title = div.parents(`dl`).prev());
  1181. if(!title[0]){
  1182. return ;
  1183. }
  1184. let id = div.parents(`.${PNAME}`).find(`dl[xid]`).attr('xid');
  1185. if(data[id] && data[id].config.height){//既然固定高度了, 那就看着办吧
  1186. }else{
  1187. let height = title.find(`.${NAME}`)[0].clientHeight;
  1188. title.css('height' , (height > 36 ? height + 4 : height) + 'px');
  1189. //如果是layui pane模式, 处理label的高度
  1190. let label = title.parents(`.${PNAME}`).parent().prev();
  1191. if(label.is('.layui-form-label') && title.parents('.layui-form-pane')[0]){
  1192. height = height > 36 ? height + 4 : height;
  1193. title.css('height' , height + 'px');
  1194. label.css({
  1195. height: height + 2 + 'px',
  1196. lineHeight: (height - 18) + 'px'
  1197. })
  1198. }
  1199. }
  1200. let input = title.find(`.${TDIV} input`),
  1201. isShow = !div.find('span:last')[0] && !title.find(`.${INPUT}`).val();
  1202. if(isShow){
  1203. let ph = input.attr('back');
  1204. input.removeAttr('back');
  1205. input.attr('placeholder', ph);
  1206. }else{
  1207. let ph = input.attr('placeholder');
  1208. input.removeAttr('placeholder');
  1209. input.attr('back', ph)
  1210. }
  1211. }
  1212. Common.prototype.indexOf = function(arr, val){
  1213. for(let i = 0; i < arr.length; i++) {
  1214. if(arr[i].value == val || arr[i].value == (val ? val.value : val) || arr[i] == val || JSON.stringify(arr[i]) == JSON.stringify(val)) {
  1215. return i;
  1216. }
  1217. }
  1218. return -1;
  1219. }
  1220. Common.prototype.remove = function(arr, val){
  1221. let idx = this.indexOf(arr, val ? val.value : val);
  1222. if(idx > -1) {
  1223. arr.splice(idx, 1);
  1224. return true;
  1225. }
  1226. return false;
  1227. }
  1228. Common.prototype.selectAll = function(id, isOn, skipDis){
  1229. let dl = $(`[xid="${id}"]`);
  1230. if(!dl[0]){
  1231. return ;
  1232. }
  1233. if(dl.find('.xm-select-linkage')[0]){
  1234. return ;
  1235. }
  1236. dl.find(`dd[lay-value]:not(.${FORM_SELECT_TIPS}):not(.${THIS})${skipDis ? ':not(.'+DISABLED+')' :''}`).each((index, item) => {
  1237. item = $(item);
  1238. let val = this.getItem(id, item);
  1239. this.handlerLabel(id, dl.find(`dd[lay-value="${val.value}"]`), true, val, !isOn);
  1240. });
  1241. }
  1242. Common.prototype.removeAll = function(id, isOn, skipDis){
  1243. let dl = $(`[xid="${id}"]`);
  1244. if(!dl[0]){
  1245. return ;
  1246. }
  1247. if(dl.find('.xm-select-linkage')[0]){//针对多级联动的处理
  1248. data[id].values.concat([]).forEach((item, idx) => {
  1249. let vs = item.value.split('/');
  1250. let pid, li, index = 0;
  1251. do{
  1252. pid = vs[index ++];
  1253. li = dl.find(`.xm-select-linkage-group${index}:not(.xm-select-linkage-hide) li[value="${pid}"]`);
  1254. li.click();
  1255. }while(li.length && pid != undefined);
  1256. });
  1257. return ;
  1258. }
  1259. data[id].values.concat([]).forEach((item, index) => {
  1260. if(skipDis && dl.find(`dd[lay-value="${item.value}"]`).hasClass(DISABLED)){
  1261. }else{
  1262. this.handlerLabel(id, dl.find(`dd[lay-value="${item.value}"]`), false, item, !isOn);
  1263. }
  1264. });
  1265. }
  1266. Common.prototype.reverse = function(id, isOn, skipDis){
  1267. let dl = $(`[xid="${id}"]`);
  1268. if(!dl[0]){
  1269. return ;
  1270. }
  1271. if(dl.find('.xm-select-linkage')[0]){
  1272. return ;
  1273. }
  1274. dl.find(`dd[lay-value]:not(.${FORM_SELECT_TIPS})${skipDis ? ':not(.'+DISABLED+')' :''}`).each((index, item) => {
  1275. item = $(item);
  1276. let val = this.getItem(id, item);
  1277. this.handlerLabel(id, dl.find(`dd[lay-value="${val.value}"]`), !item.hasClass(THIS), val, !isOn);
  1278. });
  1279. }
  1280. Common.prototype.skin = function(id){
  1281. let skins = ['default' ,'primary', 'normal', 'warm', 'danger'];
  1282. let skin = skins[Math.floor(Math.random() * skins.length)];
  1283. $(`dl[xid="${id}"]`).parents(`.${PNAME}`).find(`.${FORM_SELECT}`).attr('xm-select-skin', skin);
  1284. this.check(id) && this.commonHandler(id, $(`dl[xid="${id}"]`).parents(`.${PNAME}`).find(`.${LABEL}`));
  1285. }
  1286. Common.prototype.getPosition = function(e){
  1287. let x = 0, y = 0;
  1288. while (e != null) {
  1289. x += e.offsetLeft;
  1290. y += e.offsetTop;
  1291. e = e.offsetParent;
  1292. }
  1293. return { x: x, y: y };
  1294. };
  1295. Common.prototype.onreset = function(){//监听reset按钮, 然后重置多选
  1296. $(document).on('click', '[type=reset]', (e) => {
  1297. $(e.target).parents('form').find(`.${PNAME} dl[xid]`).each((index, item) => {
  1298. let id = item.getAttribute('xid'),
  1299. dl = $(item),
  1300. dd,
  1301. temp = {};
  1302. common.removeAll(id);
  1303. data[id].config.init.forEach((val, idx) => {
  1304. if(val && (!temp[val] || data[id].config.repeat) && (dd = dl.find(`dd[lay-value="${val.value}"]`))[0]){
  1305. common.handlerLabel(id, dd, true);
  1306. temp[val] = 1;
  1307. }
  1308. });
  1309. })
  1310. });
  1311. }
  1312. Common.prototype.bindEvent = function(name, id, fun){
  1313. if(id && id instanceof Function){
  1314. fun = id;
  1315. id = null;
  1316. }
  1317. if(fun && fun instanceof Function){
  1318. if(!id){
  1319. $.each(data, (id, val) => {
  1320. data[id] ? (data[id].config[name] = fun) : (events[name][id] = fun)
  1321. })
  1322. }else{
  1323. data[id] ? (data[id].config[name] = fun, delete events[name][id]) : (events[name][id] = fun)
  1324. }
  1325. }
  1326. }
  1327. Common.prototype.check = function(id, notAutoRender){
  1328. if($(`dl[xid="${id}"]`).length) {
  1329. return true;
  1330. }else if($(`select[xm-select="${id}"]`).length){
  1331. if(!notAutoRender){
  1332. this.render(id, $(`select[xm-select="${id}"]`));
  1333. return true;
  1334. }
  1335. }else{
  1336. delete data[id];
  1337. return false;
  1338. }
  1339. }
  1340. Common.prototype.render = function(id, select){
  1341. common.init(select);
  1342. common.one($(`dl[xid="${id}"]`).parents(`.${PNAME}`));
  1343. common.initVal(id);
  1344. }
  1345. Common.prototype.log = function(obj){
  1346. }
  1347. let Select4 = function(){
  1348. this.v = v;
  1349. this.render();
  1350. };
  1351. let common = new Common();
  1352. Select4.prototype.value = function(id, type, isAppend){
  1353. if(typeof id != 'string'){
  1354. return [];
  1355. }
  1356. let fs = data[id];
  1357. if(!common.check(id)){
  1358. return [];
  1359. }
  1360. if(typeof type == 'string' || type == undefined){
  1361. let arr = fs.values.concat([]) || [];
  1362. if(type == 'val') {
  1363. return arr.map((val) => {
  1364. return val.value;
  1365. });
  1366. }
  1367. if(type == 'valStr') {
  1368. return arr.map((val) => {
  1369. return val.value;
  1370. }).join(',');
  1371. }
  1372. if(type == 'name') {
  1373. return arr.map((val) => {
  1374. return val.name;
  1375. });
  1376. }
  1377. if(type == 'nameStr') {
  1378. return arr.map((val) => {
  1379. return val.name;
  1380. }).join(',');
  1381. }
  1382. return arr;
  1383. }
  1384. if(common.isArray(type)) {
  1385. let dl = $(`[xid="${id}"]`),
  1386. temp = {},
  1387. dd,
  1388. isAdd = true;
  1389. if(isAppend == false){//删除传入的数组
  1390. isAdd = false;
  1391. }else if(isAppend == true){//追加模式
  1392. isAdd = true;
  1393. }else{//删除原有的数据
  1394. common.removeAll(id);
  1395. }
  1396. if(isAdd){
  1397. fs.values.forEach((val, index) => {
  1398. temp[val.value] = 1;
  1399. });
  1400. }
  1401. type.forEach((val, index) => {
  1402. if(val && (!temp[val] || fs.config.repeat)){
  1403. if((dd = dl.find(`dd[lay-value="${val}"]`))[0]){
  1404. common.handlerLabel(id, dd, isAdd, null, true);
  1405. temp[val] = 1;
  1406. }else{
  1407. let name = common.valToName(id, val);
  1408. if(name){
  1409. common.handlerLabel(id, dd, isAdd, common.getItem(id, val), true);
  1410. temp[val] = 1;
  1411. }
  1412. }
  1413. }
  1414. });
  1415. }
  1416. }
  1417. Select4.prototype.on = function(id, fun, isEnd) {
  1418. common.bindEvent(isEnd ? 'endOn' : 'on', id, fun);
  1419. return this;
  1420. }
  1421. Select4.prototype.filter = function(id, fun){
  1422. common.bindEvent('filter', id, fun);
  1423. return this;
  1424. }
  1425. Select4.prototype.maxTips = function(id, fun){
  1426. common.bindEvent('maxTips', id, fun);
  1427. return this;
  1428. }
  1429. Select4.prototype.opened = function(id, fun){
  1430. common.bindEvent('opened', id, fun);
  1431. return this;
  1432. }
  1433. Select4.prototype.closed = function(id, fun){
  1434. common.bindEvent('closed', id, fun);
  1435. return this;
  1436. }
  1437. Select4.prototype.config = function(id, config, isJson){
  1438. if(id && typeof id == 'object'){
  1439. isJson = config == true;
  1440. config = id;
  1441. id = null;
  1442. }
  1443. if(config && typeof config== 'object'){
  1444. if(isJson){
  1445. config.header || (config.header = {});
  1446. config.header['Content-Type'] = 'application/json; charset=UTF-8';
  1447. config.dataType = 'json';
  1448. }
  1449. id ? (
  1450. ajaxs[id] = $.extend(true, {}, ajaxs[id] || ajax, config), !common.check(id) && this.render(id),
  1451. data[id] && config.direction && (data[id].config.direction = config.direction),
  1452. data[id] && config.clearInput && (data[id].config.clearInput = true),
  1453. config.searchUrl && data[id] && common.triggerSearch($(`.${PNAME} dl[xid="${id}"]`).parents(`.${FORM_SELECT}`), true)
  1454. ) : (
  1455. $.extend(true, ajax, config),
  1456. $.each(ajaxs, (key, item) => {
  1457. $.extend(true, item, config)
  1458. })
  1459. );
  1460. }
  1461. return this;
  1462. }
  1463. Select4.prototype.render = function(id, options){
  1464. if(id && typeof id == 'object'){
  1465. options = id;
  1466. id = null;
  1467. }
  1468. let config = options ? {
  1469. init: options.init,
  1470. disabled: options.disabled,
  1471. max: options.max,
  1472. isSearch: options.isSearch,
  1473. searchUrl: options.searchUrl,
  1474. isCreate: options.isCreate,
  1475. radio: options.radio,
  1476. skin: options.skin,
  1477. direction: options.direction,
  1478. height: options.height,
  1479. formname: options.formname,
  1480. layverify: options.layverify,
  1481. layverType: options.layverType,
  1482. showCount: options.showCount,
  1483. placeholder: options.placeholder,
  1484. create: options.create,
  1485. filter: options.filter,
  1486. maxTips: options.maxTips,
  1487. on: options.on,
  1488. on: options.on,
  1489. opened: options.opened,
  1490. closed: options.closed,
  1491. template: options.template,
  1492. clearInput: options.clearInput,
  1493. } : {};
  1494. options && options.searchType != undefined && (config.searchType = options.searchType == 'dl' ? 1 : 0);
  1495. if(id){
  1496. fsConfigs[id] = {};
  1497. $.extend(fsConfigs[id], data[id] ? data[id].config : {}, config);
  1498. }else{
  1499. $.extend(fsConfig, config);
  1500. }
  1501. ($(`select[${NAME}="${id}"]`)[0] ? $(`select[${NAME}="${id}"]`) : $(`select[${NAME}]`)).each((index, select) => {
  1502. let sid = select.getAttribute(NAME);
  1503. common.render(sid, select);
  1504. setTimeout(() => common.setHidnVal(sid, $(`select[xm-select="${sid}"] + div.${PNAME} .${LABEL}`)), 10);
  1505. });
  1506. return this;
  1507. }
  1508. Select4.prototype.disabled = function(id){
  1509. let target = {};
  1510. id ? (common.check(id) && (target[id] = data[id])) : (target = data);
  1511. $.each(target, (key, val) => {
  1512. $(`dl[xid="${key}"]`).prev().addClass(DIS);
  1513. });
  1514. return this;
  1515. }
  1516. Select4.prototype.undisabled = function(id){
  1517. let target = {};
  1518. id ? (common.check(id) && (target[id] = data[id])) : (target = data);
  1519. $.each(target, (key, val) => {
  1520. $(`dl[xid="${key}"]`).prev().removeClass(DIS);
  1521. });
  1522. return this;
  1523. }
  1524. Select4.prototype.data = function(id, type, config){
  1525. if(!id || !type || !config){
  1526. common.log(`id: ${id} param error !!!`)
  1527. return this;
  1528. }
  1529. if(!common.check(id)){
  1530. common.log(`id: ${id} not render !!!`)
  1531. return this;
  1532. }
  1533. this.value(id, []);
  1534. this.config(id, config);
  1535. if(type == 'local'){
  1536. common.renderData(id, config.arr, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100');
  1537. }else if(type == 'server'){
  1538. common.ajax(id, config.url, config.keyword, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100');
  1539. }
  1540. return this;
  1541. }
  1542. Select4.prototype.btns = function(id, btns, config){
  1543. if(id && common.isArray(id)){
  1544. btns = id;
  1545. id = null;
  1546. }
  1547. if(!btns || !common.isArray(btns)) {
  1548. return this;
  1549. };
  1550. let target = {};
  1551. id ? (common.check(id) && (target[id] = data[id])) : (target = data);
  1552. btns = btns.map((obj) => {
  1553. if(typeof obj == 'string'){
  1554. if(obj == 'select'){
  1555. return quickBtns[0];
  1556. }
  1557. if(obj == 'remove'){
  1558. return quickBtns[1];
  1559. }
  1560. if(obj == 'reverse'){
  1561. return quickBtns[2];
  1562. }
  1563. if(obj == 'skin'){
  1564. return quickBtns[3];
  1565. }
  1566. }
  1567. return obj;
  1568. });
  1569. $.each(target, (key, val) => {
  1570. val.config.btns = btns;
  1571. let dd = $(`dl[xid="${key}"]`).find(`.${FORM_SELECT_TIPS}:first`);
  1572. if(btns.length){
  1573. let show = config && config.show && (config.show == 'name' || config.show == 'icon') ? config.show : '';
  1574. let html = common.renderBtns(key, show, config && config.space ? config.space : '30px');
  1575. dd.html(html);
  1576. }else{
  1577. let pcInput = dd.parents(`.${FORM_SELECT}`).find(`.${TDIV} input`);
  1578. let html = pcInput.attr('placeholder') || pcInput.attr('back');
  1579. dd.html(html);
  1580. dd.removeAttr('style');
  1581. }
  1582. });
  1583. return this;
  1584. }
  1585. Select4.prototype.search = function(id, val){
  1586. if(id && common.check(id)){
  1587. ajaxs[id] = $.extend(true, {}, ajaxs[id] || ajax, {
  1588. first: true,
  1589. searchVal: val
  1590. });
  1591. common.triggerSearch($(`dl[xid="${id}"]`).parents(`.${FORM_SELECT}`), true);
  1592. }
  1593. return this;
  1594. }
  1595. Select4.prototype.replace = function(id, type, config){
  1596. if(!id || !type || !config){
  1597. common.log(`id: ${id} param error !!!`)
  1598. return this;
  1599. }
  1600. if(!common.check(id, true)){
  1601. common.log(`id: ${id} not render !!!`)
  1602. return this;
  1603. }
  1604. let oldVals = this.value(id, 'val');
  1605. this.value(id, []);
  1606. this.config(id, config);
  1607. if(type == 'local'){
  1608. common.renderData(id, config.arr, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100', false, true);
  1609. this.value(id, oldVals, true);
  1610. }else if(type == 'server'){
  1611. common.ajax(id, config.url, config.keyword, config.linkage == true, config.linkageWidth ? config.linkageWidth : '100', false, (id) => {
  1612. this.value(id, oldVals, true);
  1613. }, true);
  1614. }
  1615. }
  1616. return new Select4();
  1617. });