2011年11月28日 星期一

讓 jQuery UI 的 DatePicker 多個 clear 按鈕

Keith Wood 寫了不錯的日曆挑選元件,同時也被 jQuery UI 收錄為官方版的挑日期方案。所以我們只要在 datepicker 頁面,就可以找到。然而,如果你細心的去比較 Keith Wood 的個人網站,會發現該作者目前所發表的日曆挑選元件,似乎在功能上,比 jQuery UI 所發佈的還要多。舉例來說,下面的日曆元件是來自於 Keith Wood 目前的版本 4.0.6


有沒有發現,他有一個 Clear 的鏈結,點下去,會將目前的日期輸入方塊上的資料清掉。很重要嗎?如果你的日期輸入方塊,有設定為 readOnly = true 時,這種需求的機會應該就會變高了。那 jQuery UI 的有提供嗎?
目前 jQuery UI 的版本是:1.8.16,很不巧的,沒有,他並沒有 clear 的功能。但如果你真心喜歡一個人的話,理應可以包容對方不足的地方。但前提是,要先努力過,努力甚麼呢?先給他去整形一下吧...


雖然 jQuery UI 目前的版本並沒有提供,但熱心的工程師,總是會想出些「成人之美」的方案。我在 http://bugs.jqueryui.com/ticket/3999 看到了很多人的抱怨,但也發現了一個有建設性的解法,雖然要多寫幾行程式,但能抓到老鼠的都算是好貓啦!




<script type="text/javascript">
$(function(){
    $(".pickdate").datepicker({
        changeMonth: true,
        changeYear: true,
        dateFormat: 'yy/mm/dd',            
        showButtonPanel: true

    });

    // hack to add clear button
    // 增加清除按鈕 -Start (Ref. http://bugs.jqueryui.com/ticket/3999)
    //wrap up the redraw function with our new shiz
    var dpFunc = $.datepicker._generateHTML; //record the original
    $.datepicker._generateHTML = function (inst) {
        var thishtml = $(dpFunc.call($.datepicker, inst)); //call the original

        thishtml = $('<div />').append(thishtml); //add a wrapper div for jQuery context

        //locate the button panel and add our button - with a custom css class.
        $('.ui-datepicker-buttonpane', thishtml).append(
 $('<button class="\
  ui-datepicker-clear ui-state-default ui-priority-primary ui-corner-all\
  "\>Clear</button>'
 ).click(function () {
     inst.input.attr('value', '');
     inst.input.datepicker('hide');
 })
);

        thishtml = thishtml.children(); //remove the wrapper div

        return thishtml; //assume okay to return a jQuery
    };

    // 增加清除按鈕 -End

  
  
});
</script>
如此折騰一番後,就可以多生出一個 Clear 按鈕了。

測試程式 [下載]

參考:
01:http://bugs.jqueryui.com/ticket/3999
02:Keith Wood,http://keith-wood.name/index.html

2011年11月8日 星期二

利用 FileStream 讀檔、寫檔


在 C# 裡,透過 FileStream 可以很容易地完成檔案的讀/寫動作,有時候真的會覺得,它其實不難,但真要從無到有卻沒得參考還真的有點不方便,所以整理了一下基本的使用方式。更多有關檔案操作方法,可以參考《[C#] 檔案讀寫》這篇文章,寫得很詳細。


/// 
/// 將檔案寫到 Byte[]
/// 
/// 

/// 
private byte[] File2Byte(string strFilePath)
{
    FileStream fileStream = null;
    Byte[] fileBytes = null;

    if (File.Exists(strFilePath))
    {
        try
        {
            fileStream = new FileStream(strFilePath, FileMode.Open, FileAccess.ReadWrite);
            fileBytes = new byte[(int)fileStream.Length]; //設定 fileBytes 的長度
            fileStream.Read(fileBytes, 0, fileBytes.Length); //將 filestream 資料讀到 fileBytes 
        }
        catch
        {
                    
        }
        finally
        {
            fileStream.Close();
            fileStream.Dispose();
        }
    }

    return fileBytes;
}


在 MSDN 的《FileStream 類別》有提到:「請確定對所有 FileStream 物件呼叫 Dispose 方法,尤其是在磁碟空間有限的環境中更應如此。如果沒有可用的磁碟空間,且在 FileStream 完成之前沒有呼叫 Dispose 方法,則執行 IO 作業可能會引發例外狀況。」雖然目前沒有直接可實驗的環境,就姑且信之,乖乖的加上一行 Dispose。

/// 
/// 將 Byte[] 資料寫到檔案
/// 
/// 

/// 

/// 
private bool Byte2File(byte[] bRead, string strNewFilePath)
{
    FileStream fileStream = null;
    try
    {
        fileStream = new FileStream(strNewFilePath, FileMode.OpenOrCreate);
        fileStream.Write(bRead, 0, bRead.Length);
    }
    catch(Exception ex)
    {
        Response.Write(ex.Message);
        return false;
    }
    finally
    {
        fileStream.Close();
        fileStream.Dispose();
    }

    return true;
}


呼叫讀檔/寫檔函式:
protected void btnFile2Byte_Click(object sender, EventArgs e)
{
    //設定檔案來源
    //string strFilePath = "D:\\upload\\projAply\\ann_e3wdwz10.xls";
    string strFilePath = @"D:\upload\projAply\ann_e3wdwz10.xls";

    //將來源檔案寫到 Byte[] bRead
    Byte[] bRead= File2Byte(strFilePath);

    //將 Byte[]  bRead 裡的資料寫到檔案
    Byte2File(bRead, "D:\\upload\\projAply\\ann_test.xls");
}


在設定檔案來源的地方,特別用了一個 「@」符號,其實是故意的。主要是想要特別分享這個好方法。原先使用單純的字串時,如果遇到反斜線(\)時,則必須使用雙反斜線(\\)來代表。但如果在字串前面加上 @ 符號後,後面的字串除了引號(")需要改用雙引號("")來替換之外,就不再需要考慮逸出字元的處理了,甚至連跨越數行都沒有問題。詳見:C#中的@符號


Ref:

01.
[C#] 檔案讀寫
http://blog.xuite.net/autosun/study/32576568

02.
FileStream 類別
http://msdn.microsoft.com/zh-tw/library/system.io.filestream(v=vs.80).aspx

03.
C# byte[]和文件FileStream相互转化
http://www.cnblogs.com/wskfire/archive/2007/11/30/978212.html

04.
C#中的@符號
http://tc.wangchao.net.cn/bbs/detail_149142.html

05.
2.4.4.5 字串常值
http://msdn.microsoft.com/zh-tw/library/aa691090(v=vs.71).aspx

06.
C# 字串變數, 如何包含雙引號或反斜線
http://www.allenkuo.com/GenericArticle/view.aspx?id=28

人在低谷,只有往上看的選擇;人在高峰,卻有往下環顧的責任



難免有時候,會遇到低潮、或令自己難過不已的事情,就好比經歷了一場大風雪,雖然你不知道何時會結束,但可以肯定的,是它終究會過去。「面對它,接受它,處理它,放下它。」,嚴然是處理問題的成熟作法,但並沒有人要求你一定要理性,其實也可以任性一些些。當這突如其來的問題發生時,你,會怎麼處理呢?

以下列出幾個常見的作法:


  • 克服難堪情緒的最好方法,是儘快把事情的來龍去脈講給周遭的人聽。你會發現,原來支持你的人比你想像還要多,而且別人不只不會責備你,還很樂意幫助你。此外,講的次數越多,你的情緒波動會漸漸變小,然後逐漸接受這件事。不管發生什麼事,盡量別讓自己的情緒受影響,這樣才能有清楚的腦袋,對下一步做策略思考。 
  • 自己不好意思開口對別人訴說,那就跟神說,或跟自己的宗教信仰說。 這會比一個人悶在心裡頭好很多。
  • 觀功念恩。觀看對方的好處,感謝對方帶給你的成長與收穫。看別人的功德,別人不一定有好處,但自己一定有好處;看別人的過失,別人不一定受害,自己一定受害。
  • 「境由心生,聖人轉心不轉境,凡人轉境不轉心。事來心始現,事去境隨空。虛靈無我,捨己從人。」事情的本身,並沒有所謂的絕對。若以受害者的角度去看它,你會更難過;但如果你相信無限生命(甚至可以延伸到下一世、下二世),它就會只是生命中的一個過客而已。緣聚而來,緣散而去,聚散乃人生常態,有緣成為同路人,到站各自奔東西。
  • 「欲知前世因,今生受者是,欲知來世果,今生做者是。」如果前世有造業,今世來償還,天經地義,也沒什麼好難過,所以要歡喜去受。如果前世沒造業,今世來累積福德資糧,你賺到了,所以更要歡喜去受。如此,幹麼還難過啊!
  • 適度的增加可以轉移注意力的活動。如多參加戶外活動、或多承擔些額外工作,讓自己沒時間悲傷。


是否您還有更好的方法呢,聆聽專線(暫不提供 0800),請直接填寫意見回覆就好...






參考:
01.Cheers 125 期 「只要9招,躍升職場要角(全文)」
02.觀功念恩 開啟心靈快樂之鑰






王師傅坐公共汽車到上海市嘉定區高潮村。
因沒去過所以剛過二站就開始問車掌小姐:'高潮到了沒有?'
車掌小姐答:'沒有'
過了二站後,王師傅又問了: '高潮到了沒有?'
車掌小姐答:'沒有。'
沒過幾分鐘,王師傅又問:'高潮到了沒有?'
這時,車掌小姐實在是不耐煩了。
高聲地回答道:

高潮到了我會叫!!!



2011年11月3日 星期四

動態切換 Master Page

隨著心情、節日或角色而變換網頁色系,似乎蠻符合鮮明的個人風格。這樣的需求,換一換 css 應該就可以完成。但如果連排版也要重新建構,例如由原先的 Menu Bar放左邊,改成 Menu Bar 放上面,這樣 ... 心情就不會再美麗了。


樣板A
樣板B
為了能夠動態(或根據某些條件)來切換網頁樣板,有個比較簡單的方式,就是透過 Master Page 的更換來完成。也就是說,事先設計好幾個 Master Page A, B, C, D ...,最後根據某個規則來載入適當的 Master Page 就可以達成簡單的樣板切換功能了。而每個樣板所需要的 CSS 或 javascript ,也可以依據不同的 Master Page 而各自撰寫。

自己參考了 Ryan 的 「Dynamically Loading Master Pages in ASP.NET 2.0」文章,整理了一些測試程式。


首先建立 Dynamic 類別,為了讓需要動態切換的頁面來繼承。在程式中,是假設日後的樣板資訊是留存在 DB ,所以這邊會去 DB 抓資料回來。
 
namespace CMaster
{
    public class Dynamic:System.Web.UI.Page
    {
        protected override void OnPreInit(EventArgs e)
        {
            string strMaster = GetMasterFromDB();

            if (!strMaster.Equals(string.Empty))
            {
                base.MasterPageFile = strMaster;
            }

            base.OnPreInit(e);
        }


        //模擬從 DB 抓取 Master 設定
        private string GetMasterFromDB()
        {
            return "~/SK02.Master";
        }
    }
}
接著將需要動態切換 Master Page 的頁面,將其頁面的繼承改為 Dynamic ,以自己的範例來說,就是修改 MyPage.cs 如下:
namespace CMaster
{
    public partial class MyPage : Dynamic
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }
}
這裡將 原先的 public partial class MyPage : System.Web.UI.Page 改成
 public partial class MyPage : Dynamic

如此就可以完成動態切換 Master Page 的需求了。

在 Ryan 的文章中有提到透過設定 web.config 的 pageBaseType 可以達到一次設定所有頁面都支援動態切換 Master Page,但使用這方法要注意,你的程式必須是使用 Inline mode 開發,如果是使用 Code Behind (預設都是採 Code Behind),則設定 web.config 這種方式就會失效囉。



參考: