Inline-Edit Control Using ASP.NET 2.0 AJAX 1.0 Extensions
page 3 of 7
by Bilal Haidar
Feedback
Average Rating: 
Views (Total / Last 10 Days): 34752/ 85

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");

View Entire Article

User Comments

Title: Glo Vapor Electonic Cigarette   
Name: Chris Fontan
Date: 2010-06-20 12:42:14 PM
Comment:
we used the inline edit in the admin section of our website! It works GREAT!


Electronic cigarettes, 510 ego, tornado, glo stick, ecigarettes, liquid nicotine, long battery life, smokeless cigarettes, healthy cigarette, water vapor, tobacco alternative, stop smoking, quit smoking
www.glovapor.com
Title: thanks   
Name: gasby
Date: 2010-04-09 12:27:13 PM
Comment:
the change does not reflect in the span when the page is refreshed
Title: Not Download   
Name: Adil
Date: 2009-06-11 2:53:58 AM
Comment:
I want to download this arttical but not going to download .please ckeck it.
This is very good idea.
Thanks
Title: using more than 1 region   
Name: Chris Fontan
Date: 2008-09-23 12:49:48 PM
Comment:
is there a little more information on using multiple editable regions?
Title: Cool one   
Name: Habiburahman Khaled
Date: 2007-11-03 3:16:36 AM
Comment:
Thanks great one.
Title: Updates   
Name: Mikhail
Date: 2007-10-18 5:26:01 PM
Comment:
As far as I can see (correct me if I wrong) you can only update one field at a time.

I think it will be much better is to have autimatically generated button , which loops through all the controls on the form and check the class. if class is editText, if submit the ajax update request to the update page and when update is done, then refreshes all controls.
Title: Good Idea   
Name: Worawut Boontan
Date: 2007-10-18 8:14:57 AM
Comment:
Thanks
very nice idea.
Title: Re:   
Name: Bilal Haidar
Date: 2007-10-07 2:21:56 AM
Comment:
Thanks guys, you are full of sense,
Hey check out another version of the above control. In fact this one was based on another script and adding it to a website requires some work, that is why I came up with a new control that is a server control and enables inline edit. I will soon have an article on it, check it out here:
http://bhaidar.net/cs/archive/2007/10/03/asp-net-2-0-ajax-inlineeditlabel-control.aspx

Hope you enjoy it!
Regards
Title: Very Very Cool!   
Name: Mohammad Azam
Date: 2007-10-06 11:39:09 PM
Comment:
Wow! thank is soooo awesome :)
Title: Nice   
Name: Steve
Date: 2007-10-05 4:39:07 PM
Comment:
Very cool!






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2021 ASPAlliance.com  |  Page Processed at 2021-12-08 1:47:35 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search