over 4 years ago

使用 xwork-core-2.3.24.jar
參照 xwork-validator-1.0.2.dtd DOCTYPE 設定
修正 xxxx-validation.xml 的 DOCTYPE 內容

<!DOCTYPE validators PUBLIC 
        "-//Apache Struts//XWork Validator 1.0.2//EN"
        "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
 
over 4 years ago

Eclipse 出現底下 Exception

Exception starting filter struts2
java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils

主要是 lib 忘記導入 commons-lang3-3.2.jar

 
over 4 years ago

如果在 A頁面 轉跳到 B頁面後使用 document.referrer
會因瀏覽器的版本而得到不一樣的來源Url
可在 A頁面使用底下語來轉跳到 B頁面
讓 document.referrer 能正常取得來源Url

function gotoUrl(url){
    var referLink = document.createElement('a');
    referLink.href = url;
    document.body.appendChild(referLink);
    referLink.click();
}
 
over 4 years ago

底下當 learners.remove 時會出現 java.util.ConcurrentModificationException
原因是再each刪除陣列元素後 index 指標溢位的問題
因為 each 執行中不會檢查陣列數的變化

for(Object learner : learners){
    RecordObject user = (RecordObject)learner;
    if(ignoreList.contains(user.getInt("UserId"))){
        learners.remove(learner);
    }
}

改寫方式一 使用 for

for(int i = 0; i < learners.size(); i++){
    RecordObject user = (RecordObject)learners.get(i);
    int sessionId = user.getInt("SessionId");
    int courseId = user.getInt("CourseId");
    int userId = user.getInt("UserId");

    if(isTRLearnerBy(courseId, sessionId, userId) && !ignoreList.contains(user.getInt("UserId"))){
        learners.remove(i);
        i = i - 1; // 因 for 最後會做 i++ 所以必須將 i 維持在刪除時 index 再往下
    }
}

改寫方式二 使用 Iterator

Iterator<RecordObject> sListIterator = learners.iterator(); 
while(sListIterator.hasNext()){
    RecordObject user = (RecordObject)sListIterator.next();
    int sessionId = user.getInt("SessionId");
    int courseId = user.getInt("CourseId");
    int userId = user.getInt("UserId");

    if(isTRLearnerBy(courseId, sessionId, userId) && !ignoreList.contains(user.getInt("UserId"))){
        sListIterator.remove();
    }
}
 
almost 6 years ago

練習寫 Validate Plugin
可以自訂驗證函數跟設定群組
= =+不過 selector 在IE 8 有點小問題改了一下條件...

/*
 * Validate Plugin
 *  範例
 *  <ReqExp group="A" checkId="name" check="empty" error="請輸入姓名" />
 *  <ReqExp group="B" checkId="phone" check="compareTo" compareid="tel" error="手機電話不相同" />
 *
 *  ReqExp 屬性介紹
 *  group 群組
 *  checkId 檢查的ID
 *  check 檢查的函數名稱
 *  error 錯誤訊息
 *
 *  $("#btnA").myValidate();
 *  
 *  $("#btnB").myValidate({
 *      group: "B",
 *      // 自訂驗證函數 val 為 checkId 的值 reqExp 為 ReqExp 標籤物件 check="checkNum"
 *      checkNum:  function(val, reqExp) {
 *          if(val == "") {
 *              return true;
 *          }
 *          var regu = "[0-9]";
 *          var re = new RegExp(regu);
 *          return re.test(val);
 *      }
 *  });
 *  
 *  說明
 * submitForm 設定要 submit 的表單id
 * bind 綁定的事件
 * group 驗證群組
 * 預設的驗證函數  val 為 checkId 的值   reqExp 為 ReqExp 標籤物件
 * 可自訂加入驗證函數
 *  compareTo: function(val, reqExp) {
 *          var compareValue = $("#" + reqExp.attr("compareid")).val();
 *          compareValue = compareValue.replace(/\r\n|\r|\n/g, '');     
 *           
 *          if(val != compareValue) {
 *              return false;
 *          } else {
 *              return true;
 *          }
 *  },
 * alertDesc alert 警訊的事件 可自行覆蓋修改
 * mySubmit Submit 事件 可自行覆蓋修改
 * resultData 物件屬性
 *    resultData.alertErrorDesc 錯誤訊息
 *    resultData.checkResult  驗證結果 true or false
 *    resultData.submitForm submit 表單id
 */
$.fn.myValidate = function (settings) {
    // 預設屬性
    var _defaultSettings = {
        submitForm: "form1",
        bind: "click",
        group: "A",
        
        empty: function (val, reqExp) {
            if(val == "") {
                return false;
            }
         
            var regu = "^[ ]+$";
            var re = new RegExp(regu);
             
            return !re.test(val);
        },
        
        compareTo: function(val, reqExp) {
            var compareValue = $("#" + reqExp.attr("compareid")).val();
            compareValue = compareValue.replace(/\r\n|\r|\n/g, '');     
             
            if(val != compareValue) {
                return false;
            } else {
                return true;
            }
        },
        
        alertDesc: function (resultData) {
            alert(resultData.alertErrorDesc);
        },
        
        mySubmit: function (resultData) {
            $("#" + resultData.submitForm).submit();
        }
    }   
    
    var _settings = $.extend(_defaultSettings, settings);
    
    var _validateMethods = {
        eachReqExp : function() {
            
            $("ReqExp").each(function() { 
                
                if ($(this).attr("group") == _settings.group) {
                    var checkValue = "";
                
                    checkValue = $("#" + $(this).attr("checkid")).val();
                    checkValue = checkValue.replace(/\r\n|\r|\n/g, '');
                
                    var checkMethod = $(this).attr("check");
                
                    if (!_settings[checkMethod](checkValue, $(this))) {
                        _settings.alertErrorDesc += $(this).attr("error") + "\n";
                    }
                }
            });
            
            if (_settings.alertErrorDesc != "") {
                _settings.checkResult = false;
            } else {
                _settings.checkResult = true;
            }
        }
    }
    
    var _handler = function () {
        // 綁定事件
        var this_object = $(this);
        this_object.bind(_settings.bind, function() {
            
            _settings.checkResult = true;
            _settings.alertErrorDesc = "";
            
            // 搜尋驗證物件
            _validateMethods.eachReqExp();
            // 建立結果
            var resultData = {};
            resultData.alertErrorDesc = _settings.alertErrorDesc;
            resultData.checkResult = _settings.checkResult;
            resultData.submitForm = _settings.submitForm;
            
            if (resultData.checkResult == false) {
                _settings.alertDesc(resultData);
            }
            
            if (resultData.checkResult == true) {
                _settings.mySubmit(resultData);
            }
        });
    }
    
    return this.each(_handler);
}
 
almost 6 years ago

寫個讓 client 端去產生分頁的 Plugin
這樣 server 端只要計算 總頁數 跟 現在頁碼 和 指定的網址 到 html 的 Plugin 就好了
也可以控制顯示的分頁模式和利用 callback 接收 data 分頁容器來做修改
不過頁碼還真是不好拿捏.....XD感覺會有bug

/*
 * 分頁 plugin
 *  範例
 *  
 *  <div id="page"></div>
 *  
 *  $("#page").myPageLink(
 *          {
 *              sumPages: 40,
 *              currentPage:6,
 *              pageSize:5,
 *              pageUrl: "plugin.html?",
 *              pageParamName: "p",
 *              firstDesc: "<<",
 *              lastDesc: ">>",
 *              preDesc: "<",
 *              nextDesc: ">",
 *              callback: function (data) {
 *                  //alert(data.html())
 *              }
 *          }
 *  );
 *  說明
 *      sumPages: 30,    總頁數
 *      currentPage: 5, 現在頁碼
 *      pageSize:5,         每排頁碼數目
 *      pageUrl: "plugin.html?", 綁定網址
 *      pageParamName: "page", 分頁參數名稱
 *      firstDesc: "第一頁", 第一頁名稱
 *      lastDesc: "最末頁", 最末頁名稱
 *      preDesc: "上一頁", 上一頁名稱
 *      nextDesc: "下一頁", 下一頁名稱
 *      preAndNextDesc: "...",  尚有頁碼注解
 *      isSetFirst: true, 啟用否 第一頁
 *      isSetLast: true, 啟用否 最末頁
 *      isSetPre: true, 啟用否 上一頁
 *      isSetNext: true, 啟用否 下一頁
 *      isSetPreAndNextDesc: true, 啟用否 尚有頁碼注解
 *      callback: function (data) {} 回傳 分頁容器  物件
 */
$.fn.myPageLink = function (settings) {
    // 預設屬性
    var _defaultSettings = {
        sumPages: 30,
        currentPage: 5,
        pageSize:5,
        pageUrl: "plugin.html?",
        pageParamName: "page",
        firstDesc: "第一頁",
        lastDesc: "最末頁",
        preDesc: "上一頁",
        nextDesc: "下一頁",
        preAndNextDesc: "...",
        isSetFirst: true,
        isSetLast: true,
        isSetPre: true,
        isSetNext: true,
        isSetPreAndNextDesc: true,
        callback: function (data) {}
    }   
    
    var _settings = $.extend(_defaultSettings, settings);
    
    var _pageMethods = {
            bindFirstPage: function() {
                if (_settings.currentPage != 1 && _settings.isSetFirst == true) {
                    _settings.pageContent += '<a id="1" href="' + _settings.pageUrl + 
                                _settings.pageParamName + '=1">' + _settings.firstDesc + '</a>';
                }
            },
            bindLastPage: function() {
                if (_settings.currentPage != _settings.sumPages && _settings.isSetLast == true) {
                    _settings.pageContent += '<a id="' + _settings.sumPages + '" href="' + _settings.pageUrl + 
                                _settings.pageParamName + '=' + _settings.sumPages + '">' + _settings.lastDesc + '</a>';
                }
            },
            bindPrePage: function() {
                if (_settings.currentPage != 1 && _settings.isSetPre == true) {
                    var pageNum = parseInt(_settings.currentPage) - 1;
                    _settings.pageContent += '<a id="' + pageNum + '" href="' + _settings.pageUrl + 
                            _settings.pageParamName + '=' + pageNum  + '">' + _settings.preDesc + '</a>';
                }
            },
            bindNextPage: function() {
                if (_settings.currentPage != _settings.sumPages && _settings.isSetNext == true) {
                    var pageNum = parseInt(_settings.currentPage) + 1;
                    _settings.pageContent += '<a id="' + pageNum + '" href="' + _settings.pageUrl + 
                            _settings.pageParamName + '=' + pageNum  + '">' + _settings.nextDesc + '</a>';
                }
            },
            bindPreDesc: function() {
                if (_settings.startPage > 1 && _settings.isSetPreAndNextDesc == true) {
                    _settings.pageContent += "<span>" + _settings.preAndNextDesc + "</span>";
                }
            },
            bindNextDesc: function() {
                if (_settings.endPage < _settings.sumPages && _settings.isSetPreAndNextDesc == true) {
                    _settings.pageContent += "<span>" + _settings.preAndNextDesc + "</span>";
                }
            },
            countStartAndEndPage : function () {
                var startPage = 1;
                var endPage = 1;
                
                // 計算起始頁碼
                startPage = _settings.currentPage - parseInt(_settings.pageSize / 2);
                // 最末頁
                if (_settings.currentPage == _settings.sumPages) {
                    startPage = _settings.sumPages - _settings.pageSize + 1;
                }
                // 第一頁
                if (_settings.currentPage == 1) {
                    startPage = 1;
                }
                // 檢查是否為小於1
                if (startPage < 1) {
                    startPage = 1;
                }
                
                // 計算終止頁碼
                var endPage = startPage + _settings.pageSize - 1;
                
                if (endPage > _settings.sumPages) {
                    startPage -=  endPage - _settings.sumPages;
                    endPage = _settings.sumPages;
                }
                
                // 檢查是否為小於1
                if (startPage < 1) {
                    startPage = 1;
                }
                
                _settings.endPage = endPage;
                _settings.startPage = startPage;                
            },
            bindPages: function() {
                
                for (var pagenum = _settings.startPage; pagenum <= _settings.endPage; pagenum++) {
                    if (pagenum == _settings.currentPage) {
                        _settings.pageContent += "<span>" + pagenum + "</span>";
                    } else {
                        _settings.pageContent += '<a id="' + pagenum  + '" href="' + _settings.pageUrl + 
                                _settings.pageParamName + '=' + pagenum  + '">' + pagenum + '</a>';
                    }
                }
            }
    };
    
    var _handler = function () {
        _settings.pageContent = "";
        
        _pageMethods.countStartAndEndPage();
        
        _pageMethods.bindFirstPage();
        _pageMethods.bindPrePage();
        _pageMethods.bindPreDesc();
        _pageMethods.bindPages();
        _pageMethods.bindNextDesc();
        _pageMethods.bindNextPage();
        _pageMethods.bindLastPage();
        
        $(this).append(_settings.pageContent);
        
        _settings.callback($(this));
    }
    
    return this.each(_handler);
}

使用 Ajax 參考範例

setPage(1, 40);
function setPage(page, sumpages) {
    $("#page").html("");
    
    $("#page").myPageLink(
            {
                sumPages: sumpages,
                currentPage:page,
                pageSize:11,
                callback: function (data) {
                    data.find("a").bind("click", function () {
                        // 加入Ajax
                        
                        // 重設定分頁
                        setPage(this.id, sumpages);
                        return false;
                    });
                }
            }
    );
}
 
almost 6 years ago

最近才發現html 注解掉的input 不會被POST....
看來我還是要多看點書才行XDDDD

<!--
<input type="text" .../>
-->
 
almost 6 years ago

img 的遮罩 Plugin
蠻常用到的....寫一下
可設定圓角

/*
 * 遮罩 img 物件
 *  範例
 *  <img src="Winter.jpg" />
 *  
 *  $(function (){
 *      $("img").myRectImg({
 *          rectHeight: 300,
 *          rectWidth: 300,
 *          rectRadius: 30,
 *          callback: function(data) {
 *              data.css({"border-style" : "dashed", "border-width": 1});
 *          }
 *      });
 *  });
 *  
 *  說明
 * rectHeight 遮罩的高
 * rectWidth 遮罩的寬
 * isInlineBlock  display 是否設定為 inline-block
 * borderWidth 遮罩框線寬度
 * callback 回傳 data 為遮罩的物件, 可自行修改css
 */
$.fn.myRectImg = function (settings) {
    // 預設屬性
    var _defaultSettings = {
        rectHeight: 200,
        rectWidth: 200,
        isInlineBlock:true,
        rectRadius: 0,
        borderWidth: 0,
        callback: function(data){}
    }
    
    var _settings = $.extend(_defaultSettings, settings);
    
    var _handler = function () {
        // 計算浮動位置
        var imgW = $(this).width();
        var imgH = $(this).height();
        
        var imgTop = (_settings.rectHeight - imgH) / 2;
        var imgLeft = (_settings.rectWidth - imgW) / 2;
        
        var rectDiv = $("<div></div>");
        
        $(this).wrap(
            // 加入遮罩 
                rectDiv.css({
                "position" : "relative",
                "overflow" : "hidden",
                "width" : _settings.rectWidth,
                "height" : _settings.rectHeight,
                "display" : (_settings.isInlineBlock) ? "inline-block" : "block",
                "border-radius": _settings.rectRadius,
                "border-style" : "solid",
                "border-width" : _settings.borderWidth
            })
        
        ).css({"top" : imgTop, "left" : imgLeft, "position" : "absolute"});
        
        _settings.callback($(this).parent("div"));
    }
    
    return this.each(_handler);
}
 
almost 6 years ago

Plugin 練習
兩種模式的浮動視窗
寫得好亂XDD

/*
 * 顯示浮動視窗工具
 *  範例
 *  $('#test1').myPopUp({showId: "PopUpbox"});
 *  $('#test2').myPopUp({showId: "PopUpbox2", closeId: "closeBox2"});
 *  $('#debug').myPopUp({bind: "mouseover", closebind: "mouseout", showId: "PopUpbox", closeId: "debug", showType: "float"});
 *  說明
 * bind 為主物件綁定的事件 預設 click
 * showId 顯示容器的Id 預設 myPopUpbox
 * closeId 關閉容器的Id 預設 closeBox
 * closebind 關閉容易的事件  預設 click
 * showType 顯示類型 popUp & float 預設 popUp
 * showBox 顯示時所要執行的 call back 
 */
$.fn.myPopUp = function (settings) {
    
    var _defaultSettings = {
            
            bind: "click",
            showId: "myPopUpbox",
            closeId: "closeBox",
            closebind: "click",
            showType:"popUp",
            showBox: function () {}
    };
    
    var _settings = $.extend(_defaultSettings, settings);
    
    var _boxMethods = {
            initBox: function () {
                if (_settings.showType == "popUp")  {
                    _popMethods.initPopUp();
                } else {
                    
                }
            },
            showBox :   function () {
                if (_settings.showType == "popUp")  {
                    _popMethods.showPopUp();
                } else {
                    _floatMethods.showFloat();
                }
            },
            closeBox : function () {
                if (_settings.showType == "popUp")  {
                    _popMethods.closePopUp();
                } else {
                    _floatMethods.closeFloat();
                }
            }
    };
    
    var _floatMethods = {
            
            showFloat : function () {
                var myoffset = _settings.id_object.offset();
                var width = _settings.id_object.width();
                
                _settings.showId_object.css({ "position":"absolute", 
          'left': myoffset.left + width + 15, 'top': myoffset.top, 'z-index':100 });
          
                _settings.showId_object.show(1000, function () {
                    $(this).stop();
                });
                
            },
            closeFloat : function () {
                _settings.showId_object.hide(1000, function () {
                    $(this).stop();
                });
            }
    };
    
    var _popMethods = {
            
            showPopUp : function () {
                    var boxWidth = _settings.showId_object.width(); 
                var boxheight = _settings.showId_object.height();
          
                _settings.showId_object.css({"position":"absolute", 
            "left": (_settings.document_object.width() - boxWidth) / 2, 
            "top": (_settings.document_object.height()) / 2, 'z-index': 100 });
            
                _settings.box_id_object.css({"width": _settings.document_object.width(), 
            "height": _settings.document_object.height() });
            
                _settings.showId_object.show();
                _settings.box_id_object.show();
            },
            resizePopUP : function () {         
                    var boxWidth = _settings.showId_object.width(); 
                var boxheight = _settings.showId_object.height();
                _settings.showId_object.css({ "left": (_settings.document_object.width() - boxWidth) / 2, 
          "top": (_settings.document_object.height()) / 2, 'z-index': 100 }); 
          
                _settings.box_id_object.css({ "width": _settings.document_object.width(), 
          "height": _settings.document_object.height() });  
            },
            closePopUp : function () {
                _settings.showId_object.hide();
                _settings.box_id_object.hide();
            },
            initPopUp: function () {
                $("body").append('<div id="' + _settings.background_box_id + 
        '" style="position:absolute;display:none;width:100%;height:100%;background-color:#999999;left:0px;top:0px;opacity: 0.50;filter: alpha(opacity=50);"></div>');
                _settings.box_id_object = $("#" + _settings.background_box_id);
                // 設定底圖關閉事件
                 _settings.box_id_object.click(function () {
                    _boxMethods.closeBox();
                });
                // 設定視窗刷新大小
                $(window).resize(function(){ 
                    _popMethods.resizePopUP();
                });
            }
            
    };
    
    var _handler = function () {
        
        // 初始化必要物件
        _settings.background_box_id = this.id +  "_background_box";
        _settings.id_object = $("#" + this.id);
        _settings.showId_object = $("#" + _settings.showId);
        _settings.window_object = $(window);
        _settings.document_object = $(document);
        _boxMethods.initBox();
        
        // 綁定事件
        var this_object = $(this);
        this_object.bind(_settings.bind, _settings.showBox);
        this_object.bind(_settings.bind, _boxMethods.showBox);
        
        if ((this.id == _settings.closeId && _settings.closebind != _settings.bind) || 
                this.id != _settings.closeId) {
            
            $("#" + _settings.closeId).bind(_settings.closebind, _boxMethods.closeBox);
        }
    };
    
    return this.each(_handler);
}
 
almost 6 years ago

JQuery Plugin 練習
因為常遇到要對比壓縮圖檔的問題
所以寫個 Plugin 方便使用

/*
 * resize img 物件
 *  範例
 *  <img src="Winter.jpg" />
 *  
 *  $(function (){
 *      $("img").myReImgSize({
 *          reHeight:100,
 *          reWidth:100
 *      });
 *
 *      OR
 *
 *      $("img").myReImgSize();
 *  });
 *  
 *  說明
 * reHeight 壓縮範圍內的高
 * reWidth 壓縮範圍內的寬
 */
$.fn.myReImgSize = function (settings) {
    // 預設屬性
    var _defaultSettings = {
        reHeight: 200,
        reWidth: 200
    }
    
    var _settings = $.extend(_defaultSettings, settings);
    
    var _handler = function () {
        //取得影像實際的長寬
        var imgW = $(this).width();
        var imgH = $(this).height();
        
        //計算縮放比例
        var preW = _settings.reWidth / imgW;
        var preH = _settings.reHeight / imgH;
        
        var pre = 1;
        if (preW > preH) {
          pre = preH;
        } else {
          pre = preW;
        }
        
        //設定目前的縮放比例
        $(this).width(imgW * pre);
        $(this).height(imgH * pre);
    };
    
    return this.each(_handler);
}