好得很程序员自学网

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

持续集成之道:在你的开源项目中使用Travis CI

持续集成之道:在你的开源项目中使用Travis CI

持续集成之道:在你的开源项目中使用Travis CI

自从接触并践行了敏捷的一些实践之后,便深深的喜欢上了敏捷。尤其是测试自动化和持续集成这两个实践,可以显著的提高软件的质量和集成效率,实时检测项目健康度,使团队成员对项目保持充足的信心。

 

但是对于个人项目而言,虽然测试自动化好实现,但是要实现持续集成还是稍有难度。因为持续集成需要搭建一个集成服务器,并建立某种反馈机制。而大多数人来说并没有自己的独立服务器,并且配置也极为繁琐。

 

不过不用怕,现在已经进入了云时代。  Travis CI 为我们提供了免费的集成服务器,让我们省却了自己搭建集成服务器的烦恼。

 

Travis CI 的官网介绍是:  A hosted continuous integration service for the open source community.  表明它主要是给开源社区提供持续集成服务。其与github这个全球最火爆的代码托管网站高度集成,可以很方便的为github中的项目建立持续集成服务。

 

它不仅支持多种语言,而且支持同时在多个运行环境中运行build,能全方位的测试你的程序。

 

下面就介绍下如何将 Travis CI 与自己在github上的某个repository集成。(这里以我自己的repository  https://github.com/huangbowen521/SpringMessageSpike  为例。 )

 

首先,使Travis CI通过github OAuth认证。

 

点击 https://travis-ci.org/ 右上角的 Sign in with GitHub 按钮,输入自己的github账号和密码,并允许Travis CI的认证。

 

然后,激活GitHub Service Hook。

 

GitHub给用户提供了一个Service Hook接口,只要用户对host在github上的repository作用了一些action(比如push,pull),就会触发相应的Service Hook。而 Travis CI 正是基于这个原理来trigger你的build。当你发起一个push操作时,就会trigger  Travis CI 的服务。

 

设置方法是访问 Travis CI 的 profile ,选择相应的repository打开Service Hook开关。

 

 

然后登陆你的github,访问具体的repository的Service Hook页面,确保设置了Travis CI Hook的github name和travis token。

 

 

最后,给repository配置.travis.yml文件。该文件需要放置在repository的跟目录下。

 

.travis.yml文件是一个相当重要的文件,里面需要配置你所使用的语言、运行环境、构建工具、构建脚本、通知方式等。最重要的是设置语言,其它的都有相应的默认值。

 

这是为我的 SpringMessageSpike 设置的.travis.yml文件。由于我的项目中使用了maven作为构建工具,而 Travis CI 对java语言设置的默认构建工具就是maven,所以无需在文件中显式指定。

.travis.yml

 1 
 2 
 3 
 4 
 5 
   language  :   java 
   jdk  : 
     -   oraclejdk7 
     -   openjdk7 
     -   openjdk6 
  

 

你可以使用一个travis-lint来检查你的yml文件是否是有效的。他是ruby写的一个gem,需要ruby的运行环境。安装方式是在terminal下 gem install travis-lint 。你只需要在你的repository根目录下运行 travis-lint 即可进行检查。

 

想要更进一步的关于.travis.yml的配置请参见: http://about.travis-ci.org/docs/user/build-configuration/

 

只要这三步就完成了配置。现在发起一个push就可以trigger你在 Travis CI 的build。 这时候登陆 Travis CI 可以看到你的Build的状态和日志。

 

 

你可以在respository的README.md文件中加入build状态图标。方法是在在该文件中加入  [![Build Status](https://travis-ci.org/[YOUR_GITHUB_USERNAME]/[YOUR_PROJECT_NAME].png)](https://travis-ci.org/[YOUR_GITHUB_USERNAME]/[YOUR_PROJECT_NAME]) 即可。

 

 

总体来说 Travis CI 是一个轻量级、可高度定制化的免费的持续集成服务。但我觉得还是有几个缺点:

 

运行build需要大量的准备,耗时较长。

作为免费的服务,不支持build时间超过20分钟的项目。

主站访问速度略慢。

Table中对tr的上下拖拽移动

  前天公司门户网站中新闻发布后写好的新闻想实现手动上下换位置。在网上找了一个专门为table写的js,有源码,可以自己改样式,动态效果。

正文开始:

首先需要引用一个js:

  jquery

jQuery.tableDnD =  {
      /*  * Keep hold of the current table being dragged   */  
    currentTable :   null  ,
      /*  * Keep hold of the current drag object if any   */  
    dragObject:   null  ,
      /*  * The current mouse offset   */  
    mouseOffset:   null  ,
      /*  * Remember the old value of Y so that we don't do too much processing   */  
    oldY:  0 ,

      /*  * Actually build the structure实际构建结构   */  
    build:   function  (options) {
          //   Set up the defaults if any 

         this .each( function  () {
              //   This is bound to each matching table, set up the defaults and override with user options这是绑定到每个匹配表,设置默认值,并与用户选项覆盖 
             this .tableDnDConfig =  jQuery.extend({
                onDragStyle:   null  ,
                onDropStyle:   null  ,
                  //   Add in the default class for whileDragging 
                onDragClass: "tDnD_whileDrag" ,
                onDrop:   null  ,
                onDragStart:   null  ,
                scrollAmount:  5 ,
                serializeRegexp:  /[^\-]*$/,  //   The regular expression to use to trim row IDs 
                serializeParamName:  null ,  //   If you want to specify another parameter name instead of the table ID 
                dragHandle:  null   //   If you give the name of a class here, then only Cells with this class will be draggable 
            }, options ||  {});
              //   Now make the rows draggable 
            jQuery.tableDnD.makeDraggable( this  );
        });

          //   Now we need to capture the mouse up and mouse move event 
         //   We can use bind so that we don't interfere with other event handlers 
         jQuery(document)
            .bind( 'mousemove' , jQuery.tableDnD.mousemove)
            .bind( 'mouseup' , jQuery.tableDnD.mouseup);

          //   Don't break the chain 
         return   this  ;
    },

      /*  * This function makes all the rows on the table draggable apart from those marked as "NoDrag"   */  
    makeDraggable:   function  (table) {
          var  config =  table.tableDnDConfig;
          if   (table.tableDnDConfig.dragHandle) {
              //   We only need to add the event to the specified cells 
             var  cells = jQuery("td."+ table.tableDnDConfig.dragHandle, table);
            cells.each(  function  () {
                  //   The cell is bound to "this" 
                jQuery( this ).mousedown( function  (ev) {
                    jQuery.tableDnD.dragObject  =  this  .parentNode;
                    jQuery.tableDnD.currentTable  =  table;
                    jQuery.tableDnD.mouseOffset  = jQuery.tableDnD.getMouseOffset( this  , ev);
                      if   (config.onDragStart) {
                          //   Call the onDrop method if there is one 
                        config.onDragStart(table,  this  );
                    }
                      return   false  ;
                });
            })
        }   else   {
              //   For backwards compatibility, we add the event to the whole row 
             var  rows = jQuery("tr", table);  //   get all the rows as a wrapped set 
            rows.each( function  () {
                  //   Iterate through each row, the row is bound to "this" 
                 var  row = jQuery( this  );
                  if  (! row.hasClass("nodrag" )) {
                    row.mousedown(  function  (ev) {
                          if  (ev.target.tagName == "TD" ) {
                            jQuery.tableDnD.dragObject  =  this  ;
                            jQuery.tableDnD.currentTable  =  table;
                            jQuery.tableDnD.mouseOffset  = jQuery.tableDnD.getMouseOffset( this  , ev);
                              if   (config.onDragStart) {
                                  //   Call the onDrop method if there is one 
                                config.onDragStart(table,  this  );
                            }
                              return   false  ;
                        }
                    }).css( "cursor", "move");  //   Store the tableDnD object 
                 }
            });
        }
    },

    updateTables:   function  () {
          this .each( function  () {
              //   this is now bound to each matching table 
             if  ( this  .tableDnDConfig) {
                jQuery.tableDnD.makeDraggable(  this  );
            }
        })
    },

      /*  * Get the mouse coordinates from the event (allowing for browser differences)   */  
    mouseCoords:   function  (ev){
          if (ev.pageX ||  ev.pageY){
              return   {x:ev.pageX, y:ev.pageY};
        }
          return   {
            x:ev.clientX  + document.body.scrollLeft -  document.body.clientLeft,
            y:ev.clientY  + document.body.scrollTop  -  document.body.clientTop
        };
    },

      /*  * Given a target element and a mouse event, get the mouse offset from that element.
        To do this we need the element's position and the mouse position   */  
    getMouseOffset:   function  (target, ev) {
        ev  = ev ||  window.event;

          var  docPos    =  this  .getPosition(target);
          var  mousePos  =  this  .mouseCoords(ev);
          return  {x:mousePos.x - docPos.x, y:mousePos.y -  docPos.y};
    },

      /*  * Get the position of an element by going up the DOM tree and adding up all the offsets   */  
    getPosition:   function  (e){
          var  left = 0 ;
          var  top  = 0 ;
          /*  * Safari fix -- thanks to Luis Chato for this!   */ 
         if  (e.offsetHeight == 0 ) {
              /*  * Safari 2 doesn't correctly grab the offsetTop of a table row
            this is detailed here:
            http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
            the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
            note that firefox will return a text node as a first child, so designing a more thorough
            solution may need to take that into account, for now this seems to work in firefox, safari, ie   */  
            e  = e.firstChild;  //   a table cell 
         }

          while   (e.offsetParent){
            left  +=  e.offsetLeft;
            top   +=  e.offsetTop;
            e      =  e.offsetParent;
        }

        left  +=  e.offsetLeft;
        top   +=  e.offsetTop;

          return   {x:left, y:top};
    },

    mousemove:   function  (ev) {
          if  (jQuery.tableDnD.dragObject ==  null  ) {
              return  ;
        }

          var  dragObj =  jQuery(jQuery.tableDnD.dragObject);
          var  config =  jQuery.tableDnD.currentTable.tableDnDConfig;
          var  mousePos =  jQuery.tableDnD.mouseCoords(ev);
          var  y = mousePos.y -  jQuery.tableDnD.mouseOffset.y;
          //  auto scroll the window 
         var  yOffset =  window.pageYOffset;
           if   (document.all) {
              //   Windows version 
             //  yOffset=document.body.scrollTop; 
             if  ( typeof  document.compatMode != 'undefined' && 
                 document.compatMode  != 'BackCompat' ) {
               yOffset  =  document.documentElement.scrollTop;
            }
              else   if  ( typeof  document.body != 'undefined' ) {
               yOffset = document.body.scrollTop;
            }

        }
            
          if  (mousePos.y-yOffset <  config.scrollAmount) {
            window.scrollBy( 0, - config.scrollAmount);
        }   else   {
              var  windowHeight = window.innerHeight ?  window.innerHeight
                    : document.documentElement.clientHeight  ?  document.documentElement.clientHeight : document.body.clientHeight;
              if  (windowHeight-(mousePos.y-yOffset) <  config.scrollAmount) {
                window.scrollBy( 0 , config.scrollAmount);
            }
        }


          if  (y !=  jQuery.tableDnD.oldY) {
              //   work out if we're going up or down... 
             var  movingDown = y >  jQuery.tableDnD.oldY;
              //   update the old value 
            jQuery.tableDnD.oldY =  y;
              //   update the style to show we're dragging 
             if   (config.onDragClass) {
                dragObj.addClass(config.onDragClass);
            }   else   {
                dragObj.css(config.onDragStyle);
            }
              //   If we're over a row then move the dragged row to there so that the user sees the 
             //   effect dynamically 
             var  currentRow =  jQuery.tableDnD.findDropTargetRow(dragObj, y);
              if   (currentRow) {
                  //   TODO worry about what happens when there are multiple TBODIES 
                 if  (movingDown && jQuery.tableDnD.dragObject !=  currentRow) {
                    jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
                }   else   if  (! movingDown && jQuery.tableDnD.dragObject !=  currentRow) {
                    jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
                }
            }
        }

          return   false  ;
    },

      /*  * We're only worried about the y position really, because we can only move rows up and down   */  
    findDropTargetRow:   function  (draggedRow, y) {
          var  rows =  jQuery.tableDnD.currentTable.rows;
          for  ( var  i=0; i<rows.length; i++ ) {
              var  row =  rows[i];
              var  rowY    =  this  .getPosition(row).y;
              var  rowHeight = parseInt(row.offsetHeight)/2;
             if  (row.offsetHeight == 0 ) {
                rowY  =  this  .getPosition(row.firstChild).y;
                rowHeight  = parseInt(row.firstChild.offsetHeight)/2;
             }
              //   Because we always have to insert before, we need to offset the height a bit 
             if  ((y > rowY - rowHeight) && (y < (rowY +  rowHeight))) {
                  //   that's the row we're over 
                 //   If it's the same as the current row, ignore it 
                 if  (row == draggedRow) { return   null  ;}
                  var  config =  jQuery.tableDnD.currentTable.tableDnDConfig;
                  if   (config.onAllowDrop) {
                      if   (config.onAllowDrop(draggedRow, row)) {
                          return   row;
                    }   else   {
                          return   null  ;
                    }
                }   else   {
                      //   If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic) 
                     var  nodrop = jQuery(row).hasClass("nodrop" );
                      if  (!  nodrop) {
                          return   row;
                    }   else   {
                          return   null  ;
                    }
                }
                  return   row;
            }
        }
          return   null  ;
    },

    mouseup:   function  (e) {
          if  (jQuery.tableDnD.currentTable &&  jQuery.tableDnD.dragObject) {
              var  droppedRow =  jQuery.tableDnD.dragObject;
              var  config =  jQuery.tableDnD.currentTable.tableDnDConfig;
              //   If we have a dragObject, then we need to release it, 
             //   The row will already have been moved to the right place so we just reset stuff 
             if   (config.onDragClass) {
                jQuery(droppedRow).removeClass(config.onDragClass);
            }   else   {
                jQuery(droppedRow).css(config.onDropStyle);
            }
            jQuery.tableDnD.dragObject    =  null  ;
              if   (config.onDrop) {
                  //   Call the onDrop method if there is one 
                 config.onDrop(jQuery.tableDnD.currentTable, droppedRow);
            }
            jQuery.tableDnD.currentTable  =  null ;  //   let go of the table too 
         }
    },

    serialize:   function  () {
          if   (jQuery.tableDnD.currentTable) {
              return   jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable);
        }   else   {
              return  "Error: No Table id set, you need to set an id on your table and every row" ;
        }
    },

    serializeTable:   function  (table) {
          var  result = "" ;
          var  tableId =  table.id;
          var  rows =  table.rows;
          for  ( var  i=0; i<rows.length; i++ ) {
              if  (result.length > 0) result += "&" ;
              var  rowId =  rows[i].id;
              if  (rowId && rowId && table.tableDnDConfig &&  table.tableDnDConfig.serializeRegexp) {
                rowId  = rowId.match(table.tableDnDConfig.serializeRegexp)[0 ];
            }

            result  += tableId + '[]=' +  rowId;
        }
          return   result;
    },

    serializeTables:   function  () {
          var  result = "" ;
          this .each( function  () {
              //   this is now bound to each matching table 
            result += jQuery.tableDnD.serializeTable( this  );
        });
          return   result;
    }

}

jQuery.fn.extend(
    {
        tableDnD : jQuery.tableDnD.build,
        tableDnDUpdate : jQuery.tableDnD.updateTables,
        tableDnDSerialize: jQuery.tableDnD.serializeTables
    }
); 

里面的

  View Code

 this .each( function  () {
              //   This is bound to each matching table, set up the defaults and override with user options这是绑定到每个匹配表,设置默认值,并与用户选项覆盖 
             this .tableDnDConfig =  jQuery.extend({
                onDragStyle:   null  ,
                onDropStyle:   null  ,
                  //   Add in the default class for whileDragging 
                onDragClass: "tDnD_whileDrag" ,
                onDrop:   null  ,
                onDragStart:   null  ,
                scrollAmount:  5 ,
                serializeRegexp:  /[^\-]*$/,  //   The regular expression to use to trim row IDs 
                serializeParamName:  null ,  //   If you want to specify another parameter name instead of the table ID 
                dragHandle:  null   //   If you give the name of a class here, then only Cells with this class will be draggable 
            }, options ||  {});
              //   Now make the rows draggable 
            jQuery.tableDnD.makeDraggable( this  );
        }); 

是为控制拖拽样式,拖拽的元素的控制,里面还有好多自定义模式的自己可以看看发觉下。

源码下载: Table拖拽

作者: Leo_wl

    

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

    

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

版权信息

查看更多关于持续集成之道:在你的开源项目中使用Travis CI的详细内容...

  阅读:35次