顯示具有 jQuery 標籤的文章。 顯示所有文章
顯示具有 jQuery 標籤的文章。 顯示所有文章

2013年6月13日 星期四

jQuery 取得 checkbox 至少有一個選取

客戶的需求中,「當使用者至少要選取一筆資料才能進行下一個動作」。常見的 UI 設計,當然是使用 checkbox。

而我的 case,是資料有一萬多筆,此時整個網頁非常痴肥而難以接受。問題是,客戶就是要這樣的網頁,客戶拒絕分頁

jQuery length

問題來了,此時我使用了如下的 jQuery 語法查詢是否有選取一個 checkbox

var isChecked = $('input[name=chk]:checked').length > 0;

相當然爾,網頁就硬生生當在那裡,動也不能動。效能不好

jQuery is

根據我「多年」「 .NET」的經驗,使用 length 等同於計算所有被勾選的項目,然後再計算出總筆數,這樣的效能當然不好啊。於是趕快找一找 jQuery document,很快的就發現了 jQuery is 非常符合我的需求。於是馬上改了程式

   1: var isChecked = $('input[name=chk]')is(':checked');

滿心期待效能飛快,但「更慢了」。怎麼會…

效能比較

找到一個測試,也證實了這樣的結果。怎麼會這樣…

另外,又找了一個 checkboxtests,這次加入了自己寫的 .each() 來測試是否會比較快?結論是:不會。

心得

到了 javascript 的世界,以前許多經驗值就必須大打折扣了。

2010年8月12日 星期四

使用 Ajax 方式取得 UserControl 的內容

同事問到,如何以 Ajax 的方式取得 UserControl 的內容。

問題

由於 UserControl 是無法單獨被客戶端所呼叫(Request),因此我們必須想個辦法將 UserControl 加到一個 Page內。

解決步驟

1 Web Service 回傳 UserControl 的內容

使用 Visual Studio (我使用 2010) 建立一個 Web Application,並加入一個 WebService。程式碼如下

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{
    [WebMethod(EnableSession = true)]
    public string GetUserControlHtml(string location)
    {
        var webServiceString = string.Format("Thread Id={0}, Time={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("HHmmss fffffff"));
        var page = new Page();
        var userControl = (UserControl)page.LoadControl(location);
        userControl.EnableViewState = false;
        var form = new HtmlForm();
        form.Controls.Add(userControl);
        page.Controls.Add(form);
        var writer = new StringWriter();
        HttpContext.Current.Server.Execute(page, writer, false);

        return webServiceString + "<br /> " + RemoveFormTagFromHtml(writer.ToString());
    }


    /// <summary>
    /// 移掉 Form Tag
    /// </summary>
    /// <param name="html"></param>
    /// <returns></returns>
    private static string RemoveFormTagFromHtml(string html)
    {
        return Regex.Replace(html, @"<[/]?(form)[^>]*?>", "", RegexOptions.IgnoreCase);
    }
}

過程大略是:手動建立一個 Page,Page 內加入一個 Form,Form 動態載入指定的 UserControl。使用 Server.Execute 取得 html 內容後,將 <form tag 移除,避免避免原 asp.net 網頁失敗。

2 寫 UserControl

今天的配角是 UserControl。UserControl並不難實作。我簡單的寫了兩個 UserControl,分別 Thread.Sleep 了2秒,3秒。

3 於呼叫網頁使用 Ajax 方式呼叫 ASP.NET Web Service

我再入成兩種方式來呼叫。一個是 ASP.NET AJAX,一個則是 jQuery。

3.1 使用 ASP.NET AJAX 呼叫 Web Service

加入一個 ScriptManager,並加入一個 ScriptReference 參考到剛剛建立的 WebService。利用動態產生的 javascript file (可使用 http://…/WebService1.asmx/jsdebug 取得內容)協助呼叫 ASP.NET Web Service

3.2 使用jQuery 的 .ajax 呼叫 Web Service

使用jQuery 大概是近來 Web 技術的顯學吧。為了方便未來的 ASP.NET MVC的使用,還是乖乖的學一下吧。

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication3._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            var datestring = getNow();
            $("#div1").html("at client, " + datestring + "<br/>");
            getData("WebUserControl1.ascx", $("#div1"));

            datestring = getNow();
            $("#div2").html("at client, " + datestring + "<br/>");
            getDataByJquery("WebUserControl2.ascx", $("#div2"));
        });

        function getNow() {
            var today = new Date();
            return today.format("HHmmss ffffff");
        }
        function getData(controlLocation, container) {
            WebApplication3.WebService1.GetUserControlHtml(controlLocation,
                function (result) {
                    $(container).append(result);
                },
                function () { alert(error.get_message()); }
            );
        }

        function getDataByJquery(controlLocation, container) {
            var datestring = getNow();
            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "WebService1.asmx/GetUserControlHtml",
                data: "{'location': '" + controlLocation + "'}",
                dataType: "json",
                success: function (result) {
                    $(container).append(result.d);
                },
                error: function (error) { alert(error.responseText); }
            });
        }
    </script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/WebService1.asmx" />
        </Services>
    </asp:ScriptManager>
    <h2>
        Welcome to ASP.NET!
    </h2>
    <div style="border: 2px solid red">
        <h1>
            User Controll 1</h1>
        <div id="div1">
        </div>
    </div>
    <div style="border: 2px solid red">
        <h1>
            User Controll 2</h1>
        <div id="div2">
        </div>
    </div>
    <div id="result">
    </div>
</asp:Content>

4 測試

測試時發現狀況還不錯。雖然同時發出 Request, 約2秒後得到UserControl1 的內容,但 UserControl2卻在約略在 5.5 秒後才得到內容,而非3秒。為什麼?

image

5 Session 造成 lock,因而 Delay

原來是步驟1中,[WebMethod(EnableSession = true)] 這個 true 所造成的。改成 EnableSessioin = false後,網頁測試結果如下

image
這樣就符合我們的期待了。

沒事最好還是不要用 Session。

範例下載

2009年6月11日 星期四

[Asp.Net] 網頁如何在 Enter 鍵被按下時,改成 Tab 鍵

客戶原本使用 AS400 的系統,非常習慣輸入後按 Enter 鍵,游標會移到下一個輸入框。
這個在Windows 上是不make sense的。但不管在 WinForm,甚至是 Web Form,都有客戶這樣要求。
原因當然是:讓操作人員在新舊系統上的操作具一致性。

在 Asp.net 上要怎麼做呢?由於此行為已經是 client side 的行為了,與伺服器無器。當然需要借重 jQuery  了.
程式碼如下

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication11._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">

    <script src="jquery-1.2.6.js" type="text/javascript"></script>

    <script type="text/javascript">
        $(document).ready(
            function() {
                $('input[hhh=xxx]').keydown(
            function() {
                if (event.keyCode == 13)
                    event.keyCode = 9;
                if (this.value.length == this.maxLength)
                    event.keyCode = 9;
            });
            }
        );
        
    </script>

    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        input 1:<asp:TextBox hhh="xxx" ID="TextBox1" runat="server" MaxLength="8"></asp:TextBox><br />
        input 2:<asp:TextBox hhh="xxx" ID="TextBox2" runat="server"></asp:TextBox><br />
        input 3:<asp:TextBox hhh="xxx" ID="TextBox3" runat="server"></asp:TextBox><br />
        <asp:Button ID="Button1" runat="server" Text="Submit it" UseSubmitBehavior="false" />
    </div>
    </form>
</body>
</html>

重點如下:

  1. function myKeyDown 將 Enter 鍵改成 Tab 鍵,另外,當 text 輸入的長度已達 maxLength 時,也強迫改成 Tab 鍵
  2. 當 document ready 後,將具有 hhh 屬性值為 xxx 的 input ,當 keydown 事件發生時,呼叫  myKeyDown
  3. 之後需要這樣行為的 text box,只需增加 hhh=’xxx’ 的 attribute 即可

2009年5月4日 星期一

Asp.net 執行匯入進度

顯示匯入或上傳的進度,想必是許多 asp.net 開發人員一定會遇到的問題。
以下是我的解法。

為了讓 progress bar 能跑,當然需要 jQuery.
JQuery Progress Bar 1.1 已經幫我們寫好了,我們只需要使用即可。

再來,為了讓網頁能立刻反應當下的進度,需要使用 ASP.NET Ajax 的 AJAX 之 PageMethod 功能。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Script.Services;
using System.Web.Services;
using System.Threading;

namespace WebApplication1
{
  public partial class _Default : System.Web.UI.Page
  {
    private static SlowTask slowTask = null;

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    [ScriptMethod]
    [WebMethod]
    public static Progress GetTaskCurrentProgress()
    {
      int ii = Thread.CurrentThread.ManagedThreadId;
      return new Progress
      {
        CurrentCount = slowTask.CurrentCount,
        TotalCount = slowTask.TotalCount,
        Message =       string.Format("{0}/{1} : {2}", slowTask.CurrentCount, slowTask.TotalCount, 
        slowTask.GetAsyncTaskProgress())
      };
    }

    public struct Progress
    {
      public string Message;
      public int TotalCount;
      public int CurrentCount;
    }

    

    [ScriptMethod]
    [WebMethod]
    public static void RunItSync()
    {
      int ii = Thread.CurrentThread.ManagedThreadId;
      slowTask = new SlowTask(1000);
      slowTask.ExecuteAsyncTask();
    }
  }
}
Code behinds
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Script.Services;
using System.Web.Services;
using System.Threading;

namespace WebApplication1
{
  public partial class _Default : System.Web.UI.Page
  {
    private static SlowTask slowTask = null;

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    [ScriptMethod]
    [WebMethod]
    public static Progress GetTaskCurrentProgress()
    {
      int ii = Thread.CurrentThread.ManagedThreadId;
      return new Progress
      {
        CurrentCount = slowTask.CurrentCount,
        TotalCount = slowTask.TotalCount,
        Message =       string.Format("{0}/{1} : {2}", slowTask.CurrentCount, slowTask.TotalCount, 
        slowTask.GetAsyncTaskProgress())
      };
    }

    public struct Progress
    {
      public string Message;
      public int TotalCount;
      public int CurrentCount;
    }

    

    [ScriptMethod]
    [WebMethod]
    public static void RunItSync()
    {
      int ii = Thread.CurrentThread.ManagedThreadId;
      slowTask = new SlowTask(1000);
      slowTask.ExecuteAsyncTask();
    }
  }
}

sample code download here.

2009年4月2日 星期四

Mix09 KeyNote 筆記

微軟在 Mix09 又 release 了一堆新東西,我又要忙好一陣子了。

Expression Web 3

    SuperPreview, 可在同一介面上看到多個瀏覽器的html 預覽結果與side by side 比較

ASP.NET MVC 1.0

  1. Full Control over HTML markup
  2. SEO friendly with URL routing
  3. Test driven development workflow
  4. Easily extensible

ASP.NET 4 improvements

  1. Web Forms : 可控制 ViewState, Client ID
  2. MVC
  3. AJAX: Client Template, Client side data binding
  4. Distributed Caching

Visual Studio 2010 for web development

  1. Code focused improvments
  2. JavaScript /AJAX /jQuery tooling
  3. SharePoint: 開發與 debug
  4. Publishing and deployment : 除了複製程式外,也可IIS 設定、 create database, update schema

IIS 7 Web Server Extensions

  1. Secure FTP
  2. WebDAV support
  3. proxy

Microsoft Web Platform Installer

  1. Install the latest versions of Microsfot Web Platform tools, server, database and framework
  2. Stay up-to-date and explore what's new
  3. Runs on Windows XP, windows Vista, Windows Server 2003 and Windows Server 2008

Commerce Server 2009

Azure Services Platform

這個在去年的 PDF 已有展示了,而且,我不熟,也不太有興趣。

2009年1月6日 星期二

jQuery 於 Visual Studio 2008 的 IntelliSense

開發 jQuery 的網頁時,當然需要 IntelliSense 的協助。
以往,開發時只能先 reference -vsdoc.js 檔。如下

當然,-vsdoc.js 的檔案較大,目的是方便開發。到了上 Production 環境時,就得手動地改成

這樣好累啊!有沒有辦法只需要引用 Production 的寫法,但可以在開發時期使用 IntelliSense 的功能呢?

還好,微軟還是有幫我們想。請下載 KB958502 ,然後將 jquery-1.2.6.js 及 jquery-1.2.6-vsdoc.js 放到同一個目錄。這樣一來,VS2008 的 html designer 看到 a.js 檔時,會先看看有沒有對應的 a-vsdoc.js 檔,有的話,會拿-vsdoc.js 當 documentation 用的檔案,但部署到 Production 時,當然Client 的瀏覽器只會引用 jquery-1.2.6.js

Share with Facebook