달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

출처 : http://aspnet.4guysfromrolla.com/articles/051408-1.aspx



Introduction
Most security systems' passwords are case-sensitive. Case sensitivity nearly doubles the number of possible characters that can appear in the password, which makes it harder for nefarious users trying to break into the system. As a result, if a user logging into the system has Caps Lock turned on, they'll enter letters in the opposite case and not be able to login. Because the textboxes that collect user input typically are masked to prevent an onlooker from seeing a user's password, the user typing in her password may not realize that Caps Lock is on. To help prevent this type of user error, many login screens for desktop-based applications display some sort of warning if the user's Caps Lock is on when they start typing in their password.

Unfortunately, such functionality is rarely seen in web applications. A 4Guys reader recently asked me if there was a way to provide such feedback to a user logging into an ASP.NET website. The short answer is, Yes. It is possible to detect whether a user has Caps Lock enabled through JavaScript. Likewise, it's possible to have this client-side logic execute whenever a user starts typing in a particular textbox. With a little bit of scripting, such an interface could be devised.

After thinking about the implementation a bit, I decided to create a compiled server-side control that would emit the necessary JavaScript. This article introduces this control, WarnWhenCapsLockIsOn, and shows how it works and how to use it in an ASP.NET web page. Read on to learn more!

 
 
An Overview of the WarnWhenCapsLockIsOn Control's Functionality
The WarnWhenCapsLockIsOn control is designed to display a page developer-specified message if a user types in a specified TextBox control with Caps Lock on. The control extends the Label class so it has the same set of properties as the Label control: Text, Font, Width, CssClass, and so on. Use these properties to configure the message and the message's appearance.

In addition to the Label control's properties, the WarnWhenCapsLockIsOn control also has a TextBoxControlId property, which you must set to the ID of a TextBox control. This property is required. (To provide a Caps Lock warning for multiple TextBox controls on the page, add a WarnWhenCapsLockIsOn control for each TextBox.) If the user starts typing in the specified textbox with the Caps Lock on, the WarnWhenCapsLockIsOn control is displayed. The WarnWhenCapsLockIsOn control is hidden again when one of the following conditions apply:

  • The user types in the same textbox with Caps Lock off.
  • The WarnWhenCapsLockIsOn control has been displayed for WarningDisplayTime milliseconds. The WarningDisplayTime property defaults to a value of 2500, meaning that the control will be displayed for 2.5 seconds after the last character with Caps Lock on has been typed. You can lengthen or shorten this property value as needed. A value of 0 displays the warning until the user types in a character without Caps Lock on or after there's a postback.

To provide a warning to the user if Caps Lock is on, then, you'll add this control to the page, set its Text property (and, perhaps, other formatting properties), and indicate the TextBox to "watch" via the control's TextBoxControlId property. That's all there is to it! We'll discuss how to add the WarnWhenCapsLockIsOn control to your ASP.NET website project and look at an end-to-end example in the "Using the WarnWhenCapsLockIsOn Control in an ASP.NET Web Page" section later on in this article.

Initially Hiding the WarnWhenCapsLockIsOn Control
Whenever the ASP.NET page is loaded in the user's browser, the WarnWhenCapsLockIsOn control needs to be hidden so that it does not appear. The WarnWhenCapsLockIsOn control should only appear when the user starts typing in the specified textbox with Caps Lock on. To initially hide the WarnWhenCapsLockIsOn control, I overrided the control's AddAttributesToRender method and added code that set the visibility and display style attributes to "hidden" and "none", respectively.

public class WarnWhenCapsLockIsOn : System.Web.UI.WebControls.Label
{
   protected override void AddAttributesToRender(HtmlTextWriter writer)
   {
      base.AddAttributesToRender(writer);

      // Add a style attribute that hides this element (by default)
      writer.AddStyleAttribute(HtmlTextWriterStyle.Visibility, "hidden");
      writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");

   }
}

The effects of these style attribute settings are evinced by the markup sent to the browser. Because the WarnWhenCapsLockIsOn control extends the Label class, it renders as a <span> element with the value of its Text property rendered as the <span> element's inner content, just like the Label control. In the style attribute you can see that the visibility and display settings have been configured to hide the control:

<span id="ID" style="visibility:hidden;display:none;">Value of Text property</span>

We now need to write JavaScript that sets the visibility and display settings to "visible" and "inline" whenever the user types into the corresponding textbox with Caps Lock on.

Executing JavaScript in Response to Typing in a Textbox
It is possible to execute JavaScript in response to a variety of client-side events, such as when the document has loaded, when the user changes the selection of a drop-down list, when an input field receives (or loses) focus, or when the user presses a key. To execute client-side script in response to a user pressing a key, use the onkeypress event like so:

<input type="text" ... onkeypress="action" />

The action can be inline script or a call to a function. In addition to noting that a key has been pressed, JavaScript offers the event object, which includes information such as what key was pressed and whether or not the Shift key was depressed, among other useful tidbits. In short, we need to add an onkeypress client-side event handler to the TextBox control referenced by the WarnWhenCapsLockIsOn control's TextBoxControlId property. The event handler called must determine whether Caps Lock is on or off and show or hide the WarnWhenCapsLockIsOn control in response.

To add client-side event handlers to a server-side Web control use the Attributes collection like so:

WebControlID.Attributes["attribute"] = "value";

The above code adds the markup attribute="value" to the Web control's rendered output. Usually this sort of logic is applied during the PreRender stage of the page lifecycle. Therefore, to implement this functionality I overrode the OnPreRender method in the WarnWhenCapsLockIsOn class (which is fired during the PreRender stage) and added the following code:

public class WarnWhenCapsLockIsOn : System.Web.UI.WebControls.Label
{
   protected override void OnPreRender(EventArgs e)
   {
      base.OnPreRender(e);

      if (this.Enabled)
      {
         /* We need to add two bits of JavaScript to the page:
          * (1) The include file that has the JavaScript function to check if Caps Lock is on
          * (2) JavaScript that will call the appropriate function in (1) when a key is pressed in the TextBoxControlId TextBox
          */

         // (1) Register the client-side function using WebResource.axd (if needed)
         if (this.Page != null && !this.Page.ClientScript.IsClientScriptIncludeRegistered(this.GetType(), "skmControls2"))
            this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "skmValidators", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "skmControls2.skmControls2.js"));


         // (2) Call skm_CountTextBox onkeyup
         TextBox tb = GetTextBoxControl();
         tb.Attributes["onkeypress"] += string.Format("skm_CheckCapsLock( event, '{0}', {1});", this.ClientID, this.WarningDisplayTime);
      }
   }
}

The GetTextBoxControl method (not shown in this article) returns a reference to the TextBox control specified by the TextBoxControlId property. This referenced TextBox has its Attributes collection updated to include an onkeypress event handler that calls the JavaScript function skm_CheckCapsLock. The skm_CheckCapsLock function (which we'll examine shortly), is passed three input parameters:

  • event - information about the keypress event, including what key was pressed and whether the Shift key was depressed.
  • The value of the WarnWhenCapsLockIsOn's ClientID property - we need to supply the client-side id of the WarnWhenCapsLockIsOn control so that it can be displayed or hidden, depending on whether the user has Caps Lock on.
  • WarningDisplayTime - the number of milliseconds to display the Caps Lock warning; defaults to 2500 milliseconds (2.5 seconds).

The WarnWhenCapsLockIsOn control is one of a few controls in my open-source control library, skmControls2. Another control in the same library is the TextBoxCounter control, which interactively displays how many characters the user has currently typed into a given textbox. (For more information on the TextBoxCounter control, read: Creating a TextBox Word / Character Counter Control.) The TextBoxCounter control requires a bit of JavaScript, and that JavaScript is already defined in a file named skmControls2.js. This file is compiled as an embedded resource in the assembly and is loaded into the ASP.NET page on which the TextBoxCounter or WarnWhenCapsLockIsOn controls are used via a call to the GetWebResourceUrl method. For more information on this technique see: Accessing Embedded Resources through a URL using WebResource.axd.

Because the skmControls2 library already has a JavaScript file, I decided to place the skm_CheckCapsLock function (and ancillary helper functions) there. It is injected into the ASP.NET page in the OnPreRender method (see step 1 in the comments in OnPreRender).

Determining Whether Caps Lock is On
When the keypress event is raised in client-side script, the event object contains information as to what key was pressed and whether the Shift key was depressed (along with whether Alt and Ctrl were depressed). It does not, however, indicate whether Caps Lock was on. The good news is that with a bit of code we can determine whether Caps Lock is on. If the user has entered a capital letter and the Shift key is not depressed, then Caps Lock must be on; likewise, if the user enters a lowercase letter and the Shift key is depressed, then Caps Lock is on.

The skm_CheckCapsLock function determines whether Caps Lock is on and, if so, calls the skm_ShowCapsWarning function, which displays the WarnWhenCapsLockIsOn control for a specified interval. If Caps Lock is not on then the skm_HideCapsWarning function is called, which hides the WarnWhenCapsLockIsOn control. The skm_CheckCapsLock function uses a modified version of a script created by John G. Wang, available online at http://javascript.internet.com/forms/check-cap-locks.html.

function skm_CheckCapsLock( e, warnId, dispTime ) {
   var myKeyCode = 0;
   var myShiftKey = e.shiftKey;
   
   if ( document.all ) {
      // Internet Explorer 4+
      myKeyCode = e.keyCode;
   } else if ( document.getElementById ) {
      // Mozilla / Opera / etc.
      myKeyCode = e.which;
   }
   
   if ((myKeyCode >= 65 && myKeyCode <= 90 ) || (myKeyCode >= 97 && myKeyCode <= 122)) {
      if (
         // Upper case letters are seen without depressing the Shift key, therefore Caps Lock is on
         ( (myKeyCode >= 65 && myKeyCode <= 90 ) && !myShiftKey )

         ||

         // Lower case letters are seen while depressing the Shift key, therefore Caps Lock is on
         ( (myKeyCode >= 97 && myKeyCode <= 122 ) && myShiftKey )
       )
      {
         skm_ShowCapsWarning(warnId, dispTime);
      }
      else {
         skm_HideCapsWarning(warnId);
      }
   }
}

The keen reader will note that this check doesn't really identify when Caps Lock is on or off. Rather, it identifies if Caps Lock is on or off when typing in an alphabetic character. If the user types in the number "9" or presses the left arrow, the first conditional statement will evaluate to false. In other words, the skm_ShowCapsWarning or skm_HideCapsWarning functions are only called when the user enters an alphabetic character.

The skm_ShowCapsWarning and skm_HideCapsWarning functions are not shown in this article; you'll have to download the source code to inspect them. They're both fairly straightforward: both reference the WarnWhenCapsLockIsOn control and then set the visibility and display properties to show or hide the warning message. The only trickiness deals with the code that displays the warning for at most a specified number of milliseconds after the user types in with Caps Lock on. Specifically, these functions use the JavaScript setTimeout and clearTimeout methods. For more information on these functions, see the JavaScript Timing Events tutorials at W3 Schools.

Using the WarnWhenCapsLockIsOn Control in an ASP.NET Web Page
The download available at the end of this article includes the complete source code for the WarnWhenCapsLockIsOn controls, as well as a demo ASP.NET website. To use the skmControls2 controls in an ASP.NET website, copy the DLL to the website's /Bin directory and then add the following @Register directive to the tops of the .aspx pages where you want to use the controls:

<%@ Register Assembly="skmControls2" Namespace="skmControls2" TagPrefix="skm" %>

(Alternatively, you can add this @Register directive in the Web.config file so that you do not need to add it to every ASP.NET page that uses the controls. See Tip/Trick: How to Register User Controls and Custom Controls in Web.config.)

The demo included in the download has an ASP.NET page that shows using the WarnWhenCapsLockIsOn control in two scenarios: on a stand-alone TextBox and on the Password TextBox in the Login control. Let's look at the stand-alone TextBox example first:

<b>Please enter your name:</b>
<asp:TextBox ID="YourName" runat="server"></asp:TextBox>

<skm:WarnWhenCapsLockIsOn runat="server" ID="WarnOnYourName"
           CssClass="CapsLockWarning" TextBoxControlId="YourName"
           WarningDisplayTime="5000"><b>Warning:</b> Caps Lock is on.</skm:WarnWhenCapsLockIsOn>

<br />
<asp:Button ID="Button1" runat="server" Text="Submit" />

The declarative markup above shows three controls: a TextBox (YourName); a WarnWhenCapsLockIsOn control; and a Button Web control. The WarnWhenCapsLockIsOn control is configured to display the message "Warning: Caps Lock is on" when the user types into the YourName textbox with Caps Lock on. It uses the CSS class CapsLockWarning for its styling, which I've defined on the page; the class specifies a light yellow background, padding, centered text, and a red border. The warning message is displayed for (at most) five seconds.

The following screen shot shows the demo page in action. Note that when Caps Lock is on and an alphabetic character is typed, the warning is displayed. This warning immediately disappears when Caps Lock is turned off and another alphabetic character is typed, or after five seconds, whatever comes first.

A warning is displayed when typing in the textbox with Caps Lock on.

This demo also shows how to apply the WarnWhenCapsLockIsOn control to the Password TextBox of a Login control. Start by adding a Login control to the page and then, from the Designer, select the "Convert to Template" from its smart tag. This will convert the Login control into a template, at which point you can add the WarnWhenCapsLockIsOn control in the Login user interface as needed, referencing the Password TextBox (whose ID property is "Password"). Be sure to put the WarnWhenCapsLockIsOn control within the Login control's template so that it can "see" the Password TextBox.

The WarnWhenCapsLockIsOn control can also be used in a Login control.

Happy Programming!

  • By Scott Mitchell
  • Posted by tornado
    |
    출처 : http://msdn.microsoft.com/ko-kr/library/cc438020(VS.71).aspx


    동적으로 웹 서버 컨트롤 템플릿 만들기

    여러 가지 이유로 인해, 런타임 전에는 필요한 템플릿과 이 템플릿에 포함해야 할 텍스트나 컨트롤을 알 수 없는 경우도 있습니다. 이러한 경우에는 코드를 사용하여 동적으로 템플릿을 만들 수 있어야 합니다.

    참고   템플릿을 Web Forms 사용자 정의 컨트롤로 만들어 이 템플릿을 페이지에 있는 컨트롤에 동적으로 바인딩해도 됩니다. 자세한 내용은 템플릿 기반 사용자 정의 컨트롤 만들기를 참조하십시오.

    템플릿을 사용하는 모든 컨트롤(DataList, RepeaterDataGrid 컨트롤)에 대해 코드를 사용하여 템플릿을 만들 수 있습니다. DataGrid 컨트롤의 경우, 다른 두 컨트롤에 대한 행 형식의 템플릿을 사용하지 않고 열을 정의하는 템플릿을 사용합니다.

    참고   DataGrid 컨트롤에 대한 템플릿 열을 만들 때는 몇 가지 차이점이 있습니다. 자세한 내용은 프로그래밍 방식으로 DataGrid 컨트롤에 템플릿 만들기를 참조하십시오.

    템플릿 클래스 만들기

    동적 템플릿을 만들려면 필요할 때 인스턴스화할 수 있는 템플릿 클래스를 만듭니다.

    참고   Visual Basic .NET에서 클래스를 만드는 데 대한 배경 설명을 보려면 클래스의 이해를 참조하십시오. Visual C# .NET의 경우에는 클래스를 참조하십시오.

    템플릿 클래스를 만들려면

    1. System.Web.UI 네임스페이스의 ITemplate 인터페이스를 구현하는 새 클래스를 만듭니다.
    2. 필요한 경우, 클래스에서 만들 템플릿의 형식(ItemTemplate, AlternatingItemTemplate 등)을 결정할 때 사용되는 값을 클래스의 생성자에 전달합니다.
         생성자에 템플릿 형식을 전달할 때 형식 안전성을 유지하려면 ListItemType 형식을 사용하여 생성자에 매개 변수를 추가하면 됩니다. ListItemType 열거형에서는 Repeater, DataListDataGrid 컨트롤에 대해 사용 가능한 템플릿 형식을 정의합니다.
    3. ITemplate 인터페이스의 유일한 멤버인 InstantiateIn 메서드를 클래스에 구현합니다. 이 메서드를 통해 텍스트 및 컨트롤의 인스턴스를 지정된 컨테이너에 삽입할 수 있습니다.
    4. InstantiateIn 메서드에서 템플릿 항목에 대한 컨트롤을 만들고 속성을 설정한 다음 부모의 Controls 컬렉션에 추가합니다. InstantiateIn 메서드에 전달된 참조를 통해 부모 컨트롤에 액세스할 수 있습니다.
      참고   Controls 컬렉션에 정적 텍스트를 직접 추가할 수는 없지만, Literal 컨트롤 또는 LiteralControl 컨트롤 등의 컨트롤을 만들고 Text 속성을 설정한 다음 이 컨트롤을 부모 컬렉션에 추가할 수는 있습니다.

      다음 예제에서는 일부 정적 텍스트("Item number:") 및 카운터를 표시하는 완전한 템플릿 클래스를 보여 줍니다. 카운터는 클래스에 대해 itemcount라는 공유 또는 정적 값(사용하는 언어에 따라 다름)으로 보존되며 새 항목이 만들어질 때마다 크기가 증가합니다.

      클래스에서는 만들어지는 템플릿의 형식을 나타내기 위해 ListItemType 열거형 값을 받는 명시적 생성자를 정의합니다. 만들어지는 템플릿의 형식에 따라 코드에서 서로 다른 종류의 컨트롤이 만들어지고 이 컨트롤은 부모 컨트롤의 Controls 컬렉션에 추가됩니다. 마지막으로, 대체 항목 템플릿에 대해 서로 다른 배경색을 가진 HTML 테이블이 만들어집니다.

      ' Visual Basic
      Private Class MyTemplate
         Implements ITemplate
         Shared itemcount As Integer = 0
         Dim TemplateType As ListItemType
      
         Sub New(ByVal type As ListItemType)
            TemplateType = type
         End Sub
      
         Sub InstantiateIn(ByVal container As Control) _
            Implements ITemplate.InstantiateIn
            Dim lc As New Literal()
            Select Case TemplateType
               Case ListItemType.Header
                  lc.Text = "<TABLE border=1><TR><TH>Items</TH></TR>"
               Case ListItemType.Item
                  lc.Text = "<TR><TD>Item number: " & itemcount.ToString _
                     & "</TD></TR>"
               Case ListItemType.AlternatingItem
                  lc.Text = "<TR><TD bgcolor=lightblue>Item number: " _
                     & itemcount.ToString & "</TD></TR>"
               Case ListItemType.Footer
                  lc.Text = "</TABLE>"
            End Select
            container.Controls.Add(lc)
            itemcount += 1
         End Sub
      End Class
      
      // C#
      public class MyTemplate : ITemplate
      {
         static int itemcount = 0;
         ListItemType templateType;
      
         public MyTemplate(ListItemType type)
         {
            templateType = type;
         }
      
         public void InstantiateIn(System.Web.UI.Control container)
         {
            Literal lc = new Literal();
            switch( templateType )
            {
               case ListItemType.Header:
                  lc.Text = "<TABLE border=1><TR><TH>Items</TH></TR>";
                  break;
               case ListItemType.Item:
                  lc.Text = "<TR><TD>Item number: " + itemcount.ToString() +
                     "</TD></TR>";
                  break;
               case ListItemType.AlternatingItem:
                  lc.Text = "<TR><TD bgcolor=lightblue>Item number: " + 
                     itemcount.ToString() + "</TD></TR>";
                  break;
               case ListItemType.Footer:
                  lc.Text = "</TABLE>";
                  break;
            }
            container.Controls.Add(lc);
            itemcount += 1;
         }
      }

    동적 템플릿 사용

    사용할 수 있는 동적 템플릿이 있으면 이 템플릿을 코드에서 인스턴스화할 수 있습니다.

    참고   DataGrid 컨트롤에서 하나의 동적 템플릿을 열로 사용하여 작업하려면 프로그래밍 방식으로 DataGrid 컨트롤에 템플릿 만들기를 참조하십시오.

    동적 템플릿을 사용하려면

    1. 동적 템플릿의 인스턴스를 만들고 적합한 경우 여기에 항목 형식의 값을 전달합니다.
    2. Repeater 또는 DataList 컨트롤의 템플릿 속성 중 하나에 ItemTemplate, AlternatingItemTemplate, HeaderTemplate 등의 인스턴스를 할당합니다.

      다음 예제에서는 동적 템플릿을 Repeater 컨트롤과 함께 사용하는 방법을 보여 줍니다. 이 예제에서는 페이지가 로드되는 동안 컨트롤이 데이터 소스에 바인딩되기 전에 템플릿이 인스턴스화됩니다.

      ' Visual Basic
      Private Sub Page_Load(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles MyBase.Load
         Repeater1.HeaderTemplate = New MyTemplate(ListItemType.Header)
         Repeater1.ItemTemplate = New MyTemplate(ListItemType.Item)
         Repeater1.AlternatingItemTemplate = _
            New MyTemplate(ListItemType.AlternatingItem)
         Repeater1.FooterTemplate = New MyTemplate(ListItemType.Footer)
         SqlDataAdapter1.Fill(DsCategories1)
         Repeater1.DataBind()
      End Sub
      
      // C#
      private void Page_Load(object sender, System.EventArgs e)
      {
         Repeater1.HeaderTemplate = new MyTemplate(ListItemType.Header);
         Repeater1.ItemTemplate = new MyTemplate(ListItemType.Item);
         Repeater1.AlternatingItemTemplate = 
            new MyTemplate(ListItemType.AlternatingItem);
         Repeater1.FooterTemplate = new MyTemplate(ListItemType.Footer);
         sqlDataAdapter1.Fill(dsCategories1);
         Repeater1.DataBind();
      }

    템플릿에 데이터 바인딩 추가

    템플릿 클래스 안에서 데이터에 액세스할 수 있는 방법은 클래스를 만드는 방법에 따라 다양합니다. 이 중에서 페이지 아키텍처 자체에서 데이터 바인딩을 구현하는 것이 가장 좋습니다. 템플릿에 컨트롤을 추가하면 이러한 컨트롤의 DataBinding 이벤트에 대한 처리기도 추가됩니다. 이 이벤트는 템플릿 항목과 해당 템플릿과 관련된 컨트롤이 모두 만들어진 후에 발생하며 데이터를 페치하여 컨트롤에서 사용할 수 있도록 합니다.

    참고   템플릿에 컨트롤을 만들 때 디자인 타임에 템플릿을 정의할 때처럼 데이터 바인딩 식을 문자열로 포함할 수 없습니다. 데이터 바인딩 식은 템플릿이 만들어지기 전에 발생하는 페이지 처리 과정 단계에서 코드로 변환되기 때문입니다.

    DataBinding 이벤트에 대한 처리기에서 컨트롤의 내용을 조작할 수 있습니다. 필수적인 것은 아니지만, 보통 임의의 위치에서 데이터를 페치(fetch)하여 컨트롤의 Text 속성에 할당합니다.

    참고   Web Forms 페이지에서의 데이터 바인딩 작업에 대한 배경 설명은 Web Forms 데이터 바인딩을 참조하십시오.

    동적 템플릿에 데이터 바인딩을 추가하려면 다음 작업을 수행해야 합니다.

    • 템플릿에서 만든 컨트롤에 데이터 바인딩 이벤트 처리기를 추가합니다.
    • 바인딩 대상이 되는 처리기를 만듭니다. 바인딩할 데이터를 이 처리기에서 가져온 다음, 바인딩되는 컨트롤의 해당 속성에 할당합니다.

    데이터 바인딩 이벤트 처리기를 추가하려면

    • 동적 템플릿에 컨트롤을 만든 후에 표준 명령을 사용하여 컨트롤의 DataBinding 이벤트를 나중에 만들 메서드에 바인딩합니다.
      참고   동적으로 이벤트 처리기를 추가하는 방법에 대한 자세한 내용은 AddHandler 및 RemoveHandler(Visual Basic용)와 이벤트 자습서(Visual C#용)를 참조하십시오.

      다음 예제에서는 새로 만든 컨트롤을 TemplateControl_DataBinding 메서드에 바인딩하는 템플릿 클래스의 코드를 보여 줍니다.

      ' Visual Basic
      Dim lc As New Literal()
         Case ListItemType.Item
         lc.Text = "<TR><TD>"
         AddHandler lc.DataBinding, AddressOf TemplateControl_DataBinding
      
      // C#
      Literal lc = new Literal();
      case ListItemType.Item:
         lc.Text = "<TR><TD>";
         lc.DataBinding += new EventHandler(TemplateControl_DataBinding);
         break;

      이 예제에서 리터럴 컨트롤의 Text 속성에 추가하는 텍스트는 이전의 예제에 나온 텍스트와는 다릅니다. 여기에는 표 행의 시작 부분과 항목 템플릿에 대한 셀만 포함되어 있습니다. 데이터 바인딩 이벤트 처리기에서 셀과 행을 완성합니다.

    다음 단계에서는 컨트롤에 데이터가 바인딩될 때 호출되는 이벤트 처리기를 만듭니다.

    DataBinding 이벤트에 대한 처리기를 만들려면

    1. 템플릿 클래스를 구성하며 이 클래스의 InstantiateIn 등과 같은 다른 메서드와 동일한 수준의 역할을 수행할 메서드를 만듭니다. 처리기의 이름은 이벤트 처리기를 바인딩할 때 사용했던 이름과 같아야 합니다. 이 이벤트에는 다음과 같은 서명이 있어야 합니다.
      ' Visual Basic
      Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
         ByVal e As System.EventArgs)
      
      // C#
      private void TemplateControl_DataBinding(object sender,
         System.EventArgs e)
    2. 다음을 수행하여 현재 템플릿 항목에 대한 데이터가 포함된 DataItem 개체의 참조를 가져옵니다.
      1. 템플릿 항목에 대한 참조를 가져옵니다. 참조를 보관할 변수를 만든 다음 이 변수에 컨트롤의 NamingContainer 속성에서 가져오는 값을 할당합니다.
      2. 이 참조를 사용하여 이름 지정 컨테이너(템플릿 항목)의 DataItem 속성을 가져옵니다.
      3. DataItem 개체에서 데이터 열 등의 개별 데이터 요소를 추출하고, 이 요소를 사용하여 바인딩 대상 컨트롤의 속성을 설정합니다.

        다음 코드에서는 동적 템플릿 안에서 데이터 바인딩을 수행하는 방법 중 하나를 보여 줍니다. 여기에서는 Repeater 컨트롤의 템플릿에서 만들어지는 Literal 컨트롤에 대한 데이터 바인딩 이벤트 처리기의 전체 코드를 보여 줍니다.

        ' Visual Basic
        Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
           ByVal e As System.EventArgs)
           Dim lc As Literal
           lc = CType(sender, Literal)
           Dim container As RepeaterItem
           container = CType(lc.NamingContainer, RepeaterItem)
           lc.Text &= DataBinder.Eval(container.DataItem, "CategoryName")
           lc.Text &= "</TD></TR>"
        End Sub
        
        // C#
        private void TemplateControl_DataBinding(object sender,
        System.EventArgs e)
        {
           Literal lc;
           lc = (Literal) sender;
           RepeaterItem container = (RepeaterItem) lc.NamingContainer;
           lc.Text += DataBinder.Eval(container.DataItem, "CategoryName");
           lc.Text += "</TD></TR>";
        }
        참고   템플릿에 여러 형식의 컨트롤이 있는 경우 각 컨트롤 형식마다 서로 다른 데이터 바인딩 이벤트 처리기를 만들어야 합니다.

    참고 항목

    Posted by tornado
    |


    출처 : http://blog.naver.com/devstory/130038823596



     

    객체의 좌표 값 추출

     

    익스플로러 6 / 파이어폭스 2 에서 테스트 되었습니다.

     

    <HTML>
    <HEAD>
     <SCRIPT type = "text/javascript">
      /**
       * 좌표 값을 측정한다.
       *
       * @param obj 측정 요망 객체
       */
      function getBounds( obj ) {
       var ret = new Object();

       if(document.all) {
        var rect = obj.getBoundingClientRect();
        ret.left = rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft);
        ret.top = rect.top + (document.documentElement.scrollTop || document.body.scrollTop);
        ret.width = rect.right - rect.left;
        ret.height = rect.bottom - rect.top;
       } else {
        var box = document.getBoxObjectFor(obj);
        ret.left = box.x;
        ret.top = box.y;
        ret.width = box.width;
        ret.height = box.height;
       }

       return ret;
      }

      /**
       * 버튼 객체의 좌표 추출
       */
      function getThisCoordi() {
       var obj = getBounds( document.getElementById("testBtn") );

       alert( "left : " + obj.left + ", top : " + obj.top + ", width : " + obj.width + ", height : " + obj.height );
      }
     </SCRIPT>
    </HEAD>
    <BODY>
    <P>&nbsp;</P>
    <CENTER><INPUT type = "button" id = "testBtn" value = "테스트" onClick = "getThisCoordi()"/></CENTER>
    </BODY>
    </HTML>

    Posted by tornado
    |

    출처 : http://blog.naver.com/devstory/130038823596


    객체의 좌표 값 추출

     

    익스플로러 6 / 파이어폭스 2 에서 테스트 되었습니다.

     

    <HTML>
    <HEAD>
     <SCRIPT type = "text/javascript">
      /**
       * 좌표 값을 측정한다.
       *
       * @param obj 측정 요망 객체
       */
      function getBounds( obj ) {
       var ret = new Object();

       if(document.all) {
        var rect = obj.getBoundingClientRect();
        ret.left = rect.left + (document.documentElement.scrollLeft || document.body.scrollLeft);
        ret.top = rect.top + (document.documentElement.scrollTop || document.body.scrollTop);
        ret.width = rect.right - rect.left;
        ret.height = rect.bottom - rect.top;
       } else {
        var box = document.getBoxObjectFor(obj);
        ret.left = box.x;
        ret.top = box.y;
        ret.width = box.width;
        ret.height = box.height;
       }

       return ret;
      }

      /**
       * 버튼 객체의 좌표 추출
       */
      function getThisCoordi() {
       var obj = getBounds( document.getElementById("testBtn") );

       alert( "left : " + obj.left + ", top : " + obj.top + ", width : " + obj.width + ", height : " + obj.height );
      }
     </SCRIPT>
    </HEAD>
    <BODY>
    <P>&nbsp;</P>
    <CENTER><INPUT type = "button" id = "testBtn" value = "테스트" onClick = "getThisCoordi()"/></CENTER>
    </BODY>
    </HTML>

    Posted by tornado
    |
    Jquery 에 달력만 있는줄 알았는데, 시간 선택하는 녀석도 있었습니다.

    목마른 놈이 우물 판다더니... 덕분에 일 하나 주워 먹었다~


    첫번째 :

    [출처] http://www.jnathanson.com/index.cfm?page=jquery/clockpick/ClockPick#config

    BGIFramework 라는 js 를 제공해 주는데, 이것을 같이 쓰면 CheckBox 같은것에 겹쳐지지 않는다.

    UI 적으로는 아주 좋지는 않지만 쓰기에는 편리함.



    두번째 :

    [출처] http://haineault.com/media/jquery/ui-timepickr/page/#d-demo-wrapper-1

    요거는 모양도 이쁘고, 테마도 지원된다.

    SelectBox, CheckBox 등이 있으면 겹쳐지는 문제가 발생.

    고치려고 하니, Jquery 초보라 힘듬 -.-;








    Posted by tornado
    |
    출처 : http://www.eggheadcafe.com/articles/system.xml.xmlserialization.asp



    Related Articles: XmlSerializer to Serialize Class to Xml and Bulk Load Data
     
    Object Serialization is a process through which an object's state is transformed into some serial data format, such as XML or a binary format.  For example, you can serialize an object and transport it over the Internet using HTTP between a client and a server.  On the other end, deserialization reconstructs the object from the stream.  XML was designed to be a technology for data exchange across heterogeneous systems.  It can be easily transmitted between distributed components because of its platform independence and its simple, text-based, self-describing format.  In this article I will discuss the serialization of custom business objects to XML and reconstruction the object back from the XML string, using C#.  This process is called XML serialization and is very well supported by .Net.
     
    Some good uses for serialization/deserialization include:
  • Storing user preferences in an object.
  • Maintaining security information across pages and applications.
  • Modification of XML documents without using the DOM.
  • Passing an object from one application to another.
  • Passing an object from one domain to another.
  • Passing an object through a firewall as an XML string.
  • These are only a few of the many possibilities that serialization opens up for us.
     
    Suppose we have an object defined and instantiated as shown below:
     class Person
      {
         private String personName;
         private Int32 personAge;
         public String Name
         { 
           get { return personName;  } 
           set { personName = value; }
         } 
         public Int32 Age 
         {
           get { return personAge; }
           set { personAge = value;}
         }
       }
    
    
    Instantiation of the class is shown below:
       Person oPerson = new Person(); 
       oPerson.Name = "Anthony";
       oPerson.Age = 38;  
    
    
     
    Let's say that for some reason, we wanted to save a copy of this object just as it is at this very moment.  We could serialize it as an XML document that would look something like this:
    Anthony 38
    Then, at some later time when we needed to use the object again, we could just deserialize it and have our object restored to us just as it was at the moment we serialized it.  However XML serialization follows certain rules and the classes defined by us have to conform to these rules.
    1. XML serialization serializes only the public fields and property values of an object into an XML stream
    2. XML serialization does not include type information
    3. XML serialization requires a default constructor to be declared in the class that is to be serialized
    4. XML serialization requires all properties that are to be serialized as read write properties.  Read only properties are not serialized.
     
    Serialize class
    The .Net framework provides a rich collection of classes for serialization.  As we are concerned with XML serialization, we will examine the use of the XmlSerializer class.  This is the central class for XML serialization and its most important methods are the Serialize and Deserialize methods.  Most of the articles discussing XML serialization use IO streams for saving serialized data into XML files, however in my example I will demonstrate the use of XML serialization to convert an object into XML string and store it in a memory stream instead of an XML file.  This technique is extremely useful in cases where a complex object is to be converted to XML string and its properties have to be manipulated and then the object recreated from the XML string on the fly!!
     
    Attributes
    Before we start with the process of demonstrating the technique of XML serialization let us have a small discussion on Metadata Attributes.  A complete discussion of Metadata Attributes is beyond the scope of this article.  Nevertheless we need to understand the concepts behind metadata attributes to understand how XML serialization works.  Attributes are annotations to an interface or a class definition to specify certain behavior.  Assemblies, classes, fields and methods, each can have attributes.  Some are used by the compiler, some are used by the runtime, e.g. to identify a method requires a call to a web service, or how to serialize a class to XML.  There is very little overhead associated when using attributes.  Attaching attributes to a class is done directly in the source code.
     
    The syntax to initialize a metadata attribute and attach
    it to a class or a method in C# is either:
     [Attribute(constructor-parameters-list )] 
    or: 
    [Attribute(constructor-parameters-list, property=value, ... )] 
    
    // The System.Xml.Serialization namespace introduces a set of attributes
    // to control how classes are mapped to XML.  Let's look at a quick example:
    // One of the attributes used with XML serialization is the XmlRootAttribute
    // to change the name of the root element of a serialization hierarchy."
    
    You would add the XmlRootAttribute to a class like this: 
    
    using System.Xml.Serialization; 
    [XmlRootAttribute(Name="Human", IsNullable=false)] 
    public class Person 
    { 
    // class implementation goes here 
    } 
    
    
     
    If we make this change in the class declaration of listing 1, and serialize the instance of this class we will get the XML generated resembling the one shown below:
    <Human> 
    <Name>Anthony</Name> 
    <Age>38</Age> 
    </Human> 
    
    
     
    We would be using UTF-8 encoding for the creating the XML stream for the custom object as it supports a wide range of Unicode character values and surrogates.  For this purpose, we will make use of the UTF8Encoding class provided by the .Net framework.  For more information on UTF8Encoding you may want to refer to MSDN at:
    UTF8Encoding
    For explaining the concept of XML serialization I will create and use a demo class Animal with a number of properties that describe an animal such as name, length, weight, place of existence etc.  First create a C# console application using the Visual Studio.Net and name the project as MySerializer.  This will automatically create a namespace MySerializer.  Import the following namespaces into the project:
    1. System.Xml.Serialization
    2. System.IO
    3. System.Text
     
    Now add a new class and name it Animal.  The code for this class is given below:
     using System;
     
     namespace MySerializer
     {
         [XmlRootAttribute(ElementName="WildAnimal", IsNullable=false)]
         public class Animal
         {
           public Animal() {   }
    
           private String animalName;
           private String foodTypeCategory;
           private Boolean isDomesticed;
           private String placeOfExistence;
           private Int32 length;
           private Int32 height;
           private Int32 weight;
           public String AnimalName
                 { get { return animalName; } set { animalName = value; } }
           public String FoodTypeCategory 
                  { get { return foodTypeCategory; }
                    set { foodTypeCategory = value; } }
           public Boolean IsDomesticed
             { get { return isDomesticed; } 
               set { isDomesticed = value; } } 
           public String PlaceOfExistence 
               { get { return placeOfExistence; } set { placeOfExistence = value; } } 
           public Int32 Length { get { return length; } set { length = value; } }
           public Int32 Height { get { return height; } set { height = value; } } 
           public Int32 Weight { get { return weight; } set { weight = value; } } 
         }
     } 
    
    
     
    Listing 2: Custom class whose objects are to be serialized to XML
    When you create the C# console application a default class by the name of Class1 gets added to the project.  This class contains the definition of the Main function that is the entry point of the assembly.  Rename this class from "Class1" to clsMain.  In this class clsMain, we will define the custom methods to serialize and deserialize the object of the class Animal. Apart from these there are helper methods to convert a UTF-8 byte array to string and vice - versa.
    The definition of these methods is given below:
    private String UTF8ByteArrayToString(Byte[] characters) 
    { 
    
      UTF8Encoding encoding = new UTF8Encoding();
      String constructedString = encoding.GetString(characters);
      return (constructedString);
     }
     
     private Byte[] StringToUTF8ByteArray(String pXmlString)
     {
         UTF8Encoding encoding = new UTF8Encoding();
         Byte[] byteArray = encoding.GetBytes(pXmlString);
         return byteArray;
     } 
    
    
     
    Listing 3: Helper Methods
    Serialization
    Now we will add a custom method SerializeObject to the class clsMain which will use the XmlSerializer to serialize the object to XML string.
    The code for this method is given below:
     
    public String SerializeObject(Object pObject) 
    {
        try 
        {
          String XmlizedString = null;
          MemoryStream memoryStream = new MemoryStream();
          XmlSerializer xs = new XmlSerializer(typeof(Animal));
          XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
          xs.Serialize(xmlTextWriter, pObject);
          memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
          XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
          return XmlizedString;
         }
         catch (Exception e) { System.Console.WriteLine(e); return null; }
     } 
    
    
     
    Listing 4: Method to serialize the custom business object
    Let us look through the code carefully.  First we create an instance of the MemoryStream class since we intend to keep the XML string in memory instead of saving it to a file.  Instantiate the XmlSerializer class with the type of the class that is to be serialized.  In our case this is the class Animal.  Now we use the XmlTextWriter Class that provides a fast, non-cached, forward-only way of generating streams or files containing XML data.  Notice that we use an overloaded constructor of the XmlTextWriter class and set the encoding to UTF-8.  This means that the XML document will be created with UTF-8 encoding.
    Now, we go to the most important step and that is calling one of the overloaded implementations of the Serialize method of the XmlSerializer object.  We now read the XML stream generated by the serializer from the BaseStream of the XmlTextWriter.  Since the BaseStream property returned by the XmlTextWriter is of the type System.IO.Stream, we can easily type cast it into MemoryStream (which is derived from System.IO.Stream) for our purpose.
    We now pass the Byte[] array returned by the ToArray() method of the MemoryStream object to the helper function UTF8ByteArrayToString.  This method constructs the XML string from the binary array and returns the same.  This small piece of trick is performed by the overloaded implementation of the GetString() method of the UTF8Encoding class.
     
    The output that is generated is given below:
    <?xml version="1.0" encoding="utf-8"?> 
    <WildAnimal xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <AnimalName>Lion</AnimalName> 
    <FoodTypeCategory>Carnivore</FoodTypeCategory> 
    <IsDomesticed>false</IsDomesticed> 
    <PlaceOfExistence>Africa</PlaceOfExistence> 
    <Length>15</Length> 
    <Height>4</Height> 
    <Weight>900</Weight> 
    </WildAnimal> 
    
    
     
    Notice that all the properties defined in the class Animal are serialized into nodes and the name of the root also gets changed from Animal to WildAnimal, this is because we had included the attribute XmlRootAttribute in the declaration of the class Animal.
    Deserialization
    Just as we had created a custom method to serialize the object, we will create another method in the class clsMain which will use the Deserialize() method of the XmlSerializer class to recreate the object from the XML string.
    The code for this method is given below:
     public Object DeserializeObject(String pXmlizedString)
     {
         XmlSerializer xs = new XmlSerializer(typeof(Automobile));
         MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString));
         XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
         return xs.Deserialize(memoryStream);
      } 
    
    
    To get the Animal object back from the XML string you will simply call this method and pass the XML string.  It will first convert the XML string to a byte array (exactly the reverse of what we did in serialization) and then recreate the object from the XmlSerializer.
    There you are!!  You have now learnt the entire process of serializing a custom object into an XML string and keeping it in an in memory variable and then reconstructing it back using deserialization.  With the help of powerful XMLDocument class and other rich XML parsing classes and readers (such as XmlReader) provided by .Net you can change values or nodes , change attributes and apply advanced XML processing functions to XML document.

    '.NET > C#' 카테고리의 다른 글

    [C#] Network Driver Check  (0) 2011.08.11
    [펌] Design Pattern --> C# @.@;  (0) 2009.12.24
    ADHelper - An Active Directory Class  (0) 2009.08.17
    C# - Dynamically Invoke Web Service At Runtime  (0) 2009.08.13
    Change the group of a user in AD through C#  (0) 2009.06.16
    Posted by tornado
    |
    출처 : http://www.c-sharpcorner.com/uploadfile/craig_aroa/adhelper08232005064459am/adhelper.aspx?login=true&user=yheesung


    흠..  예전거 보다 더 좋아진것 같습니다.
    앞으로는 누가 더 검색 잘하고, 누가 더 짜집기 잘 하느냐에 따라 프로그래머의 레벨이 정해지지 않을까...


    Working on my latest project required quite a degree of development against the Active Directory. Not having had any AD experience before slowed me down for a while, but after trawling through lost of news groups etc, I gathered enough information to do what I needed to do.

    I have developed an ADHelper class that will should take care of most AD requirements, from :-

    • creating/updating a user
    • assigning a user to a group
    • enabling/disabling their account
    • setting password
    • checking if a user is valid
    • loggin in
    • checking if a user exists
    • performing queries

    All while returning DataSets to allow easy binding to datagrids etc.

    Im by no means an expert, but hopefully this helps some of you facing the same problems that I had.

    NOTES
    =====

    This class will return a mix of ActiveDirectory 'DirectoryEntry' objects and DataSets that u can plug into your business layer

    The first couple of lines that set the following private varables, need to be changed so that the 'Configuration' is the .Net ConfigurationSettings.AppSettings["xxx"].ToString, as the configuration object is a custom one that has not been included.

    private static string ADPath=Configuration.ADFullPath ;
    private static string
    ADUser = Configuration.ADAdminUser ;
    private static string ADPassword = Configuration.ADAdminPassword ;

    Change to :-

    private static string ADPath=ConfigurationSettings.AppSettings["ADFullPath"].ToString() ;
    private static string
    ADUser = ConfigurationSettings.AppSettings["ADAdminUser"].ToString() ;
    private static string ADPassword = ConfigurationSettings.AppSettings["ADAdminPassword"].ToString() ;



    Posted by tornado
    |

    출처 : http://www.crowsprogramming.com/archives/66


    C# - Dynamically Invoke Web Service At Runtime

    Web services have become an integral part of the communications between software over a network. There are a lot of ugly details behind how they work but thankfully C# hide a lot of those gory details. What you need to know is that there is a web service description (WSDL) that describes the available services and the data types they use (via XML).

    You can use the WSDL to create types in C# that can communicate with the web service. There are a couple of ways that you can do this. You can generate a proxy class using the WSDL utility in the .NET SDK and add it to your project. You can also download the WSDL file at runtime, create the proxy class, compile it into an assembly, and execute the methods on it. This allows you to dynamically invoke methods from a web service that aren’t known at build time and is the approach I will explore today.

    Step 1 – Obtain a ServiceDescriptionImporter

    We want to create a ServiceDescriptionImporter object that we can use to generate the web service proxy class. We have to pass to it the WSDL location which is an XML document.

    XmlTextReader xmlreader = new XmlTextReader(“MyWebService” + "?wsdl");
     
    ServiceDescription serviceDescription = ServiceDescription.Read(xmlreader);
     
    // build an importer, that assumes the SOAP protocol, client binding, and generates properties
    ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
    descriptionImporter.ProtocolName = "Soap";
    descriptionImporter.AddServiceDescription(serviceDescription, null, null);
    descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
    descriptionImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;

    Step 2 – Compile an Assembly from the importer

    Now that we have the ServiceDescriptionImporter we need to use it to compile a proxy assembly that we can use to communicate with the web service. The assembly will exist in the users’ temporary folder.

    // a namespace and compile unit are needed by importer
    CodeNamespace codeNamespace = new CodeNamespace();
    CodeCompileUnit codeUnit = new CodeCompileUnit();
     
    codeUnit.Namespaces.Add(codeNamespace);
     
    ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);
     
    if (importWarnings == 0) // no warnings
    {
         // create a c# compiler
         CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
     
         // include the assembly references needed to compile
         string[] references = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
     
         CompilerParameters parameters = new CompilerParameters(references);
     
         // compile into assembly
         CompilerResults results = compiler.CompileAssemblyFromDom(parameters, codeUnit);
     
         foreach (CompilerError oops in results.Errors)
         {
              // trap these errors and make them available to exception object
              throw new Exception("Compilation Error Creating Assembly");
         }
     
         // all done....
         return results.CompiledAssembly;
    }
    else
    {
         // warnings issued from importers, something wrong with WSDL
         throw new Exception("Invalid WSDL");
    }

    Step 3 – Execute Methods from the Web Service

    Finally we have an assembly built from the web service description and now we can invoke methods from it just like any other ordinary assembly we might use. To accomplish this we must use reflection to discover the correct method.

    object obj = this.webServiceAssembly.CreateInstance(serviceName);
     
    Type type = obj.GetType();
     
    return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);

    And there you have it, dynamic invocation of web service methods at runtime. Using this technique you can invoke methods from any arbitrary web service at runtime.

    Here is a full example class for dynamically invoking a web service method in C#.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.Web.Services;
    using System.Web.Services.Description;
    using System.Web.Services.Discovery;
    using System.Xml;
     
    namespace DynamicWebExample
    {
        class WebServiceInvoker
        {
            Dictionary<string, Type> availableTypes;
     
            /// <summary>
            /// Text description of the available services within this web service.
            /// </summary>
            public List<string> AvailableServices
            {
                get{ return this.services; }
            }
     
            /// <summary>
            /// Creates the service invoker using the specified web service.
            /// </summary>
            /// <param name="webServiceUri"></param>
            public WebServiceInvoker(Uri webServiceUri)
            {
                this.services = new List<string>(); // available services
                this.availableTypes = new Dictionary<string, Type>(); // available types
     
                // create an assembly from the web service description
                this.webServiceAssembly = BuildAssemblyFromWSDL(webServiceUri);
     
                // see what service types are available
                Type[] types = this.webServiceAssembly.GetExportedTypes();
     
                // and save them
                foreach (Type type in types)
                {
                    services.Add(type.FullName);
                    availableTypes.Add(type.FullName, type);
                }
            }
     
            /// <summary>
            /// Gets a list of all methods available for the specified service.
            /// </summary>
            /// <param name="serviceName"></param>
            /// <returns></returns>
            public List<string> EnumerateServiceMethods(string serviceName)
            {
                List<string> methods = new List<string>();
     
                if (!this.availableTypes.ContainsKey(serviceName))
                    throw new Exception("Service Not Available");
                else
                {
                    Type type = this.availableTypes[serviceName];
     
                    // only find methods of this object type (the one we generated)
                    // we don't want inherited members (this type inherited from SoapHttpClientProtocol)
                    foreach (MethodInfo minfo in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                        methods.Add(minfo.Name);
     
                    return methods;
                }
            }
     
            /// <summary>
            /// Invokes the specified method of the named service.
            /// </summary>
            /// <typeparam name="T">The expected return type.</typeparam>
            /// <param name="serviceName">The name of the service to use.</param>
            /// <param name="methodName">The name of the method to call.</param>
            /// <param name="args">The arguments to the method.</param>
            /// <returns>The return value from the web service method.</returns>
            public T InvokeMethod<T>( string serviceName, string methodName, params object[] args )
            {
                // create an instance of the specified service
                // and invoke the method
                object obj = this.webServiceAssembly.CreateInstance(serviceName);
     
                Type type = obj.GetType();
     
                return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);
            }
     
            /// <summary>
            /// Builds the web service description importer, which allows us to generate a proxy class based on the 
            /// content of the WSDL described by the XmlTextReader.
            /// </summary>
            /// <param name="xmlreader">The WSDL content, described by XML.</param>
            /// <returns>A ServiceDescriptionImporter that can be used to create a proxy class.</returns>
            private ServiceDescriptionImporter BuildServiceDescriptionImporter( XmlTextReader xmlreader )
            {
                // make sure xml describes a valid wsdl
                if (!ServiceDescription.CanRead(xmlreader))
                    throw new Exception("Invalid Web Service Description");
     
                // parse wsdl
                ServiceDescription serviceDescription = ServiceDescription.Read(xmlreader);
     
                // build an importer, that assumes the SOAP protocol, client binding, and generates properties
                ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
                descriptionImporter.ProtocolName = "Soap";
                descriptionImporter.AddServiceDescription(serviceDescription, null, null);
                descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
                descriptionImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
     
                return descriptionImporter;
            }
     
            /// <summary>
            /// Compiles an assembly from the proxy class provided by the ServiceDescriptionImporter.
            /// </summary>
            /// <param name="descriptionImporter"></param>
            /// <returns>An assembly that can be used to execute the web service methods.</returns>
            private Assembly CompileAssembly(ServiceDescriptionImporter descriptionImporter)
            {
                // a namespace and compile unit are needed by importer
                CodeNamespace codeNamespace = new CodeNamespace();
                CodeCompileUnit codeUnit = new CodeCompileUnit();
     
                codeUnit.Namespaces.Add(codeNamespace);
     
                ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);
     
                if (importWarnings == 0) // no warnings
                {
                    // create a c# compiler
                    CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
     
                    // include the assembly references needed to compile
                    string[] references = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
     
                    CompilerParameters parameters = new CompilerParameters(references);
     
                    // compile into assembly
                    CompilerResults results = compiler.CompileAssemblyFromDom(parameters, codeUnit);
     
                    foreach (CompilerError oops in results.Errors)
                    {
                        // trap these errors and make them available to exception object
                        throw new Exception("Compilation Error Creating Assembly");
                    }
     
                    // all done....
                    return results.CompiledAssembly;
                }
                else
                {
                    // warnings issued from importers, something wrong with WSDL
                    throw new Exception("Invalid WSDL");
                }
            }
     
            /// <summary>
            /// Builds an assembly from a web service description.
            /// The assembly can be used to execute the web service methods.
            /// </summary>
            /// <param name="webServiceUri">Location of WSDL.</param>
            /// <returns>A web service assembly.</returns>
            private Assembly BuildAssemblyFromWSDL(Uri webServiceUri)
            {
                if (String.IsNullOrEmpty(webServiceUri.ToString()))
                    throw new Exception("Web Service Not Found");
     
                XmlTextReader xmlreader = new XmlTextReader(webServiceUri.ToString() + "?wsdl");
     
                ServiceDescriptionImporter descriptionImporter = BuildServiceDescriptionImporter(xmlreader);
     
                return CompileAssembly(descriptionImporter);
            }
     
            private Assembly webServiceAssembly;
            private List<string> services;
        }
    }

    This C# class can be easily used to invoke web service methods:

    WebServiceInvoker invoker = new WebServiceInvoker(new Uri("http://localhost/services/test.php"));
     
    string service = “MyService”;
    string method = “MyMethod”;
     
    string[] args = new string[] { “arg1”, “arg2” };
     
    string result = invoker.InvokeMethod<string>(service, method, args);

    I’ve put together an example application that you can download to evaluate the class. It allows you to invoke methods from a web service entered on the GUI and see the return value. You can download it here.

    I hope you find this useful and if you have any questions or comments be sure to leave them here.

    April 8, 2009   Posted in: Programming

    27 Responses

    1. Joel Chinchilla - April 17, 2009

      Hi, I tried to test your example with a Java Web Service, however I need to pass credentials to Web Service. How can I do it?

    2. Neena - May 7, 2009

      Can I call this code from java

    3. crow - May 10, 2009

      Not that I am aware of.

    4. Sergio - May 14, 2009

      Hi!
      finally a good example on how to call WS dynamically!
      I tryed your code, and got this problem:
      - my WS is as follows:

      public class Service1 : System.Web.Services.WebService
      {
      public Service1()
      {
      InitializeComponent();
      }

      [WebMethod]
      public double Sum(double num1, double num2)
      {
      if ( guid == “”)
      return -1;
      return num1 + num2;
      }
      }

      couldn’t be as simpler as this.
      When i run your code, it does in fact create an assemby whith the correct Service1 classname and the Sum method.
      So everything seems to be ok.
      Problem is when I invoke Sum method it sends an exception saying that “Method ‘Service1.Sum’ not found” on line :
      return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);

      Any clue?

      thanks in advance!

    5. shortcuts - May 18, 2009

      Off-topic Help - Need a secure web proxy to get around my school firewall. Any suggestions?

    6. Jeremy Foster - May 19, 2009

      I have this implemented and working but I have run into a limitation. I can not figure out how to capture multiple returned values in the SOAP response. Do you know of a way to do this?

    7. Sergio - May 19, 2009

      Jeremy,

      what do you mean with “multiple returned values in the SOAP response”. A method only returns 1 value/object. The value itself can have a collection of values/objects. Is this what you meant?
      You may try to transform the returned value to XML. Use this:

      public static string SerializeObjectToXML(T obj)
      {
      try
      {
      string xmlString = null;
      MemoryStream memoryStream = new MemoryStream();
      System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
      string s = “”;
      XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
      System.Runtime.Serialization.Formatters.Soap.SoapFormatter xsoap = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
      xsoap.Serialize(memoryStream, obj);

      xmlString = UTF8ByteArrayToString(memoryStream.ToArray());
      return xmlString;
      }
      catch(Exception ex)
      {
      ex.GetType();
      return string.Empty;
      }
      }

      public static T UnserializeObjectFromXML(string xml)
      {
      System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
      MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(xml));
      XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
      return (T)xs.Deserialize(memoryStream);
      }

      The Serialize method uses the SoapFormatter class, and in fact serializes the returned object just like what the Webservice call does.

    8. Izzy - May 22, 2009

      Hi, Crows.
      i get this webpage/artical by google.

      i got one question.

      if the input parameter of the method is normal types, like string, int etc, then it is ok.

      right now, I got one webservie, and its input parameter of the function is like this

      string
      string
      int
      int
      int
      int
      int
      int
      int
      int

      there is only one input parameter : TestMessage_input.
      it is a type which is similiar with Struct.

      I’m confused about how to forming such an input parameter in GUI???
      thanks

      your reply will be appreciated and helpful.

    9. Izzy - May 22, 2009

      oh,some infos are missing.they were deleted automatically.

      would you mind telling me your email?
      since i really have some confusions about using this.
      is that ok?

    10. Shaun - May 22, 2009

      Excellent routine! I’m having a problem using this class however. When I call “return results.CompiledAssembly;” I get the following exception:

      Execution permission cannot be acquired.
      Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

      Exception Details: System.Security.Policy.PolicyException: Execution permission cannot be acquired.

      Source Error:

      An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

      Stack Trace:

      [PolicyException: Execution permission cannot be acquired.]
      System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Boolean checkExecutionPermission) +10236136
      System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Int32& securitySpecialFlags, Boolean checkExecutionPermission) +97

      [FileLoadException: Could not load file or assembly 'm2wivo6v, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Failed to grant permission to execute. (Exception from HRESULT: 0x80131418)]
      System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +0
      System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +416
      System.Reflection.Assembly.Load(AssemblyName assemblyRef, Evidence assemblySecurity) +33
      System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() +105…

      I’m running this code in SharePoint 2007 on Windows Server 2008.

    11. vikram - May 26, 2009

      It’s working fine but application memory increases when web service call are made 2500 times.

      Can we delete the temporary files created while compiling assembly ?

    12. marmri - May 31, 2009

      Hi,
      Thank you for this great example.
      I have the same problem as Sergio - May 14, 2009
      Did you wirte him any suggestion? Please forward it or add it in this article for the whole aucience!
      I have another question: how to do, if you have following situation:

      MyWebReference.GoodbyeWorldWSService myProxy = new MyWebReference.GoodbyeWorldWSService();
      MyWebReference.sayGoodbye request = new MyWebReference.sayGoodbye();
      request.message = “ciao”;
      myProxy.sayGoodbye(request);

      I mean, you have like an object as parameter you first initialize then invoke the service method!

      Please help, is urgent. Thanx a lot in advance

    13. Jeff - June 13, 2009

      Hi As I walk on the code.. i see that the reason why its throwing an exception on this line (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args); it is maybe because you are calling a method with complex (custom) type and not a generic type. try to have a breakpoint on that line and see the details of the “type” variable.

    14. shail - June 27, 2009

      I am using your example. But its giving me an error on InvokeMember that “The request failed with HTTP status 401: Access Denied” Is there anything special, i will have to do here?

      Thanks,

      Shail …

    15. RadoColo - June 30, 2009

      Beautiful, works like a charm!

    16. usmanbinasif - July 6, 2009

      Dear it is awesome code example of this problem domain, and it is very helpful for me.

      Thanks for sharing such a wonderful peice of code.

      Regards,
      Usman Javed

    17. newbieDotNET - July 7, 2009

      Will it be possible to invoke or set the timeout property? Any help would be greatly appreciated.

      Thanks,
      Jon

    18. David Roys - July 8, 2009

      What an awesome example. Well explained and a great download! Thank you for your time and effort. Unfortunately it doesn’t quite work for me.

      I am also having the problem with authentication that shail posted. I know that when I use my web service by generating the proxy class, I need to use the line:

      ws.UseDefaultCredentials = true in order to be able to user the service.

      I am getting the following error:

      Unable To Load Service: The remote server returned an error: (401) Unauthorized.

      when I click the Load Service button and I can only assume it is because the XMLTextReader is not negotiating my credentials. If I use Internet explorer to hit the URL it will give me the WSDL but I believe this is because it handles the challenge response correctly. Do I need to use another method of getting my WSDL - i.e. not using XMLTextReader?

      Thanks again for such a great post! I learnt a lot.

    19. Mark - July 8, 2009

      Good work, excellent explanation.

      functions that expect strings do work, but functions that expect other types (int, byte[], …) do not work.

      Any idea how to solve this?

      Thanks

      Mark

    20. David Roys - July 10, 2009

      Hi there, OK, I thought I would let other readers know that I managed to sort out my problems with authentication.

      You can read the details on a blog post I made http://www.teachmenav.com/blogs/dave/archive/2009/07/11/using-reflection-to-call-nav-2009-web-services.aspx

      Thanks again for the great post.

    21. Crows Programming » I’m Back - July 15, 2009

      [...] Hey guys, sorry I’ve been away for a bit. I’ll try and respond to your questions, especially those over on the C# dynamic web service page. [...]

    22. MaTZ - July 22, 2009

      Hi,
      I have a problem with http authentication.
      I managed to download WSDL by modifying BuildAssemblyFromWSDL like this:

      System.Net.WebClient client = new System.Net.WebClient();

      if (login.Length > 0)
      {
      client.Credentials = new NetworkCredential(login, password);
      }

      System.IO.Stream stream = client.OpenRead(webServiceUri.ToString() + “?wsdl”);

      XmlTextReader xmlreader = new XmlTextReader(stream);

      ServiceDescriptionImporter descriptionImporter = BuildServiceDescriptionImporter(xmlreader);

      return CompileAssembly(descriptionImporter);

      Now I’m getting exception (error 401) later when I try to invoke web method. Any ideas?

      Thanks for the post.

    23. facebook proxy - July 25, 2009

      Interesting article. Were did you got all the information from… :)

    24. proxies - July 25, 2009

      You are a very smart person! :)

    25. Andrew Brown - August 4, 2009

      Very useful post. I have been using this technique for over a year.

      I am having a problem where the web service request takes longer than 110 seconds to return a response. This causes a timeout error. I have been troubleshooting the timeout issue by changing all configurable timeout settings from the application setting (web.config) and IIS.

      [Error Details]
      System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.Net.WebException: The operation has timed out.

      I setup a simple test where the web server thread sleeps for 2 mins and 30 seconds.

      Please post if anyone has solved this.

    26. Donald Drake - August 5, 2009

      ““Method ‘Service1.Sum’ not found” ”

      I was able to fix this error by using the following instead.

      MethodInfo method = type.GetMethod(methodName);
      return (T) method.Invoke(instance, args);

      I believe the issue is due to the fact that it is using BindingFlags.InvokeMethod.. I was not able to use any other bindingflag with the type.InvokeMember method.

      Hope this helps.

      Thanks,
      Don

    27. Andrew Brown - August 5, 2009

      I found a solution to the Timeout issue. I had to set the Timeout property of the proxy instance.

      [CODE]
      PropertyInfo propInfo = obj.GetType().GetProperty(”Timeout”);
      propInfo.SetValue(obj, 300000 /* set this to whatever timeout period you want */, null);

      Then invoke the method.

    Posted by tornado
    |
    출처 : http://blogs.technet.com/kruc/archive/2009/06/02/oc-tab.aspx


    OC 대화창 옆에 TAB 붙이는 방법

    Context Windows in Communicator Using UCMA v2.0

    Office Communicator has a number of useful but mostly unknown features. One of these is its ability to display a custom context pane in a conversation window. The context pane shows up where the video goes in a video chat, and displays HTML content from any intranet or trusted URL.Conversation window with context pane

    The way to trigger this window is to send a SIP INFO message with a particular type of XML document to the conversation. All of the remote participants that receive the message will then get the context pane in Communicator if they are configured appropriately.

    Notice the catch: there are a couple of things that need to be configured on each client in order for the context pane to show up.

    First, a registry setting needs to be set to enable the context pane functionality in Communicator. To do this, open up regedit.exe and navigate to:

    HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Communicator

    You may have to create some of those folders if they don’t already exist. Just right-click on the level above it and select New Key.

    Once you’ve found the right key, create a DWORD (32-bit) value called EnableConversationWindowTabs, with a value of 1.

    Regedit with EnableConversationWindowTabs setting

    So much for registry settings. Next, if the URL you want to use for the content of your context window is not on your local intranet, you will need to add it to your trusted sites. You can do this through Internet Options in Internet Explorer.

    Internet Options Security tab in Internet ExplorerTrusted Sites in Internet Explorer

    Once everything is configured properly, you’ll be able to see the context window when your OCS endpoint receives a SIP INFO message with “call associated data” information.

    The code to send this message through UCMA v2.0 is actually quite simple. You will need the format of the XML document, as well as the content type; I like to keep these in constants so the code stays clean.

    Here is the text of the XML document. (The {0} in the XML block represents a unique ID for each context pane, and the {1} represents the URL of the content.)

    private const string CONTEXT_WINDOW_MESSAGE = "<associatedData xmlns=\"http://" + 
    "schemas.microsoft.com/LCS/2007/04/CallAssociatedData\" xmlns:xsi=\"http://" +
    "www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://" +
    "schemas.microsoft.com/LCS/2007/04/CallAssociatedData\">" +
    "<associatedDataElement id=\"{0}\" purpose=\"CWurl\">" +
    "<urlToHost>{1}</urlToHost><closeWithWindow>false</closeWithWindow>" +
    "</associatedDataElement></associatedData>";

    Here is the content type:

    private const string CONTEXT_WINDOW_CONTENT_TYPE = "application/ms-call-associated-data+xml";

    An integer instance variable will help keep track of the next unique ID in the sequence.

    private int _contextWindowId = 1;

    Before you can send the INFO message, you will already have had to set up a CollaborationPlatform, endpoint, conversation, and call. If you need help with the steps, you should be able to find detailed instructions in the UCMA v2.0 SDK documentation, or you can look at some of the samples that come packaged with the SDK.

    In order to send the INFO message, we need to call the BeginSendInfo method on an established call. The BeginSendInfo method takes a byte array for the content of the INFO message, so the next step is to encode the XML document as a byte array:

     byte[] bytes = Encoding.UTF8.GetBytes(string.Format(CONTEXT_WINDOW_MESSAGE, 
    _contextWindowId++, _url));

    Notice that I’m plugging the context window ID and the content URL into the XML document, and also incrementing the context window ID.

    Finally, we call BeginSendInfo on the Call object, passing in the content type, the byte array, and a callback delegate. If everything is set up correctly, the remote participant(s) in the call will see the context pane appear in their conversation windows.

    infoMessageCall.BeginSendInfo(
    new System.Net.Mime.ContentType(CONTEXT_WINDOW_CONTENT_TYPE), bytes, null,
    asyncResult => infoMessageCall.EndSendInfo(asyncResult), null
    );

    If a configuration problem is preventing the context window from working properly, you should see an error message in the conversation window that says “Could not display a form related to this conversation, which may prevent access to some options. If this problem persists, contact your system administrator.” If you are getting this message, check the registry setting again, and make sure that the URL you are using is a trusted site. You can also try looking at the properties of the SipResponseData object that is returned by the EndSendInfo method; this may give you a clue to the problem.

    Note that you are perfectly free to pass in a query string parameter in the URL you send. You can do some really cool contextual things by linking to server-side applications that display data dynamically based on the parameters passed in with the URL.

    Here is the complete code of my ContextWindowMessage class:

    /// <summary>

    /// Handles the sending of the INFO message that causes the extended window 
    /// to appear in Communicator.
    /// </summary>
    public class ContextWindowMessage {
     
        #region Constants
     
        private const string CONTEXT_WINDOW_MESSAGE = "<associatedData xmlns=\"http://" +
            "schemas.microsoft.com/LCS/2007/04/CallAssociatedData\" xmlns:xsi=\"http://" +
            "www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://" +
            "schemas.microsoft.com/LCS/2007/04/CallAssociatedData\">" +
            "<associatedDataElement id=\"{0}\" purpose=\"CWurl\">" +
            "<urlToHost>{1}</urlToHost><closeWithWindow>false</closeWithWindow>" +
            "</associatedDataElement></associatedData>";
        private const string CONTEXT_WINDOW_CONTENT_TYPE = 
            "application/ms-call-associated-data+xml";
     
        #endregion
     
        private int _contextWindowId = 1;
        private string _url = string.Empty;
     
        public ContextWindowMessage(string url) {
            if (string.IsNullOrEmpty(url)) {
                throw new ArgumentException("URL cannot be null.");
            }
     
            _url = url;
        }
     
        /// <summary>
        /// Sends the INFO message with the URL for the extended window.
        /// </summary>
        /// <param name="infoMessageCall">The call in which to send the INFO message.</param>
        public void SendToCall(Call infoMessageCall) {
     
            // We need to supply the INFO message as a byte array. The message itself is an 
            // XML document, whose format is in the CONTEXT_WINDOW_MESSAGE constant.
     
            byte[] bytes = Encoding.UTF8.GetBytes(string.Format(CONTEXT_WINDOW_MESSAGE, 
                _contextWindowId++, _url));
     
            // To send the INFO message, we use the BeginSendInfo method on the Call 
            // (not the Flow). In order for the extended window to appear, the first
            // parameter (the content type) should be "application/ms-call-associated-data+xml".
     
            infoMessageCall.BeginSendInfo(
                new System.Net.Mime.ContentType(CONTEXT_WINDOW_CONTENT_TYPE), bytes, null, 
                asyncResult => infoMessageCall.EndSendInfo(asyncResult), null
            );
        }
    }
    Posted by tornado
    |

    AD 설치 PC --> Active Directory 사용자 및 컴퓨터 --> 도메인 선택
    --> Computers 선택 --> 원격 접근할 PC 선택 후 관리 선택 --> 로컬 사용자 및 그룹 --> 그룹 --> 허용할 도메인 User 추가.

    Posted by tornado
    |

    출처 : http://onlybible.tistory.com/entry/jquery-visual-하게-공부하기-ok



    http://visualjquery.com/ 



    Posted by tornado
    |
    출처 : http://onlybible.tistory.com/1202 


    tmpwatch 라는 명령


    1. 이런 파일이 있다.

    [root@testguk guk]# ll
    합계 424
    -rw-r--r-- 1 root root     10  9월 23 15:40 1.txt
    -rw-r--r-- 1 root root 357961  9월 18 17:31 1221626338-metabbs-0.11.tar.tar
    -rw------- 1 root root   1052  9월 17 02:41 anaconda-ks.cfg
    -rw-r--r-- 1 root root    104  9월 22 18:37 array_pop.php
    -rw-r--r-- 1 root root     82  9월 22 18:40 array_push.php
    -rw-r--r-- 1 root root    106  9월 23 14:19 array_shift.php
    -rw-r--r-- 1 root root    210  9월 23 14:33 array_unique.php
    -rw-r--r-- 1 root root     96  9월 23 14:23 array_unshift.php
    -rw-r--r-- 1 root root    344  9월 19 16:21 asort.php
    -rw-r--r-- 1 root root  13333  9월 17 02:41 install.log
    -rw-r--r-- 1 root root   2551  9월 17 02:41 install.log.syslog
    -rw-r--r-- 1 root root    148  9월 19 16:06 ksort.php
    -rw-r--r-- 1 root root     63  9월 22 18:32 rsort.php
    -rw-r--r-- 1 root root    200  9월 19 15:33 shuffle.php
    -rw-r--r-- 1 root root    298  9월 19 15:48 sort.php


    2. 24시간 이후로 접근이 없는 파일들 삭제

    [root@testguk guk]# tmpwatch --atime 24 ./
    [root@testguk guk]# ll
    합계 28
    -rw-r--r-- 1 root root  10  9월 23 15:40 1.txt
    -rw-r--r-- 1 root root 104  9월 22 18:37 array_pop.php
    -rw-r--r-- 1 root root  82  9월 22 18:40 array_push.php
    -rw-r--r-- 1 root root 106  9월 23 14:19 array_shift.php
    -rw-r--r-- 1 root root 210  9월 23 14:33 array_unique.php
    -rw-r--r-- 1 root root  96  9월 23 14:23 array_unshift.php
    -rw-r--r-- 1 root root  63  9월 22 18:32 rsort.php


    간단하네.
    Posted by tornado
    |
    출처 : http://meela.tistory.com/entry/Portsentry-%EC%84%A4%EC%A0%95%EB%B0%A9%EB%B2%95



    포트 스캔을 체크툴인 Portsentry 1.1를 설정하는 방법과 실제 테스트후 블러킹 하는 방법

    portsentry 란?
    portsentry는 실시간으로 이런 portscan을 탐지하고 대응하기 위해 만들어진 프로그램이며, Abacus Project의 일환으로 PSIONIC사에서 개발 배포하는 도구중 하나이다. portsentry는 정상적인 스캔과 비밀스캔 모두를 탐지한다. portsentry는 portscan을 탐지하기 위해 많은 옵션들을 가지고 있는데 아래의 방법들로 portscan에 반응한다. (자세한 내용은 README.install을 참고하세요.)

    portsentry 다운받기
    the Project Sentry Tools Summary Page 에서 1.2 버전을 다운받을 수 있다.
     Psionic Technologies 에서 개발되고 오픈소스로 공개된 프로그램인데
    Psionic Technologies 가 cisco에 acquire되면서 더이상의 서비스를 제공하지 않고있다.
    현재로서는 여기에서 마지막 업데이트 버전을 제공받을 수 있다.

    portsentry 설치하기
    [root@chtla kan]# tar xvfz portsentry-1.2.tar.gz

    [root@chtla portsentry-1.2]# make linux

    SYSTYPE=linux
    Making
    cc -O -Wall -DLINUX -DSUPPORT_STEALTH -o ./portsentry ./portsentry.c
    ./portsentry_io.c ./portsentry_util.c

    [root@chtla portsentry-1.2]# make install
    디폴트 디렉토리는 /usr/local/psionic/portsentry/portsentry 이다..

    [root@chtla portsentry-1.2]# cd /usr/local/psionic/portsentry/

    [root@chtla portsentry]# vi portsentry.conf
    수정할 내용은 portsentry가 점검할 대상 포트(port)에 대한 것으로서 필요한 점검포트들을 모두설정하거나 점검하지 않을 포트들을 빼버리면 된다. 크게 대상 포트는 TCP 포트와 UDP포트로 나위어져 있으며, 특히 Stealth 스캔에 대한 옵션에 대한 설정도 할수 있음을 유심히 보기 바란다.

    [root@chtla portsentry]# vi portsentry.ignore
    12.34.56.78 <== portsentry 에서 block 되지 않을 아이피를 적어준다..(즉 자신의 서버 아이피등..안전하다고 생각되는 아이피)

    [root@chtla portsentry]# vi /etc/rc.d/rc.local <== 부팅시 실행을 위해 추가..

    # Port Sentry Setting
    /usr/local/psionic/portsentry/portsentry -tcp
    /usr/local/psionic/portsentry/portsentry -udp
    /usr/local/psionic/portsentry/portsentry -stcp
    /usr/local/psionic/portsentry/portsentry -sudp
    /usr/local/psionic/portsentry/portsentry -atcp
    /usr/local/psionic/portsentry/portsentry -audp

    옵션들 설명

    -tcp - Basic port-bound TCP mode (기본 포트 제한 TCP 모드)
    PortSentry는 설정파일들을 확인하고 나서, 백그라운드에 있는 모든 TCP포트들을 묶을 것이다. 만약 여러분이 init 상태를 점검하길 원한다면, 단지 여러분은 메시지가 저장되어지는 local syslog 파일을 살펴보면 된다.
    -udp - Basic port-bound UDP mode (기본 포트 제한 UDP 모드)
    PortSentry는 설정파일들을 확인하고 나서, 백그라운드에 있는 모든 UDP포트들을 묶을 것이다. 만약 여러분이 init 상태를 점검하길 원한다면, 단지 여러분은 메시지가 저장되어지는 local syslog 파일을 살펴보면 된다. UDP/스텔스 스캔 경고가 적용된다. (README.stealth파일을 읽어보라.)

    -stcp - Stealth TCP scan detection mode (스텔스 TCP 스캔 탐지 모드)
    PortSentry는 호스트로 들어오는 모든 패킷들을 감시하기 위해서 raw 소켓을 사용할 것이다. 만약 호스트로 들어오는 패킷이 감시되고 있는 포트로 향한다면, PortSentry는 호스트를 방어하기 위해 작동할 것이다. 이 방법은 connect() 스캔과 SYN/half-open 스캔과 FIN 스캔을 탐지할 것이다.
    UDP/스텔스 스캔 경고가 적용된다. (README.stealth파일을 읽어보라.)

    -sudp - "Stealth" UDP scan detection mode (스텔스 UDP 스캔 탐지 모드)
    이것은 위의 TCP stealth mode와 작동방법은 동일하다. UDP 포트들을 나열하면, 그 포트들은 감시된다. 이것은 어떠한 소켓도 묶지 않으며, 실제 스텔스 스캔 탐지 모드가 아닌 중에도 거의 동일하게 동작한다.( 모든 UDP 패킷에 반응한다.)
    UDP/스텔스 스캔 경고가 적용된다. (README.stealth파일을 읽어보라.)

    -atcp - Advanced TCP stealth scan detection mode (advanced TCP 스텔스 스캔 탐지 모드)
    PortSentry는 ADVANCED_PORTS_TCP 옵션에 지정된 최상의 포트번호이하의 모든 열려진 포트에 대한 목록을 만들면서 시작하고, 이러한 포트들을 기초로 제외(exclusion)목록을 만들 것이다. 제외되지 않은( 예를 들어, [SMTP, HTTP, 등의] 열려진[listening] network daemon이 아닌, ) 영역내의 임의의 포트에 연결된 호스트들은 접속이 금지된다. 이것은 여러분이 반드시 알고 있어야 할 몇몇 아주 강력한 함축적 의미들을 가지고 있다.

    -audp - Advanced UDP stealth scan detection mode (advanced UDP 스탤스 스캔 탐지 모드)
    UDP 프로토콜을 사용한다는 점을 제외하고는 위와 같다. Advanced UDP stealth scan detection은 지원되지 않는 트래픽을 즉시 알 수 있기 때문에 강력하지만 부정확한 경보의 가능성이 높다.

    실행하기
    [root@chtla portsentry]# /usr/local/psionic/portsentry/portsentry -tcp
    [root@chtla portsentry]# /usr/local/psionic/portsentry/portsentry -udp
    [root@chtla portsentry]# /usr/local/psionic/portsentry/portsentry -stcp
    [root@chtla portsentry]# /usr/local/psionic/portsentry/portsentry -sudp
    [root@chtla portsentry]# /usr/local/psionic/portsentry/portsentry -atcp
    [root@chtla portsentry]# /usr/local/psionic/portsentry/portsentry -audp

    [root@chtla portsentry]# ps -ax|grep portsentry
    1084 ? S 0:00 /usr/local/psionic/portsentry/portsentry -tcp
    1086 ? S 0:00 /usr/local/psionic/portsentry/portsentry -udp
    1092 ? S 0:01 /usr/local/psionic/portsentry/portsentry -atcp
    1094 ? S 0:00 /usr/local/psionic/portsentry/portsentry -audp

    이처럼 실행을 되어 있는 것은 확인할수 있다..
    그런데-stcp와 -sudp가 실행이 되지 않을것이다.. 서버 두대에서 같은 방법으로 돌려 보았는데, 실행이 되지 않고 있다.. 별문제라 문제되지 않아 아직까지 크게 신경을 쓰고 있지는 않아, (혹 아시는 분은 제게 좀 알려주세요..^^) 그냥 방치에 두고 있었다..
    글을 쓰고면서 다시 기억이 났으니 우선을 그냥 넘어가기로 한다.. 큰 문제는 아니다.

    침입 ip blocking 시키기..
    우선 portsentry 는 디폴트로 tcp-wrapper 와 연동이 되어 정상적인 포트가 아닌 다른 포트로 스캔을 할지 자동으로 /etc/hosts.deny 에 기록을 하게 된다.

    그냥 사용을 해도 좋으나 iptables 가 설치 되어 있다면 이것과 연동을 하는 것이 더 낮을것이다.
    iptables와 연동을 하려면

    [root@chtla portsentry]# vi portsentry.conf

    #KILL_HOSTS_DENY="ALL: $TARGET$" <=== 이것을 주석처리 하구

    # iptables support for Linux <=== 끝부분에 있을것임
    KILL_ROUTE="/sbin/iptables -A INPUT -s $TARGET$ -j DROP" <=== 이것을 주석 처리를 풀어준다.

    iptables 의 기본 옵션으로 -I 로 되어 있을것이다.. 그대로 사용해도 사용이 없으나, iptables를 사용할 사용이라면 -A 를 쓰도록 하자.
    (-I 는 최상위로 올라가기에, 즉 최상우선적으로 적용을 시키는 옵션으로 개인적으로 iptables에 허가 ip를 등록시켜둔 상태라서 저는 이렇게 사용합니다..
    -A 를 쓰면 -I 으로 적용한것보다 밑에 있게 되어 보기가 편하거든요..)

    침입 테스트하기
    다른 컴퓨터나 해당 서버에 텔넷(보통 기본적으로 막혀 있음)이나 다른 포트에 접속을 해 보자..

    (다른 컴터에서)
    # telnet 12.34.56.78 23

    접속하면 별일없이 프럼프트 상에서 한참을 기다리고 있을것이다.(linux상에서).. 종료후 해당 서버의 /etc/hosts.deny (iptables 설정을 안했을 경우) 를 열어 보거나, iptables로 설정한 경우

    # iptables -L
    target prot opt source destination
    DROP all -- 61.xx.xx.196 anywhere <== 허가 거부된 ip

    이와 같이 거부된 것을 볼수 있을것이다..

    참조할만한 사이트

    http://www.certcc.or.kr/tools/Psionic_Portsentry.html
    http://list.kldp.org/pipermail/tip/2001Sep/0292.html

    Posted by tornado
    |
    출처 : http://www.ibm.com/developerworks/kr/library/x-ajaxjquery.html


    jQuery로 Ajax 개발을 단순화 하기

    Ajax와 DOM 스크립팅을 쉽게 하는 방법

    developerWorks
    문서 옵션
    수평출력으로 설정

    이 페이지 출력

    이 페이지를 이메일로 보내기

    이 페이지를 이메일로 보내기

    영어원문

    영어원문

    
    제안 및 의견
    피드백

    난이도 : 중급

    Jesse Skinner, Web Developer, Freelance

    2007 년 9 월 04 일

    jQuery는 JavaScript 라이브러리로서 JavaScript™와 Asynchronous JavaScript + XML (Ajax) 프로그래밍을 단순화 하는데 도움이 됩니다. JavaScript 라이브러리와는 달리, jQuery는 복잡한 코드를 간결하게 표현할 수 있는 독특한 철학이 있습니다. jQuery 원리, 기능과 특징을 배우고, 일반적인 Ajax 태스크도 수행하며, 플러그인으로 jQuery를 확장하는 방법도 알아봅니다.

    jQuery란 무엇인가?

    2006년 초, John Resig가 만든 jQuery는 JavaScript 코드로 작업하는 사람들에게는 훌륭한 라이브러리이다. 여러분이 JavaScript 언어 초보자라서 라이브러리가 Document Object Model (DOM) 스크립팅과 Ajax의 복잡성을 다루어주기를 원하든지, 숙련된 JavaScript 구루로서 DOM 스크립팅과 Ajax의 반복성에 지루해졌다면, jQuery가 제격이다.

    jQuery는 코드를 단순하고 간결하게 유지한다. 많은 반복 루프와 DOM 스크립팅 라이브러리 호출을 작성할 필요가 없다. jQuery를 사용하면 매우 적은 문자로 표현할 수 있다.

    jQuery 철학은 매우 독특하다. 무엇이든 단순하고 재사용 가능한 것으로 유지하기 위해 디자인 되었다. 여러분이 이러한 철학을 이해하고 여기에 편안함을 느낀다면, jQuery가 여러분의 프로그래밍 방식을 충분히 향상시킬 수 있다.




    위로


    단순화

    다음은 jQuery가 여러분의 코드에 어떤 영향을 미치는지를 보여주는 예제이다. 페이지의 모든 링크에 클릭 이벤트를 붙이는 것 같이 단순하고 일반적인 것을 수행하려면, 플레인 JavaScript 코드와 DOM 스크립팅을 사용하는 것이 낫다. (Listing 1)


    Listing 1. jQuery 없는 DOM 스크립팅
                    
    var external_links = document.getElementById('external_links');
    var links = external_links.getElementsByTagName('a');
    for (var i=0;i < links.length;i++) {
        var link = links.item(i);
        link.onclick = function() {
            return confirm('You are going to visit: ' + this.href);
        };
    }
    

    Listing 2는 같은 기능에 jQuery를 사용한 모습이다.


    Listing 2. jQuery를 사용한 DOM 스크립팅
                    
    $('#external_links a').click(function() {
        return confirm('You are going to visit: ' + this.href);
    });
    

    놀랍지 않은가? jQuery를 사용하면 복잡하지 않게 코드로 표현하고자 하는 것만 나타낼 수 있다. 엘리먼트를 반복할 필요가 없다. click() 함수가 이 모든 것을 관리한다. 또한, 다중 DOM 스크립팅 호출도 필요 없다. 여기에서 필요한 것은 엘리먼트가 어떻게 작동하는지를 설명하는 짧은 스트링이다.

    이 코드로 어떻게 작업이 수행되는지를 이해하기는 조금 어렵다. 우선, $() 함수가 있어야 한다. 이것은 jQuery에서 가장 강력한 함수이다. 대게, 이 함수를 사용하여 문서에서 엘리먼트를 선택한다. 이 예제에서, 이 함수는 Cascading Style Sheets (CSS) 신택스를 포함하고 있는 스트링으로 전달되고, jQuery는 효율적으로 이 엘리먼트를 찾는다.

    CSS 셀렉터의 기본을 이해하고 있다면, 이 신택스가 익숙할 것이다. Listing 2에서, #external_linksexternal_linksid를 가진 엘리먼트를 찾는다. a 앞에 있는 공간은 jQuery에게 external_links 엘리먼트 내의 모든 <a> 엘리먼트를 찾도록 명령한다. 영어와 DOM은 장황하지만, CSS에서는 매우 간단하다.

    $() 함수는 CSS 셀렉터와 매치하는 모든 엘리먼트를 포함하고 있는 jQuery 객체를 리턴한다. jQuery 객체는 어레이와 비슷하지만, 수 많은 특별한 jQuery 함수들이 포함된다. 예를 들어, click 함수를 호출함으로써 클릭 핸들러 함수를 jQuery 객체의 각 엘리먼트에 할당할 수 있다.

    또한, 엘리먼트나 엘리먼트의 어레이를 $() 함수로 전달하면, 이것은 엘리먼트 주위에 jQuery 객체를 래핑할 것이다. 이 기능을 사용하여 window 객체 같은 것에 jQuery 함수를 적용하고 싶을 것이다. 일반적으로 이 함수를 다음과 같이 로드 이벤트에 할당한다.

    window.onload = function() {
        // do this stuff when the page is done loading
    };
    

    jQuery를 사용하면, 같은 코드도 다음과 같이 된다.

    $(window).load(function() {
        // run this when the whole page has been downloaded
    });
    

    이미 알고 있었겠지만, 윈도우가 로딩하기를 기다리는 일은 매우 지루한 일이다. 전체 페이지가 로딩을 끝마쳐야 하기 때문이다. 여기에는 페이지의 모든 이미지들도 포함된다. 가끔, 이미지 로딩을 먼저 끝내고 싶지만, 대부분의 경우 Hypertext Markup Language (HTML)만 로딩해야 한다. jQuery는 문서에 특별한 ready 이벤트를 만듦으로써 이 문제를 해결한다.

    $(document).ready(function() {
        // do this stuff when the HTML is all ready
    });
    

    이 코드는 document 엘리먼트 주위에 jQuery 객체를 만들고, HTML DOM 문서가 준비될 때 함수를 설정하여 인스턴스를 호출한다. 이 함수를 필요한 만큼 호출할 수 있다. 진정한 jQuery 스타일에서, 지름길은 이 함수를 호출하는 것이다. 함수를 $() 함수로 전달한다.

    $(function() {
        // run this when the HTML is done downloading
    });
    

    지금까지, $() 함수를 사용하는 세 가지 방법을 설명했다. 네 번째 방법은, 스트링을 사용하여 엘리먼트를 만드는 것이다. 결과는, 그 엘리먼트를 포함하고 있는 jQuery 객체가 된다. Listing 3은 문단을 페이지에 추가하는 예제이다.


    Listing 3. 간단한 문단을 생성하여 붙이기
                    
    $('<p></p>')
        .html('Hey World!')
        .css('background', 'yellow')
        .appendTo("body");
    

    이전 예제에서 파악했겠지만, jQuery의 또 다른 강력한 기능은 메소드 체인(method chaining.)이다. jQuery 객체에 대해 메소드를 호출할 때마다, 이 메소드는 같은 jQuery 객체를 리턴한다. jQuery 객체에 다중 메소드를 호출하고 싶다면 셀렉터를 다시 입력하지 않고 이를 수행할 수 있다.

    $('#message').css('background', 'yellow').html('Hello!').show();
    




    위로


    Ajax로 단순하게!

    Ajax는 jQuery를 사용하면 더 단순해 질 수 있다. jQuery에는 쉬운 것도 쉽게 복잡한 것도 가능한 단순하게 만드는 유용한 함수들이 많이 있다.

    Ajax에서 사용되는 방식은 HTML 청크를 페이지 영역에 로딩하는 것이다. 여러분이 필요로 하는 엘리먼트를 선택하고 load() 함수를 사용하는 것이다. 다음은 통계를 업데이트 하는 예제이다.

    $('#stats').load('stats.html');
    

    일부 매개변수들을 서버 상의 페이지로 전달해야 할 경우가 종종 있다. jQuery를 사용하면 이는 매우 간단하다. 필요한 메소드가 어떤 것인지에 따라서 $.post()$.get() 중 선택한다. 선택적 데이터 객체와 콜백 함수를 전달할 수도 있다. Listing 4는 데이터를 보내고 콜백을 사용하는 예제이다.


    Listing 4. Ajax를 사용하여 데이터를 페이지로 보내기
                    
    $.post('save.cgi', {
        text: 'my string',
        number: 23
    }, function() {
        alert('Your data has been saved.');
    });
    

    복잡한 Ajax 스크립팅을 해야 한다면, $.ajax() 함수가 필요하다. xml, html, script, json을 지정할 수 있고, 여러분이 바로 사용할 수 있도록 jQuery가 자동으로 콜백 함수에 대한 결과를 준비한다. 또한, beforeSend, error, success, complete 콜백을 지정하여 사용자에게 Ajax에 대한 더 많은 피드백을 제공할 수 있다. 게다가, Ajax 요청의 타임아웃이나 페이지의 "최종 변경" 상태를 설정하는 매개변수들도 있다. Listing 5는 필자가 언급했던 매개변수를 사용하여 XML 문서를 검색하는 예제이다.


    Listing 5. $.ajax()를 사용하여 복잡한 Ajax를 단순하게
                    
    $.ajax({
        url: 'document.xml',
        type: 'GET',
        dataType: 'xml',
        timeout: 1000,
        error: function(){
            alert('Error loading XML document');
        },
        success: function(xml){
            // do something with xml
        }
    });
    

    콜백 성공으로 XML을 받으면, jQuery를 사용하여 HTML에서 했던 것과 같은 방식으로 XML을 볼 수 있다. 이는 XML 문서 작업을 쉽게 하며 콘텐트와 데이터를 웹 사이트로 쉽게 통합시킨다. Listing 6은 리스트 아이템을 XML의 <item> 엘리먼트용 웹 페이지에 추가하는 success 함수에 대한 확장 모습이다.


    Listing 6. jQuery를 사용하여 XML 작업하기
                    
    success: function(xml){
        $(xml).find('item').each(function(){
            var item_text = $(this).text();
    
            $('<li></li>')
                .html(item_text)
                .appendTo('ol');
        });
    }
    




    위로


    HTML 애니메이션

    jQuery를 사용하여 기본적인 애니메이션과 효과를 다룰 수 있다. 애니메이션 코드의 중심에는 animate() 함수가 있는데, 이는 숫자로 된 CSS 스타일 값을 바꾼다. 예를 들어, 높이, 넓이, 폭, 위치를 움직일 수 있다. 또한, 애니메이션의 속도를 밀리초 또는 사전 정의된 속도(느림, 보통, 빠름)로 지정할 수 있다.

    다음은, 엘리먼트의 높이와 넓이를 동시에 움직이게 하는 예제이다. 시작 값은 없고 종료 값만 있다. 시작 값은 엘리먼트의 현재 크기에서 가져온다. 여기에도 콜백 함수를 첨부했다.

    $('#grow').animate({ height: 500, width: 500 }, "slow", function(){
        alert('The element is done growing!');
    });
    

    jQuery는 빌트인 함수를 사용하여 일반적인 애니메이션도 더욱 쉽게 만든다. show()hide() 엘리먼트를 즉각적으로 또는 지정된 속도로 사용할 수 있다. fadeIn()fadeOut() 또는 slideDown()slideUp()을 사용하여 엘리먼트를 나타나게 하거나 사라지게 할 수 있다. 다음은 네비게이션의 slidedown 예제이다.

    $('#nav').slideDown('slow');
    




    위로


    DOM 스크립팅과 이벤트 핸들링

    jQuery는 DOM 스크립팅과 이벤트 핸들링을 단순화하는데 제격이다. DOM의 트래버스와 조작이 쉽고, 이벤트의 첨부, 제거, 호출은 매우 자연스러운 일이며, 직접 수행하는 것보다 에러도 적게 발생한다.

    기본적으로 jQuery는 DOM 스크립팅으로 수행하는 일들을 더욱 쉽게 수행할 수 있도록 해준다. 엘리먼트를 생성하고 append() 함수를 사용하여 이들을 다른 엘리먼트로 연결할 수 있고, clone()을 사용하여 엘리먼트를 중복시키고, 콘텐트를 html()로 설정하고, empty() 함수로 콘텐트를 삭제하고, remove() 함수로 엘리먼트를 삭제하고, wrap() 함수를 사용하여 또 다른 엘리먼트로 엘리먼트를 래핑한다.

    DOM을 트래버스 함으로써 jQuery 객체의 콘텐트를 변경할 때 여러 함수들을 사용할 수 있다. 엘리먼트의 siblings(), parents(), children()을 사용할 수 있다. 또한, next() 또는 prev() sibling 엘리먼트도 선택할 수 있다. 아마도 가장 강력한 것은 find() 함수일 것이다. jQuery 셀렉터를 사용하여 jQuery 객체의 엘리먼트 종속 관계들을 통해 검색할 수 있다.

    이 함수는 end() 함수와 사용될 때 더욱 강력해진다. 이 함수는 실행 취소 함수와 비슷하고, find() 또는 parents() 또는 다른 트래버싱 함수들을 호출하기 전에 가졌던 jQuery 객체로 돌아간다.

    메소드 체인과 함께 사용되면, 복잡한 연산도 단순하게 보이게 할 수 있다. Listing 7은 로그인 폼을 찾고 이와 관련한 여러 엘리먼트를 조작하는 예제이다.


    Listing 7. DOM의 트래버스와 조작
                    
    $('form#login')
        // hide all the labels inside the form with the 'optional' class
        .find('label.optional').hide().end()
    
        // add a red border to any password fields in the form
        .find('input:password').css('border', '1px solid red').end()
    
        // add a submit handler to the form
        .submit(function(){
            return confirm('Are you sure you want to submit?');
        });
    

    믿을 수 있는지 모르겠지만, 이 예제는, 공백을 사용한 하나의 연결된 코드 라인일 뿐이다. 우선, 로그인 폼을 선택했다. 그리고 나서, 이 안에 선택 레이블을 찾고, 이들을 숨긴 다음, end()를 호출하여 폼으로 돌아가게 하였다. 패스워드 필드를 찾았고, 보더를 빨간색으로 한 다음, 다시 end()를 호출하여 폼으로 돌아갔다. 마지막으로, 제출 이벤트 핸들러를 폼에 추가했다. 여기에서 특히 재미있는 부분은 jQuery가 모든 쿼리 연산들을 최적화 하기 때문에, 여러분은 모든 것이 서로 잘 연결될 때 엘리먼트를 두 번 찾을 필요가 없다.

    공통 이벤트 핸들링은 click(), submit(), mouseover() 같은 함수를 호출하고 여기에 이벤트 핸들러 함수를 전달하는 것만큼 단순하다. 게다가, bind('eventname', function(){})을 사용하여 커스텀 이벤트 핸들러를 할당하는 옵션도 있다. unbind('eventname')를 사용하여 특정 이벤트를 제거하거나, unbind()를 사용하여 모든 이벤트를 제거할 수 있다. 이것과 기타 함수들을 사용하는 다른 방법들은, jQuery 애플리케이션 프로그램 인터페이스(API) 문서를 참조하라. (참고자료)




    위로


    jQuery 셀렉터의 힘 활용하기

    #myid 같은 아이디 또는 div.myclass 같은 클래스 이름으로 엘리먼트를 선택한다. 하지만, jQuery는 하나의 셀렉터에서 거의 모든 엘리먼트 조합을 선택할 수 있도록 하는 복잡하고도 완벽한 셀렉터 신택스를 갖고 있다.

    jQuery의 셀렉터 신택스는 CSS3과 XPath에 기반하고 있다. CSS3과 XPath 신택스를 더욱 잘 안다면, jQuery 사용이 더욱 수월해진다. CSS와 XPath를 포함하여 jQuery 셀렉터의 전체 리스트를 보려면 참고자료 섹션을 참조하라.

    CSS3에는 모든 브라우저가 지원하지 않는 신택스가 포함되어 있기 때문에, 이를 자주 볼 수 없다. 하지만, jQuery에서 CSS3을 사용하여 엘리먼트를 선택한다. jQuery는 고유의 커스텀 셀렉터 엔진을 갖고 있다. 예를 들어, 테이블의 모든 빈 컬럼 안에 대시(dash)를 추가하려면, :empty pseudo-selector를 사용한다.

    $('td:empty').html('-');
    

    특정 클래스를 갖고 있지 않은 모든 엘리먼트를 찾는다면? CSS3은 이를 위한 신택스도 있다. :not pseudo-selector를 사용하는 것이다. 다음은 required의 클래스를 갖고 있지 않은 모든 인풋을 숨기는 방법이다.

    $('input:not(.required)').hide();
    

    또한, CSS에서처럼 다중 셀렉터를 콤마를 사용하여 하나로 연결시킬 수 있다. 다음은 이 페이지에서 모든 리스트 유형들을 동시에 숨기는 예제이다.

    $('ul, ol, dl').hide();
    

    XPath는 하나의 문서에서 엘리먼트를 찾는 강력한 신택스이다. CSS와는 다르며, CSS로 수행할 수 없는 몇 가지 일을 수행할 수 있다. 보더를 모든 체크 박스의 부모 엘리먼트에 추가하려면, XPath의 /.. 신택스를 사용할 수 있다.

    $("input:checkbox/..").css('border', '1px solid #777');
    

    가독성 있는 테이블을 만들려면, 다른 클래스 이름을 테이블의 모든 짝수 또는 홀수 행에 붙인다. 이를 다른 말로 테이블의 스트라이핑(striping)이라고 한다. jQuery를 사용하면 :odd pseudo-selector 덕택에 쉽게 수행할 수 있다. 아래 예제는 테이블의 모든 홀수 행의 백그라운드를 striped 클래스를 사용하여 변경한다.

    $('table.striped > tr:odd').css('background', '#999999');
    

    jQuery 셀렉터로 코드를 어느 정도 단순화 할 수 있는지를 보았다. 어떤 엘리먼트를 선택하든지 간에, 하나의 jQuery 셀렉터를 사용하여 이를 정의하는 방법도 찾을 수 있다.




    위로


    플러그인으로 jQuery 확장하기

    대부분의 소프트웨어와는 달리, jQuery용 플러그인 작성은 복잡한 API를 사용해야 하는 힘든 일이 아니다. 사실, jQuery 플러그인은 작성하기가 쉬워서 몇 가지만 작성하면 코드를 더욱 단순하게 유지할 수 있다. 다음은 여러분이 작성할 수 있는 가장 기본적인 jQuery 플러그인이다.

    $.fn.donothing = function(){
        return this;
    };
    

    단순하지만, 이 플러그인은 약간의 설명이 필요하다. 우선, 함수를 모든 jQuery 객체에 추가하려면, 여기에 $.fn을 할당하고, 이 함수는 this (jQuery 객체)를 리턴하여 이것이 메소드 체인을 깨트리지 않도록 해야 한다.

    이 예제를 기반으로 쉽게 구현할 수 있다. css('background')를 사용하는 대신 플러그인을 작성하여 백그라운드를 바꾸려면, 다음을 사용한다.

    $.fn.background = function(bg){
        return this.css('background', bg);
    };
    

    css()에서 값을 리턴할 뿐이다. 이것은 이미 jQuery 객체를 리턴하기 때문이다. 따라서, 메소드 체인은 여전이 잘 작동한다.

    여러분은 반복 작업이 있을 경우에 jQuery 플러그인을 사용하기 바란다. 예를 들어, 같은 일을 여러 번 수행하기 위해 each() 함수를 사용하고 있다면 플러그인을 사용해도 된다.

    jQuery 플러그인을 작성이 쉽기 때문에, 여러분이 사용할 수 있는 것도 수백 가지나 존재한다. jQuery는 탭, 곡선형 코너, 슬라이드 쇼, 툴 팁, 날짜 셀렉터, 기타 여러분이 상상하고 있는 모든 것을 위한 플러그인이 있다. 플러그인 리스트는 참고자료 섹션을 참조하기 바란다.

    가장 복잡하고 광범위하게 사용되는 플러그인은 Interface이다. 이것은 정렬, 드래그&드롭 기능, 복합 효과, 기타 복잡한 사용자 인터페이스(UI)를 핸들하는 애니메이션 플러그인이다. Interface가 jQuery를 위한 것이라면 Prototype에는 Scriptaculous가 있다.

    또한 Form 플러그인도 대중적이고 유용하다. 이것으로 Ajax를 사용하여 백그라운드에서 폼을 쉽게 제출할 수 있다. 이 플러그인은 폼의 제출 이벤트를 하이재킹 하고, 다른 인풋 필드를 찾고, 이들을 사용하여 Ajax 호출을 구현하는 상황에 사용된다.




    위로


    jQuery 이후의 삶

    jQuery를 사용하여 할 수 있는 것의 표면적인 부분만 다루었다. jQuery는 기분 좋게 사용할 수 있고 새로운 트릭이나 기능도 자연스럽다. jQuery는 JavaScript와 Ajax 프로그래밍을 매우 단순화 시킬 수 있다. 새로운 것을 배울 때마다 코드는 더욱 단순해 진다.

    jQuery를 배운 후에, 필자는 JavaScript 언어로 하는 프로그래밍에 재미를 발견했다. 지루한 부분은 알아서 처리되기 때문에, 필자는 중요한 코딩 부분에만 집중하면 된다. jQuery를 사용하게 되면서 지난날 for 루프를 작성하던 때는 거의 기억이 나지 않는다. 심지어, 다른 JavaScript 라이브러리를 사용할 생각도 거의 하지 않는다. jQuery는 JavaScript 프로그래밍 방식을 진정으로 바꿔 놓았다.



    참고자료

    교육

    제품 및 기술 얻기

    토론


    필자소개

    Photo of Jesse Skinner

    Jesse Skinner는 JavaScript와 CSS 전문 프리랜스 웹 개발자이다. 캐나다와 독일이 주 활동 무대이며, CSS 브라우저 호환성 미스터리를 풀고 있다. Jesse에 대해 더욱 알고 싶거나 웹 개발에 대한 글을 더 읽고 싶다면, 블로그 The Future of the Web를 방문해 보라.



    Posted by tornado
    |
    출처 : http://www.ibm.com/developerworks/kr/library/wa-jquery3/



    jQuery로 작업하기, 3부: jQuery와 Ajax로 RIA 만들기: JQuery: 내일 나올 웹 응용을 오늘 구현해보자

    Effects 모듈과 Ajax

    developerWorks
    문서 옵션
    수평출력으로 설정

    이 페이지 출력

    이 페이지를 이메일로 보내기

    이 페이지를 이메일로 보내기

    샘플 코드

    영어원문

    영어원문

    
    제안 및 의견
    피드백

    난이도 : 중급

    Michael Abernethy, 제품 개발 관리자, Optimal Auctions

    옮긴이 : 박재호 이해영 dwkorea@kr.ibm.com

    원문 게재일 : 2008 년 10 월 28 일
    번역 게재일 : 2009 년 1 월 13 일

    JQuery는 동적 RIA를 쉽게 개발하는 방법에 목마른 개발자를 위한 자비스크립트 라이브러리로 각광을 받고 있습니다. 브라우저 기반 응용이 데스크톱 응용을 계속 대체하고 있기에, 이런 라이브러리 활용 역시 꾸준히 증가 추세에 있습니다. jQuery 연재물에서 jQuery로 웹 응용 프로젝트를 구현하는 방법을 살펴봅시다.

    도입

    jQuery는 지난 몇 개월 동안에 웹 개발자를 위한 유력한 자바스크립트 라이브러리로 급속도로 세를 넓혀가고 있다. 이런 현상은 브라우저 기반 응용으로 데스크톱 응용을 교체하기 위한 RIA(Rich Internet Application) 활용과 필요성이 급격하게 늘어나는 상황과 맞물려 돌아간다. 스프레드시트부터 급여 계산에서 전자편지 응용에 이르기까지 브라우저로 데스크톱 응용을 교체해 나가는 현실이다. 이런 응용 개수가 많아지고 복잡해지면서 자바스크립트 라이브러리는 응용을 만드는 튼튼한 기초로 더욱 더 중요성이 높아질 것이다. jQuery는 개발자를 위한 필수 라이브러리가 되었다. 이 연재물에서는 jQuery를 깊숙하게 탐험하며, 개발자가 RIA를 빠르고 쉽게 만들기 위한 튼튼한 토대를 제공한다.

    직전 기사에서 RIA를 만드는 세 가지 기본 구성 요소와 페이지에 상호 작용을 추가하는 방법을 배웠다. 첫 번째로 살펴본 Event 모듈은 페이지에서 사용자가 일으킨 사건을 잡아서 프로그램 상에서 반응하도록 만들었다. 이런 기능을 사용해 버튼 누르기, 마우스 이동과 같은 사용자 행동 처리용 코드를 붙인다. 다음으로 살펴본 Attributes 모듈은 페이지 엘리먼트에서 값을 얻고 엘리먼트에 값을 설정하는 방법과 변수값을 포함한 자료 객체로 취급하는 방법을 설명했다. 이런 변수값은 사용자에게 어떤 반응을 보일지 결정하는 과정에 필요한 정보 대다수를 포함한다. 마지막으로 CSS 조작 방법을 살펴보고 페이지를 다시 읽어들이지 않고서도 배치, 색상, 글꼴 등을 변경하는 방법을 익혔다. 이런 세 가지 모듈에 익숙해지면, 상호대화식 웹 페이지를 구성하는 세 가지 기초 구성 요소를 익힌 셈이다. 사용자 반응을 잡아(Event), 정보를 획득하고(Attributes), 사건과 정보를 조합한 내용을 토대로 피드백을 제공한다(CSS).

    이 기사에서 동적인 웹 페이지를 구성하는 세 가지 기본 요소를 사용한다. 이런 요소는 오늘날 볼 수 있는 좀 더 첨단 웹 응용의 일부로 자리잡은 "화끈한" 효과와 기능을 제공한다. 추가 모듈이 RIA에 핵심은 아니지만, 사용자가 기억할 만한 추가 기능을 제공하며 RIA에서 사용 가능한 범위와 기능을 엄청나게 넓혀준다. 살펴볼 첫 모듈은 Effects 모듈로 엘리먼트 감추기, 엘리먼트 이동, 페이드 인/아웃과 같은 기능을 포함한다. 다시 말해 웹 페이지를 화끈하게 만드는 기능이다. 이 기사에서 설명하는 마지막 모듈은 비동기식 자바스크립트 + XML(Ajax) 모듈이다. Ajax는 RIA 하면 가장 먼저 떠오르는 단어다. Ajax는 웹 응용에 서버와 통신하는 능력을 부여해 페이지를 다시 읽어들이지 않고서도 정보를 전달하고 인출하는 기능을 제공한다(웹에 떠도는 잘못된 의견과는 달리 AJax는 단순히 멋진 자바스크립트 애니메이션 기능은 아니다). jQuery가 믿기 어려울 정도로 손쉬운 AJax 도구를 제공하며, 실제로 Ajax 사용을 자바스크립트 메서드 호출 수준으로 단순하게 만들어준다.

    이 기사에서 소개하는 예제 응용은 Effects와 Ajax 모듈을 데모 웹 응용인 웹 메일로 집어넣는 방법을 보여주면서 끝을 맺는다. 몇 가지 Effects를 데모에 추가해 활력을 불어넣고, 더욱 중요하게 몇 가지 Ajax 코드를 추가해 웹 메일이 페이지를 다시 읽지 않고서도 메시지를 출력하도록 만든다.

    Effects

    Effects 모듈은 이름처럼 "심각한" 웹 페이지가 회피해야 하는 애니메이션과 특수 효과만 포함한다고 지레짐작하기 쉽다. 하지만 이런 기능으로 끝나지 않는다. 거의 모든 응용에서 특정 페이지 엘리먼트를 가리거나 다른 페이지 엘리먼트 상태에 맞춰 끄고 켤 필요가 있다. 이런 변화 유형이 RIA에 중요한 이유는 페이지를 한 번만 읽으면서 모든 페이지 엘리먼트를 가져온 다음에 특정 엘리먼트를 표시하고 가리는 방식으로 필요한 정보만 보여주기 때문이다. 페이지를 다시 읽는 대안은 좋은 해법이 아니다. div를 감추고 보여주는 두 가지 선택이 가능한 콤보 박스를 생각해보자. 명백히 콤보 박스가 바뀔 때마다 div를 감추고 보여주려고 페이지를 다시 읽어들이는 것보다 클라이언트 쪽 코드에서 단순히 div를 감추고 보여주는 방식이 훨씬 더 쉽고 효율적이다. 단순히 감추고 보여주느냐 페이드 인/아웃 효과를 주느냐는 설계자 마음이다.

    위에서 언급한 바와 같이 가장 기초적인 효과는 show()hide() 함수다. 두 함수는 아주 직관적이며, 척 보면 알겠지만 페이지에 있는 특정 엘리먼트를 보여주고 감춘다.


    Listing 1. show()와 hide() 함수
    				
    // 페이지에 나오는 모든 <p>를 보여준다.
    $("p").show();
    
    // 페이지에 나오는 모든 <p>를 감춘다.
    $("p").hide();
    
    // 페이지에 나오는 모든 <p:odd>를 감춘다.
    $("p:odd").hide();

    이런 기본적인 기능 이외에, show()hide() 함수는 보여주고 감추는 동작 방식을 좀 더 세부적으로 제어하는 기능도 제공한다. 문서에 따르면 "우아한" 보여주기/감추기 기능은 show()를 페이드 인과 슬라이딩 아웃 조합으로 해석한다.

    몇 가지 예제를 살펴보기 앞서, 잠시 한 걸음 물러서서 Effects 함수에 인수를 전달하는 방법을 살펴보자. (일반적인 show()hide() 함수는 예외지만) 함수마다 효과를 완료하고 나서 부르는 함수와 얼마나 빠르거나 느리게 효과를 보여줄지 제어하는 속력을 전달할 수 있다. 속력 인수로 "slow", "fast", "normal"이라는 문자열 중 하나를 지정한다. 추가로 애니메이션 주기를 정확하게 제어할 필요가 있다면 인수로 밀리 초 단위의 숫자를 넘긴다. Effects 함수로 넘기는 두 번째 인수는 함수이며, 효과를 끝내고 나서 호출되는 함수다. 이렇게 하는 이유는 여러 효과를 좀 더 큰 효과 하나로 결합할 때 특정 효과가 끝나고 나서 다음 효과를 지시하는 안정적인 제어 방법을 제공하기 때문이다.


    Listing 2. 복잡한 효과
    				
    // "picture"라는 ID를 지정한 img는 감춰진 상태로 시작한다.
    // "showPicture" 버튼이 눌러졌을 때 "picture"라는 ID를 지정한 img를 보여주고
    // 애니메이션을 한다. 따라서 잽싸게 페이드인과 슬라이드 아웃을 보여준 다음에
    // 쇼가 끝나면 그림에 달린 캡션을 보여준다.
    // 캡션은 항상 <img> 태그 오른쪽으로 펼쳐진다.
    
    <input type="button" id="showPicture">
    
    <img src="/pic.jpg" id="picture"><span>This is the picture's caption</span>
    
    // document.ready() 함수 내부에 들어갈 jQuery 코드
    
    $("#picture").hide().next().hide();
    $("#showPicture").click(function(){
       $("#picture").show("fast", function(){
           $("#picture").next().show();
       });
    });
    
    // 실제 프로그램 코드보다 설명이 더 길어졌음에 주목하자!

    Effects 모듈은 show()hide()와 아주 비슷해서 궁극적으로 똑같은 작업을 수행하는 다른 함수를 지원한다. 여기서는 아주 구체적인 동작을 수행하게 만드는 함수 군을 소개하겠다. slideDown()slideUp() 함수는 페이지 엘리먼트를 보여주고 감추는 함수다. 하지만 슬라이딩 다운/업으로 엘리먼트에 애니메이션 효과를 준다(작명에 아주 머리가 파았을 테다!). 조금 전에 설명한 개선된 hide()show() 함수처럼, 슬라이드 속력과 작업이 끝나면 호출될 함수를 제어할 수 있다. 한걸음 더 나가서 여기에는 페이지 엘리먼트를 보여주고/감추기 위한 다른 옵션도 있다. fadeIn()fadeOut() 함수는 이름이 의미하듯이 페이지 엘리먼트를 투명해질 때까지 페이드 효과를 줘서 최종적으로 사라지게 만든다. 이 옵션에도 속력과 작업이 끝나면 호출될 함수를 지정할 수 있다.

    페이지 엘리먼트를 완전히 감추거나 보여주지 않는 흥미로운 함수가 하나 더 있다. fadeTo()라는 함수는 페이지 엘리먼트를 일부 투명하게 만든다. RIA에서 이런 기능이 아주 중요한 이유는 투명도는 특정 엘리먼트를 페이지에서 강조하는 훌륭한 수단이며, 페이지에서 비활성 영역을 보여주는 데 사용할 수 있기 때문이다. 예를 들어, 페이지에 여러 탭이 있는 상황에서 다른 탭이 선택하지 못한다는 사실을 강조하려고 나머지 탭에 투명도를 적용할 수 있다. 아니면 페이지 폼에서, 현재 초점이 어떤 Form 엘리먼트에 맞춰져 있는지 사용자에게 알려주고 싶을 때도 초점이 없는 모든 엘리먼트에 투명도를 가하면 구분이 가능하다. 또한 투명도 자체 효과만 해도 정말 멋지다. 뭔가를 디자인할 때 "애플이 하면 진짜 멋지다"라는 일반적인 후광 효과를 따르면 된다.


    Listing 3. 멋진 효과를 추가하기 위해 fadeTo() 활용하기
    				
    // 페이지에 있는 모든 form 엘리먼트에 60%라는 투명도를 준다.
    // 현재 초점이 있는 엘리먼트는 투명도 효과에서 제외한다.
    // 애플처럼 보이지 않는가?
    
    $(":input").fadeTo("fast", .60);
    $(":input").focus(function(){
        $(this).fadeTo("fast", 1);
    });
    $(":input").blur(function(){
        $(this).fadeTo("fast, .60);
        });

    Effects 모듈에서 소개하고픈 마지막 함수는 가장 멋지지만 가장 실수도 저지르기 쉬운 함수다. 이는 전용 애니메이션 메서드로 애니메이션에 필요한 모든 매개변수를 지정하면 나머지는 jQuery가 알아서 처리한다. 매개변수 배열에 최종값으로 넘기면 jQuery는 배열에 정의된 값을 판단해 역시 매개변수로 넘긴 속력을 적용해서 마지막 값에 이를 때까지 페이지 엘리먼트를 부드럽게 움직여준다. Listing 4는 전용 애니메이션 메서드 예를 보여준다. 말하지 않아도 알겠지만 이 함수 응용 분야는 제한이 없으므로, 독자적인 전용 애니메이션이 필요하다고 느낄 때 유용하게 써먹기 바란다.


    Listing 4. 전용 애니메이션 메서드
    				
    // 버튼을 클릭하면, "movingDiv"라는 ID가 붙은 div에 전용 애니메이션 효과를 적용한다.
    $("#myButton").click(function(){
       $("#movingDiv").animate({
          // "movingDiv"에 속한 width, opacity, fontSize를 늘리며, 5초 동안 지속한다.
          width: 700;
          opacity: 0.5;
          fontSize: "18px";
       }, 5000);
       });

    Ajax

    최근에 "Ajax를 사용합니까?"라는 유행어가 모든 웹 페이지에 등장하고 있지만, 모든 사람이 Ajax가 진짜로 무엇을 의미하는지 아는 건 아니다. "Ajax"를 구글에서 검색해 보면 (다른 검색 결과와 마찬가지로) 수백만 건에 이르는 결과가 나타나지만 Ajax 용어가 품고 있는 사상이 무엇인지를 혼동하고 있다는 증거처럼 보인다. Ajax는 몇몇 페이지에서 보여주는 진짜 멋진 애니메이션도 아니며 진짜 멋진 그림자가 아래에 깔린 팝업 창도 아니다. 단지 Ajax가 멋지기 때문에 웹 페이지에서 보여주는 모든 흥미로운 효과를 Ajax라고 부르지는 않는다. Ajax의 핵심은 간단하게 말해 클라이언트 쪽 웹 페이지가 페이지를 다시 읽어들일 필요 없이 서버와 정보를 주고받는 수단일 따름이다. Ajax가 페이지에서 화끈한 효과를 주지는 못하지만, 웹 응용이 데스크톱 응용을 흉내내기 위한 수단을 제공한다. 따라서 Ajax를 둘러싼 소문은 근거가 있다. Ajax를 광범위하게 사용하는 관례는 오늘날 볼 수 있는 RIA 부문의 급격한 성장을 견인하고 있다.

    jQuery는 Ajax를 엄청나게 쉽게 만들어준다! 과장해 추켜세울 의도는 없다. 자바스크립트 라이브러리의 도움 없이 Ajax로 작업한다면 XMLHttpRequests를 사용해야 하는데, 마이크로소프트(Microsoft®)와 파이어폭스가 사용하는 XMLHttpRequests 사이에 벌어진 차이점을 인지하고 반환 코드를 파싱하고 그 밖에 온갖 작업을 몸소 진행해야 한다. jQuery는 Ajax를 함수 호출 한방에 끝내버린다. 농담이 아니다. 과거 100행에 이르는 코드는 현재 서너 줄이면 끝난다. 믿기 어려운 시간 절약이 아닌가? 개인적으로 jQuery를 알기 전에는 여기저기 Ajax 함수를 추가하는 데 상당한 작업이 필요한 듯이 보였다. jQuery를 사용하면 Ajax가 너무나도 단순한 작업으로 변하기에 Ajax가 제공하는 모든 기능을 십분 활용하도록 응용 프로그램을 수정해왔다. 일반 함수 호출처럼 단순하다면 사용하지 못할 이유가 무엇이랴?

    독자적인 Ajax 코드를 만드는 데 가장 널리 사용하는 함수인 post()get() 메서드에 초점을 맞추자. 두 함수는 현재 이 기사를 읽고 있는 시점에서 일반적인 jQuery 함수와 상당히 비슷하게 동작한다. URL과 넘길 매개변수를 명세하고 Ajax 메서드를 종료할 때 수행하는 함수를 명세하면 된다. 두 함수를 설정하는 방식 때문에 jQuery에서 다른 함수 호출과 정확하게 일치하는 방식으로 Ajax 메서드를 호출할 수 있게 되었다. Listing 5를 살펴보자.


    Listing 5. Ajax post()와 get() 메서드
    				
    // 이 코드는 myTest.php라는 php 파일에 들어간다.
    // Ajax 예제를 설명하다가 PHP를 다룬 이유가 무엇일까?
    // 자바/JSP를 설명하자면 지면이 부족하다.
    // 서블릿 코드도 보여줘야 하기 때문이다. 하지만 PHP를 사용하면 이런 번거로움이 없다.
    // 물론 두 함수는 PHP와 자바/JSP에서 제대로 동작한다.
    <?php
         echo "This is my return String";
    ?>
    
    // jQuery에서 Ajax를 호출하는 방법이 얼마나 간단한지를 보여준다.
    // post 함수
    $.post("myTest.php", {}, function(data){
       $("p").text(data);
    });
    
    // get 함수
    $.get("myTest.php", {}, function(data){
       $("p").text(data);
       });

    두 예제를 보면 알겠지만, 해당 함수는 다른 jQuery 함수와 거의 흡사하며, 자바스크립트 라이브러리 없이 Ajax 프로그램을 작성하는 경우와 비교해 훨씬 더 사용하기 쉽다. Ajax 호출 함수를 확장하기 위해 사용 가능한 몇 가지 인수가 있다. 첫 번째 인수는 두말할 필요없이 호출할 URL이 되어야 한다. PHP 파일, JSP 파일, 서블릿이 될 수 있으며, 실제로 요청을 처리할 수만 있다면 뭐든 가능하다. (나중에 예제 응용을 보면 알겠지만) 요청에 반드시 반응할 필요도 없다. 두 번째 인수는 옵션으로 post/get으로 넘길 자료를 담는다. 이 인수는 배열 형태다. 일반적으로 페이지에서 사용자 ID 등 Form 엘리먼트에 들어있는 정보를 넘길 때 사용한다. 서버 쪽 파일에서 요청을 처리하는 데 필요한 모든 내용을 담고 있다. 세 번째 인수는 역시 옵션이며 Ajax 함수가 성공적으로 끝나고 나서 호출할 함수다. 이 함수는 일반적으로 서버에서 전달하는 정보 결과를 처리하는 코드를 포함한다. Listing 6은 네 번째 인수 설명에 앞서 첫 세 인수를 활용하는 예제를 보여준다.


    Listing 6. 추가 인수를 받아들이는 post 메서드
    				
    // username과 password 입력 필드를 페이지에 추가한다.
    <input type=text id="username">
    <input type=password id="pass">
    
    // 서버 기반 PHP 파일을 호출한다. 서버쪽으로 전달한 정보를 이 파일 내부에서 처리한다.
    $.post("myFormProcessor.php", {username: $("#username").val(), 
                                   password: $("#pass").val()});
    
    // 거꾸로, 이 PHP 파일은 받은 결과를 처리할 함수에게 정보를 반환할 수 있다.
    $.post("myFormProcessor.php", {username: $("#username").val(), 
                                   password: $("#pass").val()},
           function(data){
               // data 변수는 서버에서 반환된 텍스트를 포함한다.
               // 미리 설정할 내용은 없으며, jQuery가 알아서 대신 처리해준다.
               if (data != "ERROR")
                  $("#responseDiv").text(data);
           }
           );

    지금까지 jQuery로 Ajax를 다루는 방법은 아주 직관적이고 쉽다는 사실을 확인했다. 하지만 단순히 텍스트 문자열이 아니라 서버에서 좀 더 복잡한 정보를 다루기 시작하면 일이 꼬이기 시작한다. 더 많은 Ajax 호출이 걸려있는 좀 더 복잡한 웹 페이지에서 반환 자료는 XML 형태도 가능하다. 반환 자료는 또한 JSON 객체 형태가 될 수도 있다(JSON은 기본적으로 자바스크립트 코드에서 사용 가능한 객체를 정의하는 프로토콜이다). jQuery는 네 번째 옵션 인수로 서버에서 기대하는 반환 값 유형을 미리 정의하는 get/post 메서드에 넘기도록 허용한다. XML 문자열을 위해 "xml"이라는 문자열을 넘기고, HTML 문자열(또는 평문)을 위해 "html"이라는 문자열을 넘기고, 자바스크립트 코드를 위해 "script"라는 문자열을 넘기고, JSON 객체를 위해 "json"이라는 문자열을 넘긴다. 따라서 예를 들어, 반환 객체를 "json" 유형으로 지정하면 jQuery는 자동으로 서버에서 오는 반응 문자열을 JSON 객체로 바꿔 즉시 참조가 가능하게 만든다.


    Listing 7. Ajax에서 반환 유형 명세하기
    				
    // 반환 객체를 JSON 객체 유형으로 정의하고, 객체 형 변환이나 평가 과정을 거치지
    // 않고서 내부 필드를 참조하도록 반환 객체를 JSON 객체로 처리한다.
    
    $.post("myFormProcessor.php", {username: $("#username").val(), 
                                   password: $("#pass").val()},
           function(data){
              // jQuery는 이미 결과 자료를 JSON 객체로 변환했기에, 
              // 즉시 내부 필드를 참조할 수 있다.
              // 좀 더 깔끔한 코드를 제공하며, 향후 변경에 대응이 가능하다.
              // XML 결과를 직접 처리하는 경우와 비교하면 작업이 훨씬 쉬워진다.
              $("#username").text(data.username);
              $("#address").text(data.address);
              $("#phone").text(data.phone);
           }, 
           "json"  // 여기서 반환 유형이 JSON이라고 명세한다.
           ); 

    설명에 시간을 들일 만한 또 다른 Ajax 함수는 load()이며, 사용자가 특정 페이지를 읽어서 결과로 HTML을 얻도록 만들어준다. 설명만 보면 그다지 흥미를 못 느낄지도 모르겠다. 하지만 시작 시점에서 웹 페이지를 파싱하듯이 jQuery 코드를 사용해 반환된 정보를 파싱하는 능력이 생긴다. 이게 무슨 이야기일까? 웹 페이지를 읽은 다음에 jQuery로 파싱이 가능한 능력을 토대로 아주 효율적이고 프로그램 작성이 쉬운 웹 로봇을 직접 만들 수 있다. 특정 페이지에서 어떤 정보 유형도 수집할 수 있다. 예제를 한번 살펴보자.


    Listing 8. load() 함수 예
    				
    // 야후 주식 시세를 호출하는 방법으로 아주 기본적인 주식 시세 시스템을 구축한 다음에
    // 야후 주식 시세 페이지에서 정보를 긁어온다.
    // 여기서는 IBM 주식 가격을 찾아 "stockPrice"로 ID를 설정한 텍스트 필드에서 보여준다.
    // 주식 가격을 포함한 ID는 "yfs_190_ibm"이다.
    $("#stockPrice").load("http://finance.yahoo.com/q?s=ibm #yfs_l90_ibm").text();

    Ajax 모듈에서 소개할 마지막 두 함수는 Ajax 작업을 훌륭하게 보조해 주는 진짜 유틸리티 함수다. 이미 여러 차례 지적한 바와 같이 클라이언트와 서버 사이에서 일어나는 상호 작용 대다수는 폼과 폼이 포함하는 엘리먼트를 둘러싸고 일어난다. 이런 통신 유형이 아주 일반적이므로 jQuery에는 두 가지 유틸리티 함수가 있어서 HTTP 질의 문자열이거나 JSON 문자열 형태로 서버 쪽에 전달할 매개변수 생성을 도와준다. Ajax가 요구하는 조건에 맞춰 지원하는 유틸리티 함수를 골라 활용한다. 활용법이 아주 간단한 이유는 전체 폼을 캡슐화하므로 개발 도중에 자유롭게 엘리먼트를 추가, 삭제, 변경할 수 있기 때문이다. Listing 9는 이런 예제를 보여준다.


    Listing 9. serialize()serializeArray() 함수
    				
    // serialize() 함수는 지정 엘리먼트에 들어있는 모든 폼 엘리먼트를 살핀 다음에
    // 자동으로 엘리먼트의 모든 정보를 포함하는 <element name>=<element value>&
    // 형태로 HTTP 문자열을 만든다.
    // 예는 "firstname=Michael&lastname=Abernethy"와 같다.
    // 이렇게 만든 문자열을 Ajax 호출로 정보를 전달할 URL 뒤에 덧붙인다.
    $.post("myFormProcessor.php?" + $("#myForm").serialize());
    
    // 또한 serializeArray() 함수로 비슷한 작업을 수행할 수도 있다.
    // 폼을 JSON 형태로 변환한다.
    $.post("myFormProcessor.php", {json: $("#myForm").serializeArray()});

    여기서 배운 모든 내용을 하나로 합치기

    모든 내용을 하나로 합쳐서 만든 데모 웹 응용인 웹 메일을 마지막으로 살펴보자. 이미 지난 연재물에서 충분히 익숙하게 살펴보았을 것이다. 정보 획득을 위해 클라이언트 쪽에서 서버 쪽으로 여러 Ajax 호출을 수행한다. 여기서는 메시지를 읽고 메시지를 지울 때 AJax를 활용한다. 그러고 나서 Effects를 활용해 사용자가 메시지를 지울 때 즉시 화면에서 메시지를 사라지게 만든다. 심지어 사용자가 페이지를 다시 읽지 않으며 Ajax 호출을 활용해 비동기식으로 실제 삭제가 일어나지만 이런 삭제 동작이 즉시 일어난다. 직접 만든 웹 응용에서 Ajax 호출이 얼마나 쉬운지를 살펴보고 데스크톱 응용을 진짜로 흉내내기 위해 Ajax를 활용하는 방법을 살펴보고, Effects를 활용해 응용 프로그램 사용성을 높이는 방법을 예제를 보면서 최종적으로 확인한다.


    Listing 10. 예제 웹 응용: 메시지 삭제하기
    				
    // 먼저 메시지 삭제를 처리하는 방법을 살펴보자.
    
    // 첫 단계는 실제로 메시지를 지울 버튼 생성이다.
    <input type=button id="delete" value="Delete">
    
    // 다음으로 테이블 각 행에 체크박스를 추가해 사용자가 삭제를 원하는 메시지를
    // 선택하도록 만든다. 이런 체크박스를 나중에 활용할 텐데, 여기에 들어있는 정보는
    // 아주 중요하다(예시라고 부른다).
    // 각 체크박스 값이 message.id라는 사실에 주목하자.
    
    <tr class="messageRow" id="<%=message.id %>">
    <input type=checkbox name="delId" value="<%=message.id%>" class=selectable>
    
    // 이제 HTML이 완료되었으므로 삭제를 수행하는 jQuery 코드를 살펴보자.
    
    // 먼저, 삭제 버튼에 이벤트를 추가한다. 버튼을 누르면 체크된 메시지를 지우기 시작한다.
    
    $("#delete").click(function() {
       deleteMessages();
    });
    
    // 마지막으로 deleteMessage() 함수를 정의하자. 오늘 배운 내용에서 가장
    // 중요한 내용을 담고 있다.
    // 모든 기사에서 다룬 내용을 완성하는 함수이므로, 동작 원리를 자세히 설명하겠다.
    // 참고 1 - 아주 구체적인 검색 매개변수를 넘겨 체크된 체크박스를 하나씩
    // 순회하며 "selectable" 클래스 멤버만 찾도록 만든다.
    // 참고 2 - 체크박스 값이 포함된 테이블 행 ID와 동일하므로, Effects 모듈을 사용해
    // 전체 테이블 행을 감출 수 있다. 체크박스 값을 전달하고 표 행을 다시 얻은 다음에 감춘다.
    // 참고 3 - Ajax를 호출해 실제로 DB에서 메시지를 삭제한다. messageID를 서버에 전달해
    // 삭제될 항목을 알도록 만든다. 체크박스 값에 포함된 정보를 Ajax 호출 과정에서 전달한다.
    // 성공인지 아닌지 신경쓰지 않기 때문에 서버에서 돌아오는 대답을 무시한다.
    
    function deleteMessages()
    {
        $(".selectable:checked").each(function() {
            $("#"+$(this).val()).remove();
            $.post("<%=HtmlServlet.DELETE_MESSAGES%>.do", {delId: $(this).val()});
        });
        }

    두 번째 예제로, 메시지를 읽는 방법을 살펴보자. jQuery에서 Ajax를 활용하는 예를 보여준다.


    Listing 11. 예제 웹 응용: 메시지 읽기
    				
    
    // 지금까지 예제에서 코드 대부분을 살펴보았으므로, 코드에서 Ajax 부분만 초점을 맞춘다.
    // 참고 1 - Ajax 호출을 하면서 인수 네 개를 정의해 넘긴다.
    // 메시지를 읽으려면 서버에 두 변수를 넘겨야 한다.
    // 첫 번째는 메시지 ID로 읽기를 원하는 메시지가 무엇인지 알아야 하기 때문이다.
    // 두 번째는 현재 뷰로 .. 어떤 목적으로 사용했는지 기억나지 않는다.
    // (그다지 중요하지 않는 듯이 보인다)
    // 참고 2 - Ajax 함수로 넘기는 네 번째 인수는 "json"이다.
    // Ajax 호출로 JSON 객체를 반환하라는 표식이다. jQuery는 결과로 반환되는
    // 문자열을 JSON 객체로 자동으로 변환한다.
    // 참고 3 - eval() 함수를 사용하지 않고 JSON 객체를 직접 다루고 있다는 점에 주목하자.
    // jQuery가 객체를 만들었기 때문이다. 따라서 필드를 직접 참조할 수 있다.
    $(".messageRow").dblclick(function() {
        if ($(this).hasClass("mail_unread"))
        {
            $(this).removeClass("mail_unread");
        }
        $.post("<%=HtmlServlet.READ_MESSAGE%>.do", {messageId: $(this).attr("id"),
                                                         view: "<%=view %>"}, 
          function(data){
            if (data != "ERROR")
            {
                 // JSON 객체를 활용한다.
                 $("#subject").val(data.subject);
                 $("#message").val(data.message);
                 $("#from").val(data.from);
             }
          }, "json");
        $.blockUI(readMess, {width:'540px', height:'300px'});
        });

    결론

    jQuery와 같은 자바스크립트 라이브러리는 데스크톱에서 브라우저로 응용 프로그램을 이식함에 따라 점점 더 중요해진다. 이런 응용은 점점 더 복잡해지므로, 웹 응용 프로젝트에서 jQuery와 같은 튼튼한 교차 브라우저 해법을 필수로 요구한다. jQuery는 다른 자바스크립트 라이브러리와 격차를 벌이기 시작했으며, 필요한 모든 작업을 수행하는 능력과 함께 손쉬운 개발 특성 때문에 많은 개발자가 jQuery를 핵심 라이브러리로 선택하고 있다.

    연재물 세 번째 기사에서, 응용에 풍부함을 더해 데스크톱 응용과 웹 응용 사이에 경계를 허무는 두 가지 모듈을 익혔다. 이번 기사에서 가장 강력하게 추가한 내용은 Ajax 모듈로, 다른 jQuery 메서드 호출처럼 간단하고 직관적인 인터페이스를 제공함으로써 Ajax를 아주 쉽게 활용하도록 만든다. 페이지를 다시 읽느라 지연되는 짜증을 겪지 않고서 응용 프로그램 반응 속력을 높이는 훌륭한 도구로 몇 가지 예제를 곁들여 Ajax의 위력도 살펴보았다. Effects 패키지에 대한 내용도 빠지지 않았다. 애니메이션과 페이지 엘리먼트 감추기/보여주기 기능을 적절하게 사용한다면 좋은 UI 디자인이라는 강력한 지원군을 얻게 된다. Ajax와 Effect를 결합해 효율적으로 활용하면 웹 사이트에 동적인 능력을 상당히 강화할 수 있다.

    마지막으로 웹 응용 예제를 다시 한번 살펴보았고, AJax 모듈을 추가해 페이지를 다시 읽어들이지 않고도 메시지를 읽고 삭제하는 방법을 익혔다. 그러고 나서 Ajax와 Effect 조합으로 페이지를 다시 읽어들이지 않고도 사용자 페이지와 DB 웹 응용에서 메시지를 삭제하는 방법을 익혔다. 사용자에게 메시지 삭제는 투명한 과정이며, 미리 정해진 방식에 맞춰 프로그램 상에서 동작한다.

    이 기사는 모든 jQuery 배포판에 따라오는 핵심 라이브러리에 대한 소개 내용으로 마무리를 한다. 연재물에서 jQuery에 포함된 모든 모듈을 살펴보았으며, jQuery로 작업하는 과정이 쉽고 직관적이라는 사실을 보여줬다. 또한 어떤 웹 응용을 만들거나 jQuery는 RIA 유형에 무관하게 제 자리를 잡고 있다는 사실을 확인했다. 자바스크립트가 요구하는 수준에 맞춰 튼튼한 토대를 제공하기 때문이다. 연재물은 직접 코드를 작성하는 과정에서 jQuery를 아주 자연스럽게 활용하는 수준에 이르도록 독자들을 이끌었다. 첫 번째 기사는 jQuery 동작 방식, 페이지 엘리먼트 탐색을 위한 활용 방법, 엘리먼트를 순회하는 방법, Array 객체와 같은 방식으로 접근하는 방법을 설명했고, 두 번째 기사는 풍부함을 제공하는 토대로 세 가지 모듈을 소개했다. 마지막으로 세 번째 기사는 완벽하고 복잡한 웹 응용을 만들기 위한 프레임워크를 위한 마지막 퍼즐 조각을 보여줬다.





    위로


    다운로드 하십시오

    설명 이름 크기 다운로드 방식
    예제 애플리케이션을 담은 Zip 파일 jquery.zip 69KB HTTP
    다운로드 방식에 대한 정보




    'DHTML > Javascript' 카테고리의 다른 글

    http://visualjquery.com/  (0) 2009.08.05
    [펌]jQuery로 Ajax 개발을 단순화 하기  (0) 2009.07.30
    ExtJS --> XmlTreeLoader Error....  (154) 2009.06.26
    [그래프 툴] jquery flot  (0) 2009.06.18
    [펌] 부모창과 닫히는 팝업창  (0) 2009.04.28
    Posted by tornado
    |
    북마크가 없어져서... 블로그에 남김.




    Microsoft Office Communications Server 2007 R2
    Adding Commands to the Communicator 2007 R2 Menus

    You can add custom commands to various Communicator menus, and pass the SIP URI of the current user, and selected contacts, to the application launched by your custom command.

    The custom commands that you define appear on the following menus:

    • The Tools menu.
    • The Actions menu off the Conversation window.
    • The right-click menu off the Contact List.

    See the "Accessing a Custom Command" section, later in this topic.

    You can define custom commands for two types of applications:

    • Applications that apply only to the current user and are launched on the local computer.
    • Applications that involve additional users, such as an online collaboration program, and must be launched on each user's computer.

    When the application you want to integrate involves other users, the custom command can be invoked by:

    • Selecting one or more users, and then choosing the custom command.
    • Starting a two-party or multi-party conversation, and then choosing the custom command.

    For a detailed example, see Integrating a Third-Party Collaboration Program with Communicator in the Client Technical Reference documentation.

    Use the registry settings in the table below to add a command to the Office Communicator menus. These entries are placed in the registry at HKEY_LOCAL_MACHINE\Software\Microsoft\Communicator\SessionManager\Apps\[GUID of Application].

    Custom command registry entries

    Name Type Data

    Name

    REG_SZ

    Name of the application as it appears on the menu.

    ApplicationType

    DWORD

    0 = Executable (default)

    Dd819982.note(en-us,office.13).gif Note:
    Requires ApplicationInstallPath.

    1 = Protocol

    ApplicationInstallPath

    REG_SZ

    Full path of the executable.

    Dd819982.note(en-us,office.13).gif Note:
    Must be specified if ApplicationType is 0 (Executable).

    Path

    REG_SZ

    Full path to be launched along with any parameters, including the default parameter of %user-id% and %contact-id%.

    SessionType

    DWORD

    0 = Local session. The application is launched on the local computer.

    1 = Two-party session (default). Communicator 2007 R2 launches the application locally, and then sends a desktop alert to the other user. The other user clicks the alert and starts the specified application on their computer.

    2 = Multi-party session. Communicator 2007 R2 launches the application locally, and then sends desktop alerts to the other users, prompting them to launch the specified application on their own computer.

    ExtensibleMenu

    REG_SZ

    A list of the menus where this command will appear, separated by semi-colons. Possible values are:

    MainWindowActions MainWindowRightClick ConversationWindowActions ConversationWindowContextual ConversationWindowRightClick

    If ExtensibleMenu is not defined, the default values of MainWindowRightClick and ConversationWindowContextual are used.

    For example, executing the following Registry Editor (.REG) file results in the addition of the Contoso Sales Contact Manager menu item to the Actions menu.

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\Software\Microsoft\Communicator\SessionManager\Apps\{1F9F07C6-7E0B-462B-AAD7-98C6DBEA8F69}]
    "Name"="Contoso Sales Contact Manager"
    "HelpMessage"="The Contoso Sales Contact Manager is not installed. Contact the Help Desk for more information."
    "ApplicationType"="REG_DWORD:00000000"
    "ApplicationInstallPath"="C:\\cltest.exe"
    "Path"="C:\\cltest.exe %user-id% %contact-id%"
    "SessionType"="REG_DWORD:00000001"
    "ExtensibleMenu"="ConversationWindowActions;MainWindowRightClick"
    To access a custom command after it is added
    • Do one of the following, depending on the ExtensibleMenu values you define:

      • MainWindowActions: On the Office Communicator Title bar, click the down arrow, point to Tools, and then click your custom command.
      • MainWindowRightClick: Right-click a contact in the Contact List or Search Results pane, and then click your custom command.
      • ConversationWindowActions: In the Conversation window Title bar, click the Menu button, point to Actions, and then click your custom command.
      • ConversationWindowContextual: In the Conversation window, click the contextual actions drop-down arrow in the top right corner, below the Title bar, and then click your custom command.
      • ConversationWindowRightClick: In the Conversation window Participant List, right-click a contact name, and then click your custom command.
    Tags What's this?: Add a tag
    Community Content   What is Community Content?
    Add new content RSS  Annotations
    %contact-id% parameter is not functional in R2      javerlin   |   Edit   |   Show History
    Even though documented under "path" and shown in the example, the %contact-id% parameter is not functional in R2. It is not replaced by the actual contact value but is literally passed as "%contact-id%". The %user-id% parameter is functional.

    This lack of functionality rendors nearly useless any menu selections when right clicking on a contact since the contact information is not passed to the application.

    It would be very valuable to know if this has been intentionally removed for R2 or if it is a bug.
    Posted by tornado
    |

    보통 java 로 만든 웹어플리케이션을 구성하는 서버는 아파치(또는 IIS) 와 같은 웹서버와 WAS 를 연동 시켜서 사용한다.

    아파치 웹서버 같은 경우 디렉토리 접근제어 등의 설정들이 존재하는데, 아래와 같이 설정한다.

    <Directory "/www/context/admin/">
        Order deny,allow
        Deny from all
        Allow from 211.241.xxx.xxx/24
    </Directory>

    이렇게 설정되면 211.241.xxx에서 요청되는 255 개의 IP 에 대하여 허용을 하게 된다.

    그런데, 이렇게 했을 경우 문제가 생긴다.

    바로 루프백 주소(127.0.0.1) 이다.

    왜 문제가 되느냐, 서버에서 서버로 호출할때는 127.0.0.1 로 호출되기 때문에

    Allow 주소에 위에처럼 211.241.xxx 만 오픈 되어있을 경우 호출이 되지 않는다,

    Allow from 에 127.0.0.1 도 추가해 주어야  URLConnection 처럼 호출 하여도 문제가 발생하지 않는다.

    ----------------------

    프로그램보다 인프라가 더 어려워 -.-;
    Posted by tornado
    |
    출처 : http://www.smashingmagazine.com/2009/01/15/45-new-jquery-techniques-for-a-good-user-experience/



    by Noura Yehia

    JavaScipt libraries have made huge leaps and bounds in helping developers write code and develop products more quickly. jQuery is one of the most popular JavaScript frameworks, with powerful tools that improve the user’s interaction with Web applications. jQuery has an additional advantage in that it allows developers to select elements on a page using CSS-like syntax.

    To help you take it up a notch, we share below some methods that can help you give visitors to your website an amazing user experience. Here are over 45 impressive jQuery plug-ins and techniques that have been recently created and that could make the development of your next website an easier and more interesting experience than the last.

    You may want to take a look at the following related posts:

    Dynamic Content

    1. Build A Login Form With jQuery
    In this tutorial, we’ll create a sliding panel, that slides in to reveal more content, using JQuery to animate the height of the panel. In this case, we will be creating a hypothetical login for the new tutsplus area that’s coming soon.

    jQuery

    2. Spoiler Revealer with jQuery
    A simple technique that hides some content first and fades it in once a link is clicked.

    jQuery

    3. AJAX Upload
    This AJAX file upload plug-in allows users to easily upload multiple files without having to refresh the page. In addition, you can use any element to trigger the file selection window. The plug-in creates a semi-transparent file input screen over the button you specify, so when a user clicks on the button, the normal file selection window is shown. After the user selects a file, the plug-in submits the form that contains the file input to an iFrame. So it isn’t true AJAX but provides the same user experience.

    jQuery

    4. FCBKcomplete
    Give your users fancy Facebook-like dynamic inputs, with auto-complete and pre-added values.

    jQuery

    5. Create Accessible Charts Using Canvas and jQuery
    This tool is proof that you can use the <canvas> element to illustrate HTML table data. The idea is a good one: putting the data in a table allows it to remain accessible, while the chart can be shown for visual enhancement.

    jQuery

     

    Form Manipulation

    6. Radio Button and Check Box Replacement
    This jQuery tool replaces radio buttons and check boxes with a more appealing display.

    jQuery

    7. Submit a Form without a Page Refresh

    jQuery

    8. jQuery AJAX Contact Form
    Here is a quick and easy way to make a jQuery AJAX contact form with a “honeypot” to foil email bots, load success and error messages dynamically without leaving the page and provide descriptive error messages detailing why submitted values have failed validation.

    jQuery

    9. Simple jQuery Form Validation
    This jQuery form shows live form-input validators both server-side and browser-side.

    jQuery

     

    Navigation Menus

    10. jQuery Context Menu
    A context menu plug-in for jQuery that features easy implementation, keyboard shortcuts, CSS styling and control methods.

    jQuery

    11. Kwicks for jQuery
    Kwicks for jQuery started off as a port of the incredibly attractive MooTools framework, but has evolved into a highly customizable and versatile widget.

    jQuery

    12. jQuery iPod-style Drilldown Menu
    “We created an iPod-style drilldown menu to help users traverse hierarchical data quickly and with control. It’s especially helpful when organizing large data structures that don’t translate well into traditional dropdown or fly-out menus.”

    jQuery

    13. jQuery File Tree
    The jQuery File Tree is a configurable AJAX file-browser plug-in for jQuery. You can create a customized, fully-interactive file tree with as little as one line of JavaScript code.

    jQuery

    14. How to Create a MooTools Home Page-Inspired Navigation Effect
    In this tutorial, you’ll recreate the same effect seen in MooTools’s menu, but in jQuery!

    jQuery

    15. CSS Sprites2
    This tutorial demonstrates how to implement inline CSS Sprites2 using jQuery.

    jQuery

     

    Manipulating Content

    16. jQuery books widget
    With some custom JavaScript and jQuery magic you can create some interesting widgets. A good way to demonstrate this functionality is by building a browsable Amazon.com books widget.

    jQuery

    17. Text Size Slider
    This tutorial explains how to use a slider to control the text size of an article on a page. This lets the user control exactly the size that suits them, and is also a pretty impressive feature to have on a site.

    jQuery

    18. Pagination
    Create navigational elements: when you have a large number of items, you can group them into pages and present navigational elements that allow users to move from one page to another.

    jQuery

    19. Coda-Slider
    As with the last tool, groups items together using navigational elements that allow users to move from one page to another.

    jQuery

    20. Creating a Slick Auto-Playing Featured-Content Slider
    If you love the Coda-Slider plug-in for jQuery, then you will find this plug-in very useful for displaying lots of content in a small area. This nice plug-in adds some features not found in the original Coda-Slider, such as slowly cycling through panels, auto-playing different types of custom content. An arrow indicator serves as a visual indication of which panel you are currently viewing.

    jQuery

    • Demo can be found here.
    • Download files here.

    21. haccordion
    A simple horizontal accordion plug-in for jQuery.

    jQuery

     

    Tabular Data and Grids

    22. Table Row Checkbox Toggle
    This tool generically adds a toggle function to any table row you specify based on a CSS class name. It will, by default, toggle on any check boxes within that table row.

    jQuery

    23. Tablesorter
    Tablesorter is a jQuery plug-in that turns a standard HTML table with <th> and <td> tags into a sortable table without the need for page refreshes. Tablesorter can successfully parse and sort many types of data, including linked data, in a cell.

    jQuery

    24. TableEditor
    TableEditor provides flexible in-place editing of HTML tables. User-defined handler functions can easily be dropped in to update, for example, a data source via an AJAX request.

    jQuery

    25. Scrollable HTML Table
    This JavaScript code can be used to convert ordinary HTML tables into scrollable ones.

    jQuery

     

    Lightbox Techniques

    26. Revealing Photo Slider
    Learn how to create a thumbnail photo gallery, where clicking a button reveals the entire photo and more information about that photo.

    jQuery

    27. FancyBox
    FancyBox was born to automatically scale large images to fit in windows, adding a nice drop-shadow under the zoomed item. It can be used to group related items and add navigation between them (using a pre-loading function). FancyBox is totally customizable through settings and CSS.

    jQuery

    28. Facebox Image and Content Viewer
    Facebox is a lightweight Facebook-style Lightbox that can display images, divs, and even entirely remote pages (via AJAX) inline on a page and on demand. It uses the compact jQuery library as its engine, unlike Lightbox v2.0, which uses Prototype.

    jQuery

    29. jQuery.popeye
    jQuery.popeye is a plug-in that transforms an unordered list of images into a simple image gallery. When an image is clicked, it enlarges Lightbox-style. The images are displayed in a box with “Previous” and “Next” controls, and information about the images can be included.

    jQuery

     

    Image Galleries and Viewers

    30. Simple Controls Gallery
    Simple Controls Gallery rotates and displays each image by fading it into view over the previous one, with navigation controls that pop up when the mouse hovers over the gallery. The controls allow the user to play, pause or jump to a specific image in the gallery.

    jQuery

    31. Agile Carousel
    This jQuery plug-in allows you to easily create a custom carousel. Use the jQuery UI to enable many different types of transition. The plug-in uses PHP to call images from the folder you specify. Configure many different options including controls, slide timer length, easing type, transition type and more!

    jQuery

     

    Browser Tweaks

    32. Setting Equal Heights with jQuery
    A script to equalize the heights of boxes within the same container and create a tidy grid.

    jQuery

    33. jQuery IE6 PNG Transparency Fix
    Another IE6 PNG fix that uses jQuery selectors to automatically fix all PNG images on a page.

    34. BGI frame
    This tool helps ease the pain of dealing with IE z-index issues. You can find a demo here.

    35. Fix Overflow
    IE puts scroll bars inside overflowing elements, and if an element is only one line, the scroll bar will cover it. This plug-in fixes that issue.

    jQuery

    36. Lazy Load
    Lazy Load delays the loading of images below the fold on long pages. As the user scrolls down, the images are loaded as needed. Check out the demo here.

    37. Maxlength
    It’s a fairly common design practice to limit the number of characters a user can input in a field while giving feedback on how many spaces are left. This plug-in automates that task.

    jQuery

     

    Animation Effects

    38. Scrollable
    Scrollable is a flexible and lightweight (3.9 KB) jQuery plug-in for creating scrollable content. Scrollable items can contain any HTML, such as text, images, forms, video or any combination of them. You can make items scroll horizontally or vertically and decide how many items are visible at once.

    jQuery

    39. jQuery Fading Menu - Replacing Content
    “Instead of thinking about CSS as page layout and a way to style your page when it loads, you can use in animation and change it on-the-fly to react to events that happen on your page. Take for example a menu. You can take the “click” event that happens when clicking on a menu to do lots of stuff.”

    jQuery

    40. Build an Animated Cartoon Robot with jQuery
    This effect simulates a faux 3-D animated background reminiscent of old-school side-scrolling video games (and not unlike the parallax effect). This effect is created by layering several empty divs over each other, with transparent PNGs as background images. The backgrounds are animated at different speeds using jQuery.

    jQuery

    41. Flip
    Flip is a plug-in for jQuery that “flips” page elements in four directions. Compatible with Firefox 2+, Internet Explorer 6+, Safari 3.1 (for Windows) and Google Chrome.

    jQuery

    • Download files here.

    42. Use jQuery for Background Image Animations
    Animate your menu whenever a user hovers over an item with this effect.

    jQuery

     

    Image Manipulation

    43. Jcrop
    Jcrop is the quick and easy way to add image-cropping functionality to your Web application. It combines the ease of use of a typical jQuery plug-in with a powerful cross-platform DHTML cropping engine that is faithful to familiar desktop graphics applications.

    jQuery

    44. jQZoom
    JQZoom is a JavaScript image magnifier that makes it really easy to magnify what you want. It is easy to customize and works on all modern browsers.

    jQuery

     

    Miscellaneous

    45. Date Range Picker
    A rich date-range widget that uses the jQuery UI’s date picker and some additional custom interaction.

    jQuery

    46. Sortable Lists
    Unordered lists are commonly used to structure a website’s navigation. Having the ability to re-order such lists would be extremely useful. Here is a method to easily save and reload the list element order without getting lost as the page is refreshed.

    jQuery

    47. Amazing Music Player Using Mouse Gestures and Hotkeys
    Learn how to create an amazing music player, coded in XHTML and jQuery, that makes use of mouse gestures and hotkeys. You can click and drag the mouse to interact with the music player’s interface or use directional keys and the space bar instead of the mouse.

    jQuery

    48. Script for Tracking Outbound Links in Google Analytics with jQuery
    This code snippet uses Google Analytics and jQuery to automatically track outbound links. This interesting script enhances behavior by comparing the link’s domain to the current page’s domain and, if they are different, triggering the behavior. This is helpful when using a CMS or other tool that generates full URLs, including the “http://,” instead of relative ones.

    1. <script type="text/javascript">   
    2.     $('#content a:not(.popupwindow)').filter(function() {   
    3.         var theHref = this;   
    4.         if (theHref.hostname && theHref.hostname !== location.hostname) {   
    5.             $(theHref).not(".noAutoIcon").addClass("offSite");   
    6.             $(theHref).not(".noAutoLink").attr('target','_blank').bind('click keypress'function(event) {   
    7.                 var code=event.charCode || event.keyCode;   
    8.                 if (!code || (code && code == 13)) {   
    9.                     if(pageTracker){   
    10.                         var fixedLink = this.href;   
    11.                         fixedLink = fixedLink.replace(/https?:\/\/(.*)/,"$1");   
    12.                         fixedLink = '/outgoing/'   fixedLink;   
    13.                         pageTracker._trackPageview(fixedLink);   
    14.                     };   
    15.                 };   
    16.             });   
    17.         };   
    18.     });   
    19. </script>  
    1. <script type="text/javascript">   
    2.     $('#content a:not(.popupwindow)').filter(function() {   
    3.         var theHref = this;   
    4.         if (theHref.hostname && theHref.hostname !== location.hostname) {   
    5.             $(theHref).not(".noAutoIcon").addClass("offSite");   
    6.             $(theHref).not(".noAutoLink").attr('target','_blank').bind('click keypress'function(event) {   
    7.                 var code=event.charCode || event.keyCode;   
    8.                 if (!code || (code && code == 13)) {   
    9.                     if(pageTracker){   
    10.                         var fixedLink = this.href;   
    11.                         fixedLink = fixedLink.replace(/https?:\/\/(.*)/,"$1");   
    12.                         fixedLink = '/outgoing/'   fixedLink;   
    13.                         pageTracker._trackPageview(fixedLink);   
    14.                     };   
    15.                 };   
    16.             });   
    17.         };   
    18.     });   
    19. </script>  

    49. jGrowl
    jGrowl is a jQuery plug-in that delivers unobtrusive messages within the browser, similar to the way that OS X’s Growl Framework works.

    jQuery

    Related posts

    You may want to take a look at the following related posts:

    Posted by tornado
    |

    Extjs 2.2.1 을 다운로드 받아서 트리메뉴와 layout 을 이용하려고 했다.

    TreeMenu 를 구성하는 데이터는 XML 을 이용함.

    그러나!!!! 의도된 동작이 일어나지 않음.

    FireBug 를 동원하여 에러분석 돌입.

    FireBug 에서는 405 Method Not Allowed  에러 메시지 출력.

    그래서... Xml을 읽어오는 TreeLoader 에 옵션으로 아래와 같이 설정.

    requestMethod:'GET'

    동작 잘 한다...


    아래는 ExtJS 에서 제공하는 XmlTreeLoader 샘플 Javascript 파일이다.

    붉은 글씨를 유의하여 보면 됨.

     
    /*
     * Ext JS Library 2.2.1
     * Copyright(c) 2006-2009, Ext JS, LLC.
     * licensing@extjs.com
     *
     * http://extjs.com/license
     */


    //
    // Extend the XmlTreeLoader to set some custom TreeNode attributes specific to our application:
    //
    Ext.app.BookLoader = Ext.extend(Ext.ux.XmlTreeLoader, {
        processAttributes : function(attr){
            if(attr.first){ // is it an author node?
               
                // Set the node text that will show in the tree since our raw data does not include a text attribute:
                attr.text = attr.first + ' ' + attr.last;
               
                // Author icon, using the gender flag to choose a specific icon:
                attr.iconCls = 'author-' + attr.gender;
               
                // Override these values for our folder nodes because we are loading all data at once.  If we were
                // loading each node asynchronously (the default) we would not want to do this:
                attr.loaded = true;
                //attr.expanded = true;
            }
            else if(attr.title){ // is it a book node?
               
                // Set the node text that will show in the tree since our raw data does not include a text attribute:
                attr.text = attr.title + ' (' + attr.published + ')';
               
                // Book icon:
                attr.iconCls = 'book';
               
                // Tell the tree this is a leaf node.  This could also be passed as an attribute in the original XML,
                // but this example demonstrates that you can control this even when you cannot dictate the format of
                // the incoming source XML:
                attr.leaf = true;
            }
        }
    });

    Ext.onReady(function(){
     
        var detailsText = '<i>Select a book to see more information...</i>';
       
     var tpl = new Ext.Template(
            '<h2 class="title">{title}</h2>',
            '<p><b>Published</b>: {published}</p>',
            '<p><b>Synopsis</b>: {innerText}</p>',
            '<p><a href="{url}" target="_blank">Purchase from Amazon</a></p>'
     );
        tpl.compile();
       
        new Ext.Panel({
            title: 'Reading List',
         renderTo: 'tree',
            layout: 'border',
         width: 500,
            height: 500,
            items: [{
                xtype: 'treepanel',
                id: 'tree-panel',
                region: 'center',
                margins: '2 2 0 2',
                autoScroll: true,
             rootVisible: false,
             root: new Ext.tree.AsyncTreeNode(),
               
                // Our custom TreeLoader:
             loader: new Ext.app.BookLoader({
                 dataUrl:'xml-tree-data.xml'
                 , requestMethod: 'GET'
             }),
               
             listeners: {
                 'render': function(tp){
                        tp.getSelectionModel().on('selectionchange', function(tree, node){
                            var el = Ext.getCmp('details-panel').body;
                         if(node.leaf){
                             tpl.overwrite(el, node.attributes);
                         }else{
                                el.update(detailsText);
                            }
                        })
                 }
             }
            },{
                region: 'south',
                title: 'Book Details',
                id: 'details-panel',
                autoScroll: true,
                collapsible: true,
                split: true,
                margins: '0 2 2 2',
                cmargins: '2 2 2 2',
                height: 220,
                html: detailsText
            }]
        });
    });




    Posted by tornado
    |
    출처 : http://code.google.com/p/flot/


    Flot is a pure Javascript plotting library for jQuery. It produces graphical plots of arbitrary datasets on-the-fly client-side.

    The focus is on simple usage (all settings are optional), attractive looks and interactive features like zooming and mouse tracking.

    The plugin is known to work with Internet Explorer 6/7/8, Firefox 2.x+, Safari 3.0+, Opera 9.5+ and Konqueror 4.x+. If you find a problem, please report it. Drawing is done with the canvas tag introduced by Safari and now available on all major browsers, except Internet Explorer where the excanvas Javascript emulation helper is used.

    Examples

    Take a look at the examples to see how it works, or look at FlotUsage to see some real projects using Flot.

    Documentation

    Besides the examples, there's a README, FAQ and the API documentation, all for the development version. The NEWS will tell you the changes.

    You could also take a look at the TODO, although most of the suggestions are in the bug tracker.

    If you need more help, you can ask on the mailing list. You can probably save yourself some time skimming the FAQ first.

    Who's behind this?

    The development so far has mostly been done by Ole Laursen, sponsored by IOLA, a small Danish web-development house focusing on Django and jQuery. If you need commercial support, you're welcome to contact us.

    Posted by tornado
    |