MSelector.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. //提供两种方式,一种是传入selectValue,selectText, 另外一种是 用onLoadData 或 loadData 加载数据,
  2. MWF.xDesktop.requireApp("Template", "MTooltips", null, false);
  3. var MSelector = new Class({
  4. Extends: MWF.widget.Common,
  5. Implements: [Options, Events],
  6. options: {
  7. "style": "default",
  8. "width": "230px",
  9. "height": "30px",
  10. "defaultOptionLp" : "请选择",
  11. "trigger" : "delay", //immediately
  12. "isSetSelectedValue" : true,
  13. "isChangeOptionStyle" : true,
  14. "inputEnable" : false,
  15. "isCreateReadNode" : true, //适应给MDomitem的做法
  16. "emptyOptionEnable" : true,
  17. "containerIsTarget" : false,
  18. "textField" : "",
  19. "valueField" : "",
  20. "value" : "",
  21. "text" : "",
  22. "defaultVaue" : "",
  23. "selectValue" : "",
  24. "selectText" : "",
  25. "isEdited" : true,
  26. "tooltipsOptions" : {
  27. axis: "y", //箭头在x轴还是y轴上展现
  28. position : { //node 固定的位置
  29. x : "center", //x轴上left center right, auto 系统自动计算
  30. y : "bottom" //y 轴上top middle bottom, auto 系统自动计算
  31. },
  32. event : "click", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  33. hiddenDelay : 200, //ms , 有target 且 事件类型为 mouseenter 时有效
  34. displayDelay : 0 //ms , 有target 且事件类型为 mouseenter 时有效
  35. }
  36. },
  37. initialize: function (container, options , app, css, dropdownContainer ) {
  38. this.setOptions(options);
  39. if( !this.options.isEdited && !this.options.isCreateReadNode ){
  40. }else{
  41. this.path = "/x_component_Template/$MSelector/";
  42. this.cssPath = "/x_component_Template/$MSelector/"+this.options.style+"/css.wcss";
  43. this._loadCss();
  44. if( css ){
  45. this.css = Object.merge( this.css, css )
  46. }
  47. }
  48. this.valSeparator = /,|;|\^\^|\|/; //如果是多值对象,作为用户选择的多个值的分隔符
  49. this.app = app;
  50. this.container = $(container);
  51. this.dropdownContainer = dropdownContainer || $(dropdownContainer);
  52. },
  53. load : function( callback ){
  54. if( this.options.isEdited ){
  55. this.loadEdit(callback)
  56. }else{
  57. this.loadRead(callback)
  58. }
  59. },
  60. initPara: function(){
  61. this.itemNodeList = [];
  62. this.itemNodeObject = {};
  63. this.value = this.options.value || this.options.text || this.options.defaultVaue;
  64. this.text = this.options.text || this.options.value || this.options.defaultVaue;
  65. this.textField = this.options.textField || this.options.valueField;
  66. this.valueField = this.options.valueField || this.options.textField;
  67. if( this.options.selectValue || this.options.selectText ){
  68. this.textField = "text";
  69. this.valueField = "value";
  70. var selectValue = this.options.selectValue;
  71. var selectText = this.options.selectText;
  72. this.selectValues = typeOf( selectValue ) == "array" ? selectValue : selectValue.split( this.valSeparator );
  73. this.selectTexts = typeOf( selectText ) == "array" ? selectText : selectText.split(this.valSeparator);
  74. this.data = [];
  75. if( this.options.emptyOptionEnable ){
  76. this.data.push({
  77. value : "",
  78. text : this.options.defaultOptionLp || ""
  79. })
  80. }
  81. this.selectValues.each( function( v,i ){
  82. this.data.push({
  83. value : v,
  84. text : this.selectTexts[i]
  85. })
  86. }.bind(this))
  87. }
  88. },
  89. loadRead: function(callback){
  90. this.initPara();
  91. var fun = function(){
  92. for( var i=0; i<this.data.length; i++ ){
  93. var d = this.data[i];
  94. if( this.options.text ){
  95. if( d[this.textField] == this.options.text ){
  96. this.value = d[this.valueField];
  97. this.text = this.options.text;
  98. this.currentItemData = d;
  99. break;
  100. }
  101. }else if( this.options.value ){
  102. if( d[this.valueField] == this.options.value ){
  103. this.value = this.options.value;
  104. this.text = d[this.textField];
  105. this.currentItemData = d;
  106. break;
  107. }
  108. }
  109. }
  110. this.loadReadNode( this.text );
  111. if( callback )callback();
  112. }.bind(this);
  113. if( this.data ){
  114. fun()
  115. }else{
  116. this._loadData( function( data ) {
  117. this.data = this.parseData(data);
  118. fun();
  119. }.bind(this))
  120. }
  121. },
  122. loadReadNode: function( text ){
  123. this.fireEvent( "loadReadNode", text );
  124. if( this.options.isCreateReadNode ){
  125. if( this.node )this.node.destroy();
  126. this.node = new Element("div", {
  127. styles : this.css.readNode,
  128. text : text
  129. }).inject( this.container );
  130. }
  131. },
  132. loadEdit:function( callback ){
  133. this.initPara();
  134. if( !this.node ){
  135. if( this.options.containerIsTarget ){
  136. this.node = this.container
  137. }else{
  138. this.node = new Element("div.selectNode", {
  139. styles : this.css.selectNode
  140. }).inject( this.container );
  141. this.node.setStyles({
  142. "width":this.options.width,
  143. "height":this.options.height
  144. });
  145. }
  146. }
  147. if( this.data ){
  148. this.createDefaultItem();
  149. this.loadContent( this.data );
  150. this.fireEvent("postLoad", [this]);
  151. }else{
  152. this._loadData( function( data ){
  153. this.data = this.parseData( data );
  154. this.createDefaultItem();
  155. this.loadContent( this.data );
  156. this.fireEvent("postLoad", [this]);
  157. }.bind(this))
  158. }
  159. //this.node.addEvent( "click" , function( ev ){
  160. // this.loadContent();
  161. // ev.stopPropagation();
  162. //}.bind(this));
  163. if(callback)callback();
  164. },
  165. resetOptions : function(){
  166. if( this.contentTooltip ){
  167. this.contentTooltip.destroy();
  168. this.contentTooltip = null;
  169. }
  170. if( this.node ){
  171. this.node.empty()
  172. }
  173. //if( this.node && this.options.containerIsTarget ){
  174. // var node = this.node;
  175. //
  176. // this.node = new Element("div.selectNode", {
  177. // styles : this.css.selectNode
  178. // }).inject( node, "after" );
  179. //
  180. // this.node.setStyles({
  181. // "width":this.options.width,
  182. // "height":this.options.height
  183. // });
  184. //
  185. // node.destroy();
  186. //}
  187. this.data = null;
  188. this.load();
  189. },
  190. addOption : function(text, value){
  191. var obj = {};
  192. obj[this.textField] = text;
  193. obj[this.valueField] = value;
  194. this.data.push( obj );
  195. if( this.contentTooltip ){
  196. this.contentTooltip.createItem(obj);
  197. }
  198. },
  199. deleteOption : function(value){
  200. for( var i=0; i<this.itemNodeList.length; i++ ){
  201. var listItemNode = this.itemNodeList[i];
  202. var data = listItemNode.retrieve("data");
  203. if( data[this.valueField] == value ){
  204. this.itemNodeList.erase(listItemNode);
  205. listItemNode.destroy();
  206. break;
  207. }
  208. }
  209. if(this.itemNodeObject[ value ])delete this.itemNodeObject[ value ];
  210. if(this.data){
  211. for( var i=0; i<this.data.length; i++ ) {
  212. var d = this.data[i];
  213. if( d[this.valueField] == value ){
  214. this.data.erase(d);
  215. }
  216. }
  217. }
  218. },
  219. loadContent : function( data ){
  220. if( !this.contentTooltip ){
  221. var width = parseInt(this.options.width)+"px";
  222. this.css.tooltipNode.width = width;
  223. this.css.tooltipNode["max-width"] = width;
  224. var options = Object.merge({
  225. nodeStyles : this.css.tooltipNode,
  226. onPostLoad : function(){
  227. if( this.selectArrowNode )this.selectArrowNode.setStyles( this.css.selectArrowNode_up );
  228. if( this.inputNode ){
  229. this.inputNode.focus();
  230. }
  231. }.bind(this),
  232. onPostInitialize : function(){
  233. if(this.options.trigger == "immediately" ){
  234. this.contentTooltip.load();
  235. }
  236. }.bind(this),
  237. onHide : function(){
  238. this.status = "hidden";
  239. if(this.selectArrowNode) this.selectArrowNode.setStyles( this.css.selectArrowNode );
  240. }.bind(this)
  241. }, this.options.tooltipsOptions );
  242. this.contentTooltip = new MSelector.Tootips( this.dropdownContainer || this.app.content, this.node, this.app, data, options );
  243. this.contentTooltip.selector = this;
  244. }
  245. },
  246. setWidth : function( width ){
  247. this.options.width = width;
  248. if( this.contentTooltip ){
  249. this.contentTooltip.options.nodeStyles.width = width;
  250. this.contentTooltip.options.nodeStyles["max-width"] = width;
  251. if( this.contentTooltip.nodeStyles ){
  252. this.contentTooltip.nodeStyles.width = width;
  253. this.contentTooltip.nodeStyles["max-width"] = width;
  254. }
  255. if(this.contentTooltip.node){
  256. this.contentTooltip.node.setStyle("width",width);
  257. this.contentTooltip.node.setStyle("max-width",width);
  258. }
  259. }
  260. if( this.node ){
  261. this.node.setStyle("width",width);
  262. }
  263. this.selectValueNode.setStyle("width",parseInt(width)-25);
  264. },
  265. createDefaultItem:function(){
  266. if( this.options.containerIsTarget )return;
  267. this.selectValueNode = new Element("div.selectValueNode",{
  268. "styles":this.css.selectValueNode
  269. }).inject(this.node);
  270. this.selectValueNode.setStyles({
  271. "width":(parseInt(this.options.width)-parseInt(this.options.height)-10)+"px",
  272. "height":this.options.height,
  273. "line-height":this.options.height
  274. });
  275. var d = this._getData( this.options.value );
  276. var text = d ? d[ this.textField ] : this.options.value;
  277. if( this.options.inputEnable ){
  278. this.inputNode = new Element("input", {
  279. "value" : text || this.options.defaultOptionLp ,
  280. "styles" : this.css.inputNode
  281. }).inject( this.selectValueNode );
  282. this.inputNode.addEvents( {
  283. focus : function(){
  284. if( this.inputNode.get("value") == this.options.defaultOptionLp ){
  285. this.inputNode.set("value", "" );
  286. }
  287. }.bind(this),
  288. blur : function(){
  289. var flag = false;
  290. var val = this.inputNode.get("value");
  291. if( val == "" ){
  292. this.inputNode.set("value", this.options.defaultOptionLp);
  293. }else{
  294. for( var i=0; i<this.data.length; i++ ){
  295. var d = this.data[i];
  296. if( d[ this.textField ] == val ){
  297. var itemNode = this.itemNodeObject[ d[this.valueField] ];
  298. this.setCurrentItem( itemNode );
  299. flag = true;
  300. break;
  301. }
  302. }
  303. if( !flag ){
  304. this.cancelCurrentItem();
  305. }
  306. }
  307. }.bind(this)
  308. } )
  309. }else{
  310. this.selectValueNode.set("text", text || this.options.defaultOptionLp);
  311. }
  312. this.selectArrowNode = new Element("div.selectArrowNode",{
  313. "styles":this.css.selectArrowNode
  314. }).inject(this.node);
  315. this.selectArrowNode.setStyles({
  316. "width":this.options.height,
  317. "height":this.options.height
  318. });
  319. },
  320. setCurrentItem : function( itemNode ){
  321. var data = itemNode.retrieve( "data" );
  322. if( this.currentItemNode ){
  323. this.currentItemNode.setStyles( this.css.listItemNode );
  324. }
  325. this.currentItemNode = itemNode;
  326. this.currentItemData = data;
  327. this.currentItemText = itemNode.get("text");
  328. if( this.options.isChangeOptionStyle )itemNode.setStyles( this.css.listItemNode_current );
  329. if( this.options.isSetSelectedValue && this.selectValueNode ){
  330. if( this.options.inputEnable ){
  331. this.inputNode.set("value", data[ this.textField ] );
  332. }else{
  333. this.selectValueNode.set("text", data[ this.textField ] );
  334. }
  335. }
  336. },
  337. cancelCurrentItem: function(){
  338. if( this.currentItemNode ){
  339. this.currentItemNode.setStyles( this.css.listItemNode );
  340. }
  341. this.currentItemNode = null;
  342. this.currentItemData = null;
  343. this.currentItemText = null;
  344. },
  345. parseData: function( data ){
  346. if( typeOf( data[0] ) == "string" ){
  347. var arr = [];
  348. this.textField = "text";
  349. this.valueField = "value";
  350. if(this.options.emptyOptionEnable ){
  351. arr.push({
  352. value : "",
  353. text : this.options.defaultOptionLp || ""
  354. });
  355. }
  356. data.each( function(d){
  357. arr.push({
  358. value : d,
  359. text : d
  360. })
  361. }.bind(this));
  362. return arr;
  363. }else{
  364. if( this.options.emptyOptionEnable && this.textField ){
  365. var obj = {};
  366. obj[ this.textField ] = this.options.defaultOptionLp || "";
  367. if( this.valueField != this.textField )obj[ this.valueField ] = "";
  368. data.unshift( obj )
  369. }
  370. return data;
  371. }
  372. },
  373. destroy : function(){
  374. if( this.node )this.node.destroy();
  375. if( this.contentTooltip )this.contentTooltip.destroy();
  376. },
  377. showTooltip : function(){
  378. this.contentTooltip.load();
  379. },
  380. hide : function(){
  381. this.status = "hidden";
  382. if(this.selectArrowNode) this.selectArrowNode.setStyles( this.css.selectArrowNode );
  383. if( this.contentTooltip )this.contentTooltip.hide();
  384. },
  385. setValue : function( value ){
  386. if( this.options.isEdited ){
  387. var itemNode = this.itemNodeObject[ value ];
  388. if( itemNode ){
  389. this.setCurrentItem( itemNode );
  390. }else if( this.options.inputEnable ) {
  391. var d = this._getData( value );
  392. if( d ){
  393. this.inputNode.set("value", d[ this.textField ] );
  394. }else{
  395. this.inputNode.set("value", value );
  396. }
  397. }else{
  398. if( this.options.isSetSelectedValue && this.selectValueNode ){
  399. var d = this._getData( value );
  400. this.selectValueNode.set("text", d[ this.textField ] );
  401. this.value = value;
  402. }
  403. }
  404. }else{
  405. var d = this._getData( value );
  406. if( d ){
  407. this.loadReadNode( d[this.textField] );
  408. }else{
  409. this.loadReadNode( value );
  410. }
  411. }
  412. },
  413. get : function(){
  414. return {
  415. "value" : this.getValue(),
  416. "text" : this.getText()
  417. }
  418. },
  419. getValue : function(){
  420. if( this.options.isEdited ){
  421. if( this.currentItemData && this.valueField ) {
  422. return this.currentItemData[this.valueField]
  423. }else if( this.inputNode ){
  424. return this.inputNode.get("value");
  425. }else{
  426. return this.value;
  427. }
  428. }else{
  429. return this.value;
  430. }
  431. },
  432. getText : function(){
  433. if( this.options.isEdited ){
  434. if( this.currentItemData && this.textField ) {
  435. return this.currentItemData[this.textField]
  436. }else if( this.inputNode ){
  437. var d = this._getData( this.inputNode.get("value"), "text" );
  438. if( d ){
  439. return d[ this.textField ];
  440. }else{
  441. return this.inputNode.get("value");
  442. }
  443. }else{
  444. return this.text;
  445. }
  446. }else{
  447. return this.text;
  448. }
  449. },
  450. getData : function(){
  451. if( this.currentItemData )return this.currentItemData;
  452. if( this.inputNode )return this.inputNode.get("value");
  453. if( !this.options.text || !this.options.value )return null;
  454. for( var i=0; i<this.data.length; i++ ){
  455. var d = this.data[i];
  456. if( this.options.text ){
  457. if( d[this.textField] == this.options.text ){
  458. return d;
  459. }
  460. }else if( this.options.value ){
  461. if( d[this.valueField] == this.options.value ){
  462. return d;
  463. }
  464. }
  465. }
  466. return null;
  467. },
  468. _getData : function( vort, type ){
  469. for( var i=0; i<this.data.length; i++ ){
  470. var d = this.data[i];
  471. if( type == "text" ){
  472. if( d[this.textField] == vort ){
  473. return d;
  474. }
  475. }else{
  476. if( d[this.valueField] == vort ){
  477. return d;
  478. }
  479. }
  480. }
  481. return null;
  482. },
  483. _selectItem : function( itemNode, itemData ){
  484. this.fireEvent("selectItem", [itemNode, itemData] );
  485. },
  486. _loadData : function( callback ){
  487. //if(callback)callback();
  488. this.fireEvent("loadData",callback );
  489. },
  490. _postCreateItem: function(listItemNode, data){
  491. }
  492. });
  493. MSelector.Tootips = new Class({
  494. Extends: MTooltips,
  495. options : {
  496. axis: "y", //箭头在x轴还是y轴上展现
  497. position : { //node 固定的位置
  498. x : "center", //x轴上left center right, auto 系统自动计算
  499. y : "bottom" //y 轴上top middle bottom, auto 系统自动计算
  500. },
  501. event : "click", //事件类型,有target 时有效, mouseenter对应mouseleave,click 对应 container 的 click
  502. hiddenDelay : 200, //ms , 有target 且 事件类型为 mouseenter 时有效
  503. displayDelay : 0, //ms , 有target 且事件类型为 mouseenter 时有效
  504. hasArrow : false
  505. },
  506. _customNode : function( node, contentNode ){
  507. //var width = ( parseInt( this.selector.options.width ) )+ "px";
  508. //node.setStyles({
  509. // "width": width,
  510. // "max-width": width
  511. //});
  512. this.createItemList( this.data, contentNode )
  513. },
  514. createItemList:function(data, node){
  515. data = data || [];
  516. var _selector = this.selector;
  517. this.css = _selector.css;
  518. if(_selector.selectArrowNode)_selector.selectArrowNode.setStyles( this.css.selectArrowNode_up );
  519. _selector.listContentNode = new Element("div.listContentNode",{
  520. "styles":this.css.listContentNode
  521. }).inject( node );
  522. //_selector.listContentNode.setStyles({
  523. // "width": node.getSize().x+"px"
  524. //});
  525. _selector.listNode = new Element("div.listNode",{
  526. "styles":this.css.listNode
  527. }).inject(_selector.listContentNode);
  528. _selector.setScrollBar(_selector.listNode);
  529. data.each(function(d){
  530. this.createItem( d );
  531. }.bind(this));
  532. },
  533. createItem: function( data ){
  534. var _selector = this.selector;
  535. if( !_selector.listNode )return;
  536. var listItemNode = new Element("div.listItemNode",{
  537. "styles":this.css.listItemNode,
  538. "text": data[ _selector.textField ]
  539. }).inject(_selector.listNode);
  540. listItemNode.setStyles({
  541. "height":_selector.options.height,
  542. "line-height":_selector.options.height
  543. });
  544. if(data)listItemNode.store("data",data);
  545. listItemNode.addEvents({
  546. "click":function(ev){
  547. var _self = this.obj;
  548. var data = this.itemNode.retrieve( "data" );
  549. _self.selector.setCurrentItem( this.itemNode );
  550. _self.selector._selectItem( this.itemNode, data, ev );
  551. _self.selector.fireEvent("selectItem", [ this.itemNode, data, ev ] );
  552. _self.hide();
  553. ev.stopPropagation();
  554. }.bind({ obj : this, itemNode : listItemNode }),
  555. "mouseover":function(){
  556. if( this.obj.selector.currentItemNode != this.itemNode || !this.obj.selector.options.isChangeOptionStyle ){
  557. this.itemNode.setStyles( this.obj.selector.css.listItemNode_over );
  558. }
  559. }.bind( {obj : this, itemNode : listItemNode }),
  560. "mouseout":function(){
  561. if( this.obj.selector.currentItemNode != this.itemNode || !this.obj.selector.options.isChangeOptionStyle ){
  562. this.itemNode.setStyles( this.obj.selector.css.listItemNode );
  563. }
  564. }.bind( {obj : this, itemNode : listItemNode })
  565. });
  566. _selector.itemNodeList.push( listItemNode );
  567. _selector.itemNodeObject[ data[ _selector.valueField ] ] = listItemNode;
  568. var isCurrent = false;
  569. if( _selector.currentItemData ){
  570. isCurrent = data[ _selector.valueField ] == _selector.currentItemData[ _selector.valueField ];
  571. }else if( _selector.value ){
  572. isCurrent = data[ _selector.valueField ] == _selector.value;
  573. }else if( _selector.text ){
  574. isCurrent = data[ _selector.textField ] == _selector.text;
  575. }
  576. if( isCurrent )_selector.setCurrentItem( listItemNode );
  577. _selector.fireEvent("postCreateItem", [ listItemNode, data ] );
  578. _selector._postCreateItem(listItemNode, data)
  579. }
  580. });