2014年7月29日 星期二

如何透過MSBuild 的過程中 COPY 檔案

最近有一個內部專案

我們想要利用 TFS 進行 自動化建置部署


所以開始動工吧!

我們新增一個組建

圖1


圖2

圖3

設定MSBuild的Config 如下:

/P:VisualStudioVersion=12.0 /P:DeployOnBuild=True /P:DeployTarget=MSDeployPublish /P:MsDeployServiceUrl=https://TESTWEB2:8172/msdeploy.axd /P:AllowUntrustedCertificate=True  /P:MSDeployPublishMethod=WMSvc /P:DeployIisAppPath=xxxxx   /P:CreatePackageOnPublish=True   /P:UserName=帳號/P:Password=密碼

接下來測試一下!
新增一個佇例一個新的組建。



完成後發現,程式是無法執行的原因是

缺少DLL檔

所以我們必需要針對MSBuild進行客製化,將我們需要的檔案移轉到我們要進行Deploy的Package的目錄,讓部署的時侯可以包含這些檔案。

但是如何客製化呢?
請這樣做

先卸載專案

編輯專案檔
請在文件最後面的地方加上


 
<ItemGroup  >
    <BinFiles Include="$(OutDir)**\*.dll" />
    <SourceFile Include="@(BinFiles)" />
 </ItemGroup>
  
<Target Name="AdditionalFilesForPackage" AfterTargets="CopyAllFilesToSingleFolderForMsdeploy">
    <Message Text="Test COPY Binaries Dll Start"/>
    <Copy SourceFiles="%(SourceFile.FullPath)" DestinationFolder="$(_PackageTempDir)\bin" Condition="$([System.String]::Copy(%(SourceFile.Filename)).Contains('關鍵字'))" />
    <Message Text="Test COPY Binaries Dll End"/></Target>

上面的行為如下:

我們定義二個 itemgroup 分別為:BinFiles 、SourceFile
BinFiles 我們定義的是MSBuild時,產生的路徑中全部的DLL檔案
SourceFile 我們定義的是使用 BinFiles的路徑

接下來 目標 Target 動作

我們定義了二個properties
 AfterTargets(在這個事件之後) CopyAllFilesToSingleFolderForMsdeploy 我們要執行下列動作
Name AdditionalFilesForPackage 這個是在LOG會顯示的TAG

Message: 顯示在LOG上的訊息
Copy:我們要COPY的檔案路徑、目標位置、條件
詳細內容請參考 :MSDN

以上動作就會將DLL COPY到PackageTempDir 讓MSDeploy進行封裝的動作。

比較困難的地方是語法的設定,因為MSDN上也沒有寫的非常的清楚。



2014年6月11日 星期三

Mask 遮罩延遲顯示的狀況

前一陣子碰到一問題!
先前寫過一個遮罩的功能,可以讓PG呼叫遮罩,然後進行AJAX處理

讓使用者等待畫面處理完成!

最近有人反應,他們使用後發現,部份的頁面會產生延遲顯示的狀況!!
也就是遮罩不會馬上顯示~

便開始追查問題

首先先用chrome來進行Timeline的錄製

發現當我按下儲存的時侯(click事件)

畫面就停住了,便產生了大量的GC javascript Heap高達 94MB

所以針對程式一看~

嗯,事出必有因,畫面的行為如下:

1、畫面上有近1000個checkbox
2、當按下送出的時侯會針對checkbox 進行取值,有選取的就加入陣例(透過Each的方式)

想了一下,這應該是因為進行了javascript的大量運算,所以遮罩完全跑不出來 UI的Thread就停了

所以便寫了一個測試程式:
1、產生一個簡單的For計算,j++
  var j = 0;
  for (var i = 0; i < 1000000000; i++) {//讓JS產生一個大量運算
   j++;
  }
 console.log(j);
2、透過Deferred 物件,保證執行完成
var dtd = $.Deferred(); // 新建deferred

3、透過setTimeout 讓畫面延遲5秒,直到動畫完成
 setTimeout(tasks, 5000); // 停頓5秒

這邊可能有人覺得奇怪,為何還要設定SetTimeout 5秒後才執行程式
我們已經使用了Deferred的物件了,應該可以保證事件執行完成
但是經過測試,我們確實是保證物件有執行了,但~因為我們後續馬上執行了一個大量運算
其實是會導致Browser偵測到一個JS佔用到太多CPU,而產生停止的訊息,所以導致動畫也無法完整執行完畢

失敗
               var dtd = $.Deferred(); // 新建deferred

                var show = function (dtd) {
                    var tasks = function () { //裡面請放置你的主程式!
                        funOpenLoadingMask(true);
                        dtd.resolve(); // deferred的狀態改變
                    };
                    tasks();
                    return dtd.promise();
                };

                $.when(show(dtd))
                .then(function () {
                    var j = 0;
                    for (var i = 0; i < 1000000000; i++) {//讓JS產生一個大量運算
                        j++;
                    }
                    console.log(j);
                }).done(funOpenLoadingMask(false))

成功
                 var show = function (dtd) {
                    funOpenLoadingMask(true);

                    var tasks = function () { //裡面請放置你的主程式!
                        var j = 0;
                        for (var i = 0; i < 1000000000; i++) {//讓JS產生一個大量運算
                            j++;
                        }
                        console.log(j);
                        dtd.resolve(); // deferred的狀態改變
                    };
              
                    setTimeout(tasks, 5000); // 停頓5秒
                    return dtd.promise();
                };
               
                $.when(show(dtd))
               .then(function () {
                    funOpenLoadingMask(false);
                });


附上檔案

2014年6月9日 星期一

Kendo UI Validator 的客制化顯示方式

接到一個需求,是需要將畫面上的Validation 進行客制化的設計!
一般來說,原本的 Kendo UI Validator 顯示畫面如下:


使用者的需求如下:
  1、發生問題輸入元件要變成紅色外框
  2、預設不顯示訊息
  3、要透過ToolTip的方式顯示
  4、當滑鼠移到元件上時,就顯示ToolTip

作法如下:

1、首先需要設定每一個INPUT的專屬訊息

<label class="required" for="fullname">Your Name</label>
<input class="k-textbox" id="fullname" name="fullname" placeholder="Full name" required="" type="text" validationmessage="Please enter {0}" />
<span class="k-invalid-msg" data-for="fullname"></span><!--  專屬的顯示 -->

2、撰寫CSS
   
            /*toolTip 的顏色*/
            .k-widget.k-tooltip {
                border-color: rgb(197, 197, 197);
                background-color: red;
                color: white;
            }

            /*讓textbox顯示有紅框,因為此方法為預設的行為。*/
            .k-invalid,
            .k-textbox.k-invalid {
                border: 1px solid #ee0101;
            }

            /*加入紅框給kendo ui的元件使用*/
            .UIBorderRed {
                border: 1px solid #ee0101 !important;
            }

            /*預設的errorTip樣式*/
            .errorTip {
                background-color: #ee0101;
                color: #fff;
                float: right;
                font-size: 12px;
                border: 2px solid #ddd;
                -moz-box-shadow: 0 0 6px #000;
                -webkit-box-shadow: 0 0 6px #000;
                padding: 4px 10px 4px 10px;
                border-radius: 6px;
                -webkit-border-radius: 6px;
                position: absolute;
                opacity: 0.87;
                display: none !important;
            }
           /*顯示的errorTip樣式*/
            .errorTipShow {
                background-color: #ee0101;
                color: #fff;
                float: right;
                font-size: 12px;
                border: 2px solid #ddd;
                -moz-box-shadow: 0 0 6px #000;
                -webkit-box-shadow: 0 0 6px #000;
                padding: 4px 10px 4px 10px;
                border-radius: 6px;
                -webkit-border-radius: 6px;
                position: fixed;
                opacity: 0.87;
                display: block !important;;
            }
3、建立主要程式
                
//主要的程式:驗證控制項
var validator = $("#tickets").kendoValidator({
                    rules: {
                        required: function (input) {
                             return PICRule(input);//客制化rule
                        }
                    },
                    errorTemplate: kendo.template( '<div class="errorTip k-widget k-tooltip k-popup"><div class="k-tooltip-content">#=message#</div><div class="k-callout k-callout-s"></div></div>')//樣版
                });
4、設計RULE
var PICRule = function (input){
                     var e = input.filter("[type=checkbox]").length && !input.is(":checked"),//如果是checkbox
                                    a = input.val();//輸入值
                            
                             //驗證規則,判斷是不是null或是不是一個物件,
                             var _ = function (t, e) { return t.length ? null != t[0].attributes[e] : !1 };
                             var ChangeBorder = function (Input) {
                                         return {
                                          Add: function AddClass() {

                                           var str = $(Input).parent();

                                            if (str != undefined && (str.hasClass("k-state-default") || str.hasClass("k-widget") )) {

                                            if ($(Input).parent().find('.k-state-default').length > 0) {
                                             // log($(Input));
                                            $(Input).parent().find('.k-state-default').addClass("UIBorderRed");
                                             } else {
                                                  //  log($(Input));
                                                  $(Input).parent().addClass("UIBorderRed");
                                             }

                                             }

                                                 if ($(Input).attr('type') == "checkbox") {
                                                                //log($(Input));
                                                                $(Input).parent().addClass("UIBorderRed");
                                                            }
                                                        },
                                                        Remove: function RemoveClass() {
                                                             //log($(Input));
                                                            $(Input).parent().find('.UIBorderRed').andSelf().removeClass("UIBorderRed");

                                                        }
                                                    }
                            };

                                var requiredChangeBorder = function (input, e, a) {
                                    var changeBorder = ChangeBorder(input);
                                    if (!("" === a || !a || e)) {
                                        changeBorder.Remove();
                                    }
                                    else {
                                        changeBorder.Add();

                                    }
                                };
                          requiredChangeBorder(input, e, a);
5、針對需要使用的資料進行綁定
                        //為kendo ui 客制化元件
                        $("form .k-widget").bind("mouseenter",function () {
                            var $inputElement = $(this).find(".k-invalid");
                            var position = $(this).position();
                            //log(position.top);
                            // log(position.left);
                            if($inputElement.length >0){//有該元素在
                              var elementName = "div[data-for='" + $inputElement.attr('name') + "']";
                                //log(elementName);
                                $(elementName).addClass('errorTipShow').css({"left" : position.left ,"top" : position.top - 25});
                            }
                        
                        }).bind("mouseleave",function () {
                            var $inputElement = $(this).find(".k-invalid");
                            var elementName = "div[data-for='" + $inputElement.attr('name') + "']";
                                $(elementName).removeClass('errorTipShow').removeAttr('style');
                        });

                        //為input類型的元件
                        $("form :input").bind("mouseenter",function () {
                            var $inputElement = $(this);
                            var position = $(this).position();
                             if (!$(this).parent().hasClass("k-widget") && !$(this).parent().parent().hasClass("k-widget")){//排除Kendo UI複合元件
                                //log($(this).parent());
                            
                                if($inputElement.hasClass("k-invalid")){//如果有錯誤發生
                                  var elementName = "div[data-for='" + $inputElement.attr('name') + "']";
                                   //log(elementName);
                                    $(elementName).addClass('errorTipShow').css({"left" : position.left ,"top" : position.top - 25});
                                }
                            }
                        }).bind("mouseleave",function () {
                            var $inputElement = $(this);
                            var elementName = "div[data-for='" + $inputElement.attr('name') + "']";
                                $(elementName).removeClass('errorTipShow').removeAttr('style');;
                        });

最後測試一下結果:
附上檔案