AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1444&pId=-1
Inline-Edit Control Using ASP.NET 2.0 AJAX 1.0 Extensions
page
by Bilal Haidar
Feedback
Average Rating: 
Views (Total / Last 10 Days): 33635/ 48

Introduction

AJAX brought a lot of new ideas to develop rich web applications. Many techniques that we used to dream of before the days of AJAX can now be easily implemented!

One of the nice features that developers can provide for a Web application is the ability to allow Administrators or Editors on the website to edit pages with static text on the spot without having to generate a new Web form just for editing those static pages.

Suppose for example you would like to post your CV on a web page, that CV rarely changes, so instead of having to store it in a database you can simply place your CV as plain HTML and let it be editable on-the-spot. This way, when you for example attend a new training at your work and want to add that to you CV, you simply click on your online CV. It will be converted into an editable area, you add or remove any part of your CV and that is it! Your CV is now updated with no database access or extra effort with dynamic form!

This article shall explain how to enable editable areas on a WebForm with a single line of HTML code.

This article requires that readers are familiar with creating AJAX classes. If you feel you need more on this topic, it is recommended that you check the following article:

Original Script

The logic behind the inline-edit AJAX script that this article will discuss is based on a native AJAX script.

The author of that script used native AJAX to enable inline-edit on a web form. In this article we will convert that script into an AJAX 1.0 script where you place a reference to it inside the Script References section of the ScriptManager.

The basic idea behind the inline-edit control is that a span HTML control is placed on the Web form with a special class name. The inline-edit script will parse the page and get all spans with a specific class name and add to them onclick event. So when clicked, the content of the clicked span will be shown either in a Textbox or TextArea depending on the size of text to be edited.

Building the Script

In AJAX 1.0 Extensions a developer can create an AJAX Control, an AJAX Extender Control, and an AJAX class that can encapsulate the functionality of a feature to be added to the Web application. In this article we will create an AJAX class which will include all the methods required for the inline-edit to work properly on a Web Form. However, this AJAX class can be easily converted into an AJAX Extender control.

The inline-edit script starts by defining the constructor as shown in Listing 1.

Listing 1

// Register a new Namespace
Type.registerNamespace("bhaidar.CodeSuite.AJAX");
// Define the constructor of the InlineEdit class
bhaidar.CodeSuite.AJAX.InlineEdit = function (uiElement) {
    // Call base class just for completeness
    bhaidar.CodeSuite.AJAX.InlineEdit.initializeBase(this);
    this._uiElement = uiElement;
    this._postPage = "InlineEditHandler.aspx";
    this._otherVars = "";
    this._editMode = false;
    this._spanToEdit = null;  
    // ChangeDisplay Delegate
    this._changeDisplayDelegate = Function.createDelegate(this,
        this.ChangeDisplay);
}

As you can see, a new namespace has been created then the constructor of the inline-edit class is defined. The AJAX class is based on a UI element that is passed through the constructor. This UI element is the element that will be converted into an inline Textbox or TextArea as we will see later in this article.

The _postPage private member is the page that will be used to post to it and it will handle saving the changed text either to an XML file or database table.

The _editMode private member represents the status of the UI element whether it is in an edit mode or read mode.

The _spantoEdit private member holds the ID of the span HTML tag on the page.

Finally, the _changeDisplayDelegate is created to handle execution of a function, called ChangeDisplay, in the same context of the AJAX object that executed it.

Now it is time to add functions and properties to the prototype of the AJAX class. Listing 2 shows all the properties added to the AJAX class.

Listing 2

    // Define uiElement Property
    // This property is used to hold the ID of the UI
    // control that is to be edited inline
    get_uiElement:function() {
        // Get
        return this._uiElement;
    },
    set_uiElement:function(value) {
        // Set
        this._uiElement = value;
    },
 
    // Define postPage Property
    // The page to post to that will handle
    // saving the text typed on the page into a
    // data store
    get_postPage:function() {
        // Get
        return this._postPage;
    },
    set_postPage:function(value) {
        // Set
        this._postPage = value;
    },
 
    // Define otherVars Property
    // This variable is used to supply additional
    // variables to the postPage
    get_otherVars:function() {
        // Get
        return this._otherVars;
    },
    set_otherVars:function(value) {
        // Set
        this._otherVars= value;
    },
 
    // Define editMode Property
    // This variable is used to keep track of 
    // editing mode of the _uiElement
    get_editMode:function() {
        // Get
        return this._editMode;
    },
    set_editMode:function(value) {
        // Set
        this._editMode = value;
    },
 
    // Define spanToEdit Property
    // This property is used to hold the span control
    // that is going to be edited
    get_spanToEdit:function() {
        // Get
        return this._spanToEdit;
    },
    set_spanToEdit:function(value) {
        // Set
        this._spanToEdit = value;
    },

There is nothing special in the above code. For each private member a set/get function has been added. As you know, in AJAX there are no properties and hence the need to create two separate functions, one for the set and one for the get.

The brain of the inline-edit AJAX class is the EditBoxInit function that is shown in Listing 3.

Listing 3

    // This method parses the HTML page, get all spans with class "editText",
    // then configures each span to be clickable and editable
    EditBoxInit:function ()
    {
          if (!document.getElementsByTagName){ return; }
          var spans = document.getElementsByTagName("span");
    
      // loop through all span tags
      for (var i=0; i<spans.length; i++)
      {
                var spn = spans[i];
                if (spn != null)
                {
                // if the span has a class with name "editText", then
                // configure it
                if (((' '+spn.className+' ').indexOf("editText") != -1) && (spn.id)) 
                    {
                    this._spanToEdit = spn;
                    $addHandler(spn, 'click', this._changeDisplayDelegate);
                    
                          spn.style.cursor = "pointer";
                          spn.title = "Click to edit ...";  
                    }
                }
          }
    },

What this method does is parse the HTML of the Web Form, collects all span HTML tags that have a class named "editText" and then for each span it finds under that category, it adds a click event using the $addHandler shorthand syntax provided by the AJAX client library. Using that method requires you to specify the HTML control, the event name, and the delegate that holds a reference to the function to be executed on the firing of the event. Finally, the method adds a title and styles the cursor whenever it hovers over the editable span.

When the user clicks on the editable span, the ChangeDisplay function has to be fired. This function is displayed below.

Listing 4

// This method changes the display from a span tag
// into a textbox for the user to use to add the new
// text
ChangeDisplay: function() 
{
      spn = this.get_spanToEdit();
      if (!this.get_editMode())
      {
            width = Sys.UI.DomElement.getBounds(spn).width + 20;
            height = Sys.UI.DomElement.getBounds(spn).height + 2;
            
            if(width < 100)
                  width = 150;
            if(height < 40)
                  spn.innerHTML = "<input id=\"" + spn.id +
                        "_field\" style=\"width: " + width + 
                        "px; height: " + height + 
                        "px;\" maxlength=\"254\" type=\"text\" value=\"" + 
                        spn.innerHTML + 
                        "\" onkeypress=\"return FieldEnter(this,event,'" + 
                        spn.id + "')\" onfocus=\"HighLight(this);\" " + 
                        " onblur=\"NoHighLight(this);" +
                        " return FieldBlur(this,'" + spn.id + "');\" />";
            else
                  spn.innerHTML = "<textarea name=\"textarea\" id=\"" + spn.id + 
                        "_field\" style=\"width: " + width + 
                        "%; height: " + height + 
                        "px;\" onfocus=\"HighLight(this);\"" + 
                        " onblur=\"NoHighLight(this); return FieldBlur(this,'" 
                        + spn.id + "');\">" + spn.innerHTML + "</textarea>";
      
          this._editMode = true;
    }
    spn.firstChild.focus();
},

The function checks first to see if the script is in edit mode or not. The width and height of the editable areas are calculated using the AJAX Client Library DOM methods. Then based on the width of the editable content, a Textbox or TextArea containing the span’s content is to be displayed inside the span HTML. That is it. Now the editable span, instead of holding directly the static text, it holds a Textbox that in turn contains the text to be edited!

In case the editable text is placed in a Textbox, a set of events should be handled, mainly the onkeypress, onfocus, and onblur.

When the text is edited inside the Textbox either an Enter hit or just removing the cursor from over the Textbox would cause the text to be updated in configured data store which might be an XML file or database table.

When an Enter is hit while editing the text, the FieldEnter function has to be executed and this function is shown in Listing 5.

Listing 5

    // This method handles a keypress event inside the
    // editable area and fires a WebRequest to the server
    // to update the edited text in the data store
    FieldEnter: function(ctrl, event, fieldID) 
    {
          event = (event) ? event : window.event;
          if (event.keyCode == 13 && ctrl.value != "") 
          {
            // Execute a POST asynchornous request
            this.UpdateDataStore($get(fieldID), ctrl);
            
                // remove glow
                NoHighLight($get(fieldID));
                        
                // Page is not in editing stage
                this._editMode = false;
                return false;
          } 
          else {
                return true;
          }
    },

This function takes as input the span ID together with the event object. Then a check is done to determine if an Enter key was hit and accordingly the UpdateDataStore is called. The UpdateDataSource function is shown below.

Listing 6

    // This method is responsible to contact the server
    // and update the edited text in a data store
    UpdateDataStore: function(elem, ctrl)
    {
        // Instantiate the WebRequest object.
        var webRequest =  new Sys.Net.WebRequest();
 
        // Set the request Url.
        webRequest.set_url(this.get_postPage()); 
         
        // Set the request verb.
        webRequest.set_httpVerb("POST");
    
        // Encode the content before sending it to the server
        var encodedContent = escape(ctrl.value);
        encodedContent= encodedContent.replace(/\//g,"%2F");
        encodedContent= encodedContent.replace(/\?/g,"%3F");
        encodedContent= encodedContent.replace(/=/g,"%3D");
        encodedContent= encodedContent.replace(/&/g,"%26");
        encodedContent= encodedContent.replace(/@/g,"%40");
 
        var body = "fieldName=" + escape(elem.id) + "&content=" + encodedContent;
        if (this.get_otherVars() != "")
            body = body + "&" + this.get_otherVars();
            
        webRequest.set_body(body);
        webRequest.get_headers()["Content-Length"= body.length;
         
        // Set the web request completed event handler,
        // for processing return data.
        // Make sure to add the createDelegate so the complete method will run
        // under the same context of this class instance, means being able to
        // accesss properties on this instance of the class
        webRequest.add_completed(Function.createDelegate(this, 
            this.OnUpateStoreCompleted));
        
        // Execute the request.
        webRequest.invoke();  
    },

The above method creates a new WebRequest using the AJAX Sys.Net.WebRequest. Then it sets the URL to post to, specifies the request is a POST request, gets the edited text, encodes it in case it contains any HTML tags, and sets the body of the request. Before invoking that request, the request has been configured with a Completed function to execute once the response is back. Finally, a call to invoke the request is done.

The OnUpdateStoreCompleted function executes when the response is back from the server. The code for this function is shown below.

Listing 7

// This the handler for the Web request completed event
// that is used to display return data.
OnUpateStoreCompleted: function(executor, eventArgs)
{
  if (executor.get_responseAvailable())
  {
    var result = executor.get_responseData();
    $get(this.get_uiElement()).innerHTML = result;
  }
  else
  {
    if (executor.get_timedOut())
      alert("Request Timed Out. Sorry for the inconvience");
    else
      if (executor.get_aborted())
        alert("Request Aborted. sorry for the inconvience");
  }
}

The method will check if there is a response, then it retrieves the data sent back from the server, and updates the editable span on the page with the received response data. If on the other hand there was any problem processing the request, an alert popup will be shown to the user.

Finally, the AJAX class has to be registered.

Listing 8

// Register the class
bhaidar.CodeSuite.AJAX.InlineEdit.registerClass("bhaidar.CodeSuite.AJAX.InlineEdit");
How to use the Inline-Edit AJAX class

Now that the AJAX class has been created, it is time to test it on a Web Form. The first thing to do is add a new ScriptManager and load inside the Script Reference section the AJAX class created above. You will end up with something like this:

Listing 9

<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="InlineEdit.js" />
</Scripts>
</asp:ScriptManager>

Now to enable editable areas on the page, add the following span tag.

Listing 10

<span class="editText" id="txtName"><h1>Inline-Edit with AJAX 1.0 Extensions! </h1></span>

You will also need to attach to the pageLoad event of the Application class that is part of the AJAX Extensions Client Library.

In the pageLoad you will create a new instance of the inline-edit AJAX class so that all the editable spans are configured for editing.

The pageLoad function body is shown in Listing 8.

Listing 11

var inlineEdit = null;
function pageLoad(sender, args) {
    // Create a new instance of the class
    inlineEdit = new bhaidar.CodeSuite.AJAX.InlineEdit("txtName");
 
    // Initialize the InlineEdit
    inlineEdit.EditBoxInit();  
}

A new instance of the Inline-Edit AJAX class is created and the EditBoxInit() function is fired. Now you are ready to test your Web form in the browser and try to edit the text on the spot.

Figure 1 shows the Web form in its read-only original state.

Figure 1

Figure 2 shows the Web Form with a click is done on the editable span. As you can see, the text that was first inside the span is now displayed in a Textbox on the page. Once an Enter key is done, you will see how the Web form now shows the new edited text.

Figure 2

References

To start learning Microsoft ASP.NET 2.0 AJAX Extensions 1.0 it is strongly recommend that you start reading the AJAX documentation. This should be your first reference. In addition, you can visit the official website of ASP.NET and download all of the videos there created by Joe Stagner on the AJAX and AJAX Toolkit. Finally, there are several MSDN web casts that are worth watching. Rob Bagby, Microsoft Developer Evangelist, lately delivered a series of web casts on the Client Script side of AJAX. To find out more, please check out his blog.

In addition, a new book called "Beginning ASP.NET 2.0 AJAX" by WROX is extremely recommended and can be reached here.

Downloads
Conclusion

This article started by discussing the need for inline-edit control. Then a background history on the original inline-edit script was given. The article continued by explaining all the details required to show you how the inline-edit AJAX class was written based on the AJAX 1.0 Extensions.

Hope you enjoyed this article and benefited from the information presented. If you have any questions or comments please feel free to contact the author directly at bhaidar@gmail.com.

Happy Ajaxified Dot Netting!!



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-18 1:42:53 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search