好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Knockot JS 数字输入插件

Knockot JS 数字输入插件

我将它放在了在GitHub上面,希望有高手一起来帮助完善它,这里附上网址:

?

https://github.com/dragonrhyme/KnockotNumeric

 之前写过 XML技术在界面生成中的简单应用 的文章,后来由于一直很忙,就没有再写。但是东西已经可以用了, 附上截图给大家预览下,等自己不那么紧张的时候,再接着跟大家分享,这里先行道歉!

再附上一TabPanel为例子的XML代码:

 1   <  Tab   ID  ="tab1"   Cols  ="12"   Offset  ="0"  > 
 2     <  TabItem   Key  ="tabitem1"   LabelText  ="选项卡一"  > 
 3       <  TextBox   ID  ="tabitemtextbox1"   LabelWidth  ="10"   Cols  ="3"   Offset  ="0"   LabelText   ="文字输入一:"   Value  ="$root.text"  /> 
 4       <  TextBox   ID  ="tabitemtextbox2"   LabelWidth  ="100"   Cols  ="3"   Offset  ="0"   LabelText   ="文字输入二:"   Value  ="$root.text"   NotWripRow  ="true"  /> 
 5       <  TextBox   ID  ="tabitemtextbox3"   LabelWidth  ="100"   Cols  ="3"   Offset  ="0"   LabelText   ="文字输入三:"   Value  ="$root.text"   NotWripRow  ="true"  /> 
 6       <  TextBox   ID  ="tabitemtextbox4"   LabelWidth  ="100"   Cols  ="3"   Offset  ="0"   LabelText   ="文字输入四:"   Value  ="$root.text"   NotWripRow  ="true"  /> 
 7     </  TabItem  > 
 8   </  Tab  > 

然后这里是关于操作的定义方式,分为服务器端和客户端操作,其中客户端操作不需要额外手写代码,服务器端也是ajax交互的。也贴出来给大家探讨下(注释部分表示可以那样嵌套定义操作):

  1   <  Operations  > 
  2     <  Operation   ID  ="saveData"  > 
  3       <  ServerOperation   Handler  ="SaveChanges"   FinishAlert  ="'保存数据'"  > 
  4         <!--  <ServerOperation Handler="SaveChanges" FinishAlert="'Second'"></ServerOperation>
   5           <ClientOperation Handler="Confirm" Para="'From client'"></ClientOperation>
   6           <ClientOperation Handler="Information" Para="'From client'"></ClientOperation>
   7           <FailbackOperation>
   8             <ClientOperation Handler="Error" Para="'From client'"></ClientOperation>
   9           </FailbackOperation>  --> 
 10       </  ServerOperation  > 
 11     </  Operation  > 
 12     <  Operation   ID  ="changeValue"  > 
 13       <  ClientOperation   Handler  ="ChangeValue"   Para  ="'$root.mCourseList[0].Name', $root.mCourseList()[0].Desc"   /> 
 14     </  Operation  > 
 15     <  Operation   ID  ="changeValue1"  > 
 16       <  ClientOperation   Handler  ="ChangeValue"   Para  ="'$root.mCourseList[*].Name', $root.mCourseList()[1].Desc"   /> 
 17     </  Operation  > 
 18     <  Operation   ID  ="openWindow"  > 
 19       <  ClientOperation   Handler  ="OpenWindow"   Para  ="'window1'"   /> 
 20     </  Operation  > 
 21   </  Operations  > 

当然,OpenWindow有关于Window的定义,如下:

 1   <  PopWindow   Height  ="100"   Width  ="100"   IsEnable  ="true"   IsVisible  ="true"   ID  ="window1"   Title  ="这是个窗口"   > 
 2     <  TableContainer  > 
 3       <  DataGrid   Rows  ="6"   SelectColumnName   ="isSelected"   SelectMode  ="multi"   ID  ="datagrid1"   DataSource  ="$root.mCourseList"  > 
 4         <  Column   BindFieldKey  ="Name"   Header  ="名称"   Tip  ="This is tip"  /> 
 5         <  Column   BindFieldKey  ="Desc"   Header  ="描述"   Tip  ="This is tip"  /> 
 6       </  DataGrid  > 
 7     </  TableContainer  > 
 8   </  PopWindow  > 

看看Rhyme定义的客户端操作类库, 例如ChangeValue,解析'$root.mCourseList[*].Name'这个表达式的代码还算有些价值, 当然,还不太完善:

  1  ChangeValue:  function   (args, successCallBack, failureCallBack) {
   2       var   _$root, _$data, _event, _target, _assignTo, _from, _dataContext, _statements, _assignmentInContextByStatementsWithValue;
   3  
  4       //   Context params. 
  5      _$root = args.$root;     //   Root context of view model. 
  6      _$data = args.$data;     //   Current context of view model. 
  7      _event = args.event;     //   Event from dom or jQuery . 
  8      _target = args.target;     //   Source element of event. 
  9  
 10       //   The change where target. 
 11      _assignTo = args.params[0 ];
  12       //   The new value. 
 13      _from = ko.utils.unwrapObservable(args.params[1 ]);
  14  
 15       //   When the target was observable object, Assignment new value to it. 
 16       if  ( typeof  (_assignTo) === 'function' ) {
  17           _assignTo(_from);
  18      }  else   if  ( typeof  (_assignTo) === 'string' ) {
  19           //    The list of statements need to parse. 
 20          _statements = _assignTo.replace(/\[\*\]/g, '.*').replace(/\[\d\]/g,  function  (s, t) {  return  '.' + s.replace(/[^\d]/g, ''); }).split('.' );
  21          _assignmentInContextByStatementsWithValue =  function   (dataContext, statements, newValue, currentStatementIndex) {
  22               var  _currentContext =  dataContext,
  23                   _currentContextLength,
  24                  _currentStatementIndex =  currentStatementIndex,
  25                   _currentStatement,
  26                   _indexStatement,
  27                  _totalStatements =  statements.length;
  28  
 29               //   Syntactic analysis. 
 30               for  ( var  i = _currentStatementIndex; i < _totalStatements; i++ ) {
  31                  _currentStatement =  statements[i];
  32  
 33                   if  (_currentStatement === '$root' || _currentStatement === '$data' ) {
  34                       continue  ;
  35                  }  else   if  (/^\d+$/.test(_currentStatement)) {  //   Match index statement. 
 36                      _indexStatement =  parseInt(statements[i]);
  37  
 38                       if  (i === _totalStatements - 1 ) {
  39                           _currentContext[_indexStatement](newValue);
  40                      }  else   {
  41                          _assignmentInContextByStatementsWithValue(_currentContext[_indexStatement], statements, newValue, i + 1 );
  42                       }
  43                  }  else   if  (_currentStatement === '*') {  //   Match every item. 
 44                      _currentContextLength =  ko.utils.unwrapObservable(_currentContext).length;
  45                       for  ( var  j = 0; j < _currentContextLength; j++ ) {
  46                           debugger  ;
  47                           if  (i === _totalStatements - 1 ) {
  48                               _currentContext[j](newValue);
  49                          }  else   {
  50                              _assignmentInContextByStatementsWithValue(_currentContext[j], statements, newValue, i + 1 );
  51                           }
  52                       }
  53                  }  else  {  //   In normal case. 
 54                       if  (i === _totalStatements - 1 ) {
  55                          dataContext[_currentStatement.replace(/\(\)/g, '' )](newValue);
  56                      }  else   {
  57                          _currentContext = ko.utils.unwrapObservable(dataContext[_currentStatement.replace(/\(\)/g, '' )]);
  58                       }
  59                   }
  60               }
  61           };
  62  
 63           if  (_statements[0].search("\\u0024data") != -1 ) {
  64              _dataContext =  _$data;
  65          }  else   {
  66              _dataContext =  _$root;
  67           }
  68  
 69          _assignmentInContextByStatementsWithValue(_dataContext, _statements, _from, 0 );
  70       }
  71  }

还有Rhyme 为操作的定义自动生成了相应的操作代码:

  1  ( function (){ $( function (){initViewModel('PageLoaded', 'Evaluation' );}); })();
   2  
  3   var  saveData =  function  ($root, $data, event, target){window.appViewModel.doAction('SaveChanges','保存数据' ,  function  (viewModel, response) {  },  function   (xhr) {  });}
   4  
  5   var  changeValue =  function   ($root, $data, event, target){
   6      ClientEventHandlers.ChangeValue({ $root: $root, $data: $data, event: event, target: target, params: ['$root.mCourseList[0].Name', $root.mCourseList()[0].Desc] },  function (){  },  function  (){  });
   7   }
   8  
  9   var  changeValue1 =  function   ($root, $data, event, target){
  10      ClientEventHandlers.ChangeValue({ $root: $root, $data: $data, event: event, target: target, params: ['$root.mCourseList[*].Name', $root.mCourseList()[1].Desc] },  function (){  },  function  (){  });
  11   }
  12  
 13   var  openWindow =  function   ($root, $data, event, target){
  14      ClientEventHandlers.OpenWindow({ $root: $root, $data: $data, event: event, target: target, params: ['window1'] },  function (){  },  function  (){  });
  15  }

由于Rhyme比较懒惰,所以ViewModel定义了个通用的,当然,如果你不懒惰,定义N个慢慢玩玩后再决定是否也会学Rhyme偷懒吧。(:以后会慢慢完善:

  1   var  ViewModel =  function   (url, pageCode, initAction) {
   2  
  3       var  self =  this  ;
   4  
  5      self.url =  url;
   6      self.pageCode =  ko.observable(pageCode);
   7  
  8      self.loadData =  function   (dataHandler, successMsg, successCallBack, failureCallBack) {
   9           var  _data =  {};
  10           debugger  ;
  11          
 12           if  ( typeof  (dataHandler) === 'function' ) {
  13              _data =  dataHandler(ko.toJS(self));
  14           }
  15  
 16           $.ajax({
  17               url: self.url,
  18              data: { pageCode: _data.pageCode, actionName: _data.actionName, "datasource" : ko.toJSON(_data) },
  19              type: "POST" ,
  20              dataType: 'json' ,
  21              error:  function   (xhr) {
  22                   if  ( typeof  (failureCallBack) === 'function' ) {
  23                       try   {
  24                           failureCallBack(self, xhr);
  25                           MessageCenter.fromXhr(e);
  26                      }  catch   (e) {
  27                           MessageCenter.fromException(e);
  28                       }
  29                   }
  30               },
  31              success:  function   (response) {
  32                   if   (successMsg) {
  33                       MessageCenter.success(successMsg);
  34                   }
  35  
 36                   if  ( typeof  (successCallBack) === 'function' ) {
  37                       try   {
  38                           successCallBack(self, response);
  39                      }  catch   (e) {
  40                           MessageCenter.fromException(e);
  41                       }
  42                   }
  43               }
  44           });
  45          
 46           return   self;
  47       };
  48  
 49       //   Call service. 
 50      self.doAction =  function   (actionName, successMsg, successCallBack, failureCallBack) {
  51           debugger  ;
  52          self.loadData( function   (model) {
  53              model.actionName =  actionName;
  54  
 55               return   model;
  56           }, successMsg, successCallBack, failureCallBack);
  57       };
  58  
 59       //  self.saveChanges = function () { 
 60       //      self.doAction("SaveChanges", successMsg, function (viewModel, response) { 
 61       //          debugger; 
 62       //          ko.mapping.fromJS(response, {}, viewModel); 
 63       //      }); 
 64       //  }; 
 65  
 66      self.bind =  function  (element) {
  67           if  (element) {
  68               ko.applyBindings(self);
  69          }  else   {
  70               ko.applyBindings(self);
  71           }
  72       };
  73      
 74      ( function  (){
  75           if ( typeof (initAction) === 'function' ) {
  76               try   {
  77                   initAction(self);
  78              }  catch  (ex) {
  79                   //   init error 
 80               }
  81           }
  82       })();
  83  };

还有为了兼容万恶的IE, 不得不用JS来调整组件大小。Rhyme的布局是支持响应式布局的。当然,也是基于Bootstrap的。

  1  ( function   () {
   2      $( function   () {
   3           var  resizeControls =  function   (forVisible, containerSelector) {
   4               var  selectorTemplate = 'input[type="text"]{forVisible},input[type="password"]{forVisible},select{forVisible},textarea{forVisible}' ;
   5               var  selector = '' ;
   6  
  7               if  (forVisible ===  true  ) {
   8                  selector = selectorTemplate.replace(/{forVisible}/g, ':visible' );
   9              }  else   {
  10                  selector = selectorTemplate.replace(/{forVisible}/g, '' );
  11               }
  12  
 13               var  $resizeControl =  $(selector, containerSelector);
  14               var  totalControlForResize =  $resizeControl.length;
  15               for  ( var  i = 0; i < totalControlForResize; i++ ) {
  16  
 17                   var  currentControl =  $resizeControl.get(i),
  18                      $currentControl =  $(currentControl),
  19                      $parent = $currentControl.parents('.control-group' ),
  20                      $label = $parent.children('.control-label' );
  21                   if  ($label && $label.get(0)) { $currentControl.width($parent.get(0).offsetWidth - $label.get(0).offsetWidth - 15 ); }
  22                   else   {
  23                      $currentControl.width($parent.get(0).offsetWidth - 15 );
  24                   }
  25               }
  26           };
  27  
 28          resizeControls( true , '.controls' );
  29  
 30          window.onresize =  function   () {
  31              resizeControls( true , '.controls' );
  32           };
  33  
 34          $('[data-toggle="tab"]').live('click',  function   () {
  35               var  container = $( this ).attr('href' );
  36              resizeControls( false  , container);
  37           });
  38  
 39          $('[data-toggle="details"]').live('click',  function   () {
  40               var  container = $( this ).attr('data-toggle-target' );
  41              window.setTimeout( function  () { resizeControls( false , container); }, 10 )
  42           });
  43       });
  44  })();

Rhyme 也为布局提供了模版,类似母版页,当然,用的是HTML,生成后的也是纯HTML,由于服务于企业内部系统,所以没有对SEO做任何考虑。

View Code

Rhyme由于工作比较忙,所以难得抽出时间整理东西,接下来要是再有时间,会把那个语法解析的完善下,争取让Knockout中让人头疼的括号语法消失。Rhyme初步的想法是在绑定数据前对原有表达式语法重新解析,这样需要括号的地方就可以解析的时候在用代码插入了。有哪位有更好的想法请求分享一下。(:

Rhyme接下来的源代码会托管到GitHub,也会在博客园放下载,大家共同学习,也多帮我找找Bug,提点不足,在这里先行谢过了。

 

 

 

标签:  XSL ,  XSLT ,  代码生成 ,  Javascript MVVM ,  Javascript MVC ,  数字输入 ,  语法分析

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Knockot JS 数字输入插件的详细内容...

  阅读:43次