Inline editing with DB write : 'REAL' AJAX with Asp.Net Series

Writing to the database inline without a postback, simple and effective

This is a continuation of my 'REAL' AJAX with Asp.Net (not Asp.Net AJAX) series posts for those of us trying to stop relying on Asp.Net 'AJAX'.

This is the first example of ajax I am showing with a write to the DB, and this will show just how easy it really is. I am building on the last post (GridView Sorting/Paging : 'REAL' AJAX with Asp.Net Series) which will explain where/how the data and display is set up.

Also, you will notice that the CSS changed a bit, that is because this plugin has a hover property that resets the backgorund of the td, and that gave a funky interface; now this can be taken care of with some jQuery magic pretty easily, but that is outside the scope of what this is trying to show.

load all of your js

I am still using jQuery and the extension dataTables but for this lesson I am using an additional plugin: inPlace. So now our script loading looks like this (notice I moved the script refs into the masterpage in this lesson):

demo.master

<script type="text/javascript"
  src="js/jquery.js"></script>
<script type="text/javascript"
  src="js/jquery.dataTables.js"></script>
<script type="text/javascript"
  src="js/jquery.inplace.js"></script>


decide what you want to be editable

Now, since we are using our Repeater table from the last example, we just modify if ever-so-slightly to make it editable, to do that, we just add the class 'editable' (or whatever you want it to be) to each td that we want to be editable. In addition to adding a class, we are going to add meaningful ids to each of the cells, each ID will contain:
  • First 4 Letters - What field is being edited
  • Following digits - 'person_id' that is being edited

if you are unsure as to why we are doing this, keep reading, it will become clear.

inline_edit.aspx

<asp:Repeater ID="rpt" runat="server" DataSourceID="lds">
  <HeaderTemplate>
    <table id="sort_table">
      <thead>
        <tr><th>First</th><th>Last</th><th>Age</th></tr>
      </thead>
      <tbody>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td id="frst<%#Eval("person_id")%>" class="editable">
        <%#Eval("first_name")%>
      
</td>
      <td id="last<%#Eval("person_id")%>" class="editable">
        <%#Eval("last_name")%>
      
</td>
      <td id="age_<%#Eval("person_id")%>" class="editable">
        <%#Eval("age")%>
      
</td>
    </tr>
  </ItemTemplate>
  <FooterTemplate>
    </tbody></table>
  </FooterTemplate>
</asp:Repeater>
<asp:LinqDataSource ID="lds" runat="server"
  ContextTypeName="demoDataContext" TableName="persons" />


make them editable

Now just add in a a little jQuery magic, and the fields will be editable:

inline_edit.aspx
$(function() {
    $("#sort_table").dataTable();
    $(".editable").editInPlace({
        url: "ajax_functions/update.aspx",
        params: "ajax=yes",
        value_required: true,
        default_text: "click to edit"
    });
});

You can look on the documentation for jquery.inplace.js for a further explanation, but what we declared there is that all items that have class 'editable' will now be editable; also, requests will get sent to 'ajax_functions/update.aspx' (which we haven't made yet) and we are requiring a value.

handling the ajax

Ok, so what is happening now, is if you click on a cell you will be able to edit it, and when you click off, or hit enter (you can edit these behaviors if you want), a POST will be sent to 'ajax_functions/update.aspx'. What is sent to the page is the following values:
  • update_value - the value you edited
  • element_id - the element id that was edited
  • original_html - value from before your edit

Now we only care about the first two in this example, but the third value could also be useful given the situation; possibly returning the old value if an error occurs? Also, it may be easier to see why we included both the field and the person_id in the ID of the <td>.

For handling, you could easily have seperate pages that only handle a certain element, i.e. ajax_functions/first_name.aspx for first_name, ajax_functions/last_name.aspx for last_name, etc. but I found that if you did it that way, you ended up writing the same code over and over - so what I did was combine it into a single update handling page. That is why I include 'what' is being updated in the id.

When you make your handling page, it is important that there is no html in it to start with - as the page text itself will be what is stuffed back into the area that you edited. This is the ENTIRE ajax_functions/update.aspx page:

ajax_functions/update.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="update.aspx.cs" Inherits=ajax_functions_update" %>


Anything we want to appear we will just dump out a Response.Write() for. Here is the handling code, I will explain afterwards:

ajax_functions/update.aspx.cs
using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;

public partial class ajax_functions_update : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        demoDataContext db = new demoDataContext();
        // this is unneccessary, but more efficient since there will 
        // be more than 1 db call, this uses the same connection
        SqlConnection con = new SqlConnection(
            ConfigurationManager
            .ConnectionStrings["demoConnectionString"].ConnectionString);

        try
        {
            // get the new value
            string newValue = Request.Form[0]; 
            // figure out what is being edited (remember, its the first 4 chars in the id)
            string what = Request.Form[1].Substring(0, 4);
            // get the person_id of the changing value (the remaining digits)
            int person_id = Convert.ToInt32(
                Request.Form[1].Substring(4, Request.Form[1].Length - 4));

            con.Open();
            // get the record you want to deal with
            person p = db.persons.First(x => x.person_id == person_id);

            // change the value depending on 'what' was sent
            switch (what)
            {
                case "frst": p.first_name = newValue; break;
                case "last": p.last_name = newValue; break;
                case "age_":
                    try { p.age = Convert.ToInt32(newValue); }
                    catch { throw new Exception("not an int"); }
                    break;
                default: throw new Exception("nothing saved");
            }
            db.SubmitChanges();
            con.Close();
            Response.Write(newValue);
        }
        // this will catch all the errors and output them to the edited field
        catch (Exception ex) { Response.Write("Error: " + ex.Message); }
        finally { con.Close(); }
    }
}

First off, the code simply sets the DataContext and opens a SqlConnection (it is explained why in the code). Then, we pull from the POST values from the Request. We pull 3 things from this:
  • person_id - 'person_id' that is being edited
  • what - what field is being edited
  • newValue - the new value for the update

Now is the easy part, get the 'person' to edit, run a switch on 'what' and and update it to 'newValue'. I caught all errors and output them to Response.Write() as that is all the user will be able to see. Also, whatever is written is returned so it integrated seamlessly.  What the user will see is 'Saving...' (unless you change the text or substitute an image) and when it is complete, they will see the new value in place of the old value (which is now written to the DB) as that is what was put in the Response.Write() (if there are no errors, otherwise they'll see the error message).

There you have it! A 'real' ajax inline update with asp.net, and it was as painless as can be! There are all sorts of other things you can do like apply a js function after the update has completed, add in a nice loading graphic instead of the text, etc. - fun to play around with.

Keep in mind with this, if a user (hacker) realizes how it works, they would be able to fabricate a POST to send to your page and update it how they see fit; so be sure you test, protect against that. In one of my apps that uses this. I make sure that the record being edited belongs to the user currently logged in before they can update.

Next will be deleting a row in this table with ajax.



but...

If I have 3 'people', with last names, 'a', 'b', and 'c', and edit 'b' to now be 'z', it will not sort correctly; 'z' will not be the last one in the table, it will still be 'c'. That is because the table data that does the sorting is not held within the table itself, but in an array of 'nodes'.

I left that as a seperate download because this part dives a little deeper into the relation of the sort/edit. What needs to be done is we have to go into the array that holds the nodes, and change the related data along with the represented data in the table.

how do I do that?

This one might require reading a few times, so bear with me. First you need to set the global variables we will be using:
var oTable;
var aPos;
var editedCell;

Then, you will need to store your table in memory:
oTable = $("#sort_table").dataTable();

Now you need to intercept the click in any editable field, and get the position of it in memory; also, we will store the edited cell into a variable as well:
$(".editable").click(function() {
    aPos = oTable.fnGetPosition(this);
    editedCell = $(this);
})

What is now in aPos is a 2-element array [int row_index, int cell_index]; editedCell is the cell that you just clicked. At this point we have all the necessary values to plug the data back in. So next we tack the '.editable()' on to the end of the previous 'click()' call and add a 'success' parameter that will fire on success of the edit. Here is the completed js:

inline_edit.aspx
var oTable;
var aPos;
var editedCell;
$(function() {
    $(".editable").click(function() {
        aPos = oTable.fnGetPosition(this);
        editedCell = $(this);
    }).editInPlace({
        url: "ajax_functions/update.aspx",
        params: "ajax=yes",
        value_required: true,
        default_text: "click to edit",
        success: function() {
            var data = oTable.fnGetData(aPos[0]); 
            data[aPos[1]] = editedCell.html();
        }
    });
    oTable = $("#sort_table").dataTable();
});

Now, the table will re-sort correctly, it's a little extra work, but the added benefit is worth it IMO. Here is the download with the extended functionality (it also has the next demo in it):

Shout it

GridView Sorting/Paging : 'REAL' AJAX with Asp.Net Series

Who knew this could be so easy... and FAST?

This is a continuation of my 'REAL' AJAX with Asp.Net (not Asp.Net AJAX) series posts for those of us trying to stop relying on Asp.Net 'AJAX'.

Ok, nothing too dramatic to start things off, we are going to make some tabled data sortable and pagable all without using a bit of postback. Not only that, but it is going to be incredibly easy!

First off we need the data that these demos will be working with, nothing complicated, just a simple SQL table 'person' that holds peoples' names and ages:

setup.sql
CREATE TABLE dbo.person (
person_id INT NOT NULL PRIMARY KEY IDENTITY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
age INT NOT NULL
);

Also included in the setup.sql file is some dummy data to populate it initially. We ill be using a Linq as our datasource throughout with a .dbml file named demo.dbml.

Next we need to display the data. Normally if I wanted to do paging, I would use a GridView, due to the fact is is already integrated. But that integration is sloooow, and requires a postback - we are ajax'ing here! What we are going to do will load all the data (which could be slower initially on large data sets) and use jQuery to take care of all of the lifting for us. So, it is much more efficient for us to use a Repeater. Without postbacks, all the advantages of a GridView quickly fade away. You will see how little markup you need:

sort_page.aspx

<asp:Repeater ID="rpt" runat="server" DataSourceID="lds">
  <HeaderTemplate>
    <table id="sort_table">
      <thead>
        <tr><th>First</th><th>Last</th><th>Age</th></tr>
      </thead>
      <tbody>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td><%#Eval("first_name")%></td>
      <td><%#Eval("last_name")%></td>
      <td><%#Eval("age")%></td>
    </tr>
  </ItemTemplate>
  <FooterTemplate>
    </tbody></table>
  </FooterTemplate>
</asp:Repeater>
<asp:LinqDataSource ID="lds" runat="server"
  ContextTypeName="demoDataContext" TableName="persons" />


That is all the markup it takes, no code-behind. Now just call the javascript magic of the combination of jQuery and the extension dataTables:

sort_page.aspx
$(function() {
    $("#sort_table").dataTable();
});

And just like that you have a full sortable (with flipping sorting images), filterable, sizable, pageable and 'pretty' table using a simple Repeater. Now, I guess this isn't truly ajax, as nothing is truly pulled from the data store after the initial pull, but I argue that it is *relatively* because if you were to use a GridView jumping pages would cost a postback each time.

This is just the introduction here, but it is to show you how incredibly easy it is to get real, time-saving ajax and it is not as intmidating as you think. Next I will be showing you how to do inline editing of this table.

Shout it Update »

'REAL' AJAX with Asp.Net (not Asp.Net AJAX) Series : Building a complete ajax CRUD system with Asp.Net

Am I the only one who feels guilty every time I throw an 'UpdatePanel' into my code?

We all know Asp.Net AJAX is technically ajax, but it generally passes one the main advantage of using ajax in the first place.

Sure ajax is slick for user interface, but where I feel it really helps is speed. For example, if you want to edit a row in a GridView, you can easily do this using the GridView, stick it in an UpdatePanel and poof... you have an 'ajax' interface. But, and this is a huge but, the *ENTIRE* GridView was actually pulled from the DataSource, not just the row you were using. Asp.Net AJAX is a great tool, but it sort of masks (nearly) complete postbacks as being asynchronous; which is extremely convenient for quick development, but does not really help in the realm of performance.

Basically, I look at Asp.Net AJAX as a lazy way to do 'ajax' - that's in quotes as it really isn't asynchronous. So, lately, I have been making it my mission to get familiar with jQuery and integrating *real* ajax into my projects; and the speed gains are extremely noticable and quite impressive! Now jQuery is not necessary, but I am waaay to lazy and unskilled to write raw JS to do what I want, plus people have already written amazing jQuery plugins to do tons of what I want; not to mention it is probably written better than I could do anyway.

So, I am going to be posting a series of Asp.Net with 'real' ajax tutorials and examples in the coming weeks. I am going to be recreating all the functionality that you can get out of a GridView normally with edit, delete, new, sort, page etc. - a full CRUD (Create, Read, Update, Delete) system; but it will all be true ajax and very fast. Here are the topics that will be covered:
So stay tuned, I think you will be really impressed with how easy, and how much faster 'real' ajax is.

Shout it kick it on DotNetKicks.com

Making a registration system with Asp.Net and Linq-to-SQL (part 3)

Now that it's all up and working, we can make it friendlier and add some cool AJAX effects

After part 2 the system works just fine, but I wanted to take it a step further.This will be the last entry in this series, which I will follow up with a tutorial on how to retrieve passwords and log the registered users in.

what are we going to accomplish?

Like I said before, the system works, this is just the frosting on the cake, we are going to add some jquery and use the MasterPage to make this more accessible to the users.

markup

On the MasterPage, I added quite a few things, and on the registration page I added one key element:

demo.master
<h1>
  <span class="right">
    <a href="default.aspx">Home</a>
    <a href="register.aspx" class="triggerRegister">Register</a>
  </span>
  Registration Demo
</h1>

<div><asp:ContentPlaceHolder id="body" runat="server" /></div>

<div id="footer">
  <a href="default.aspx">Home</a> |
  <a href="register.aspx" class="triggerRegister">Register</a>
</div>

<div class="jqmWindow" id="register">
  <h3>
    <asp:UpdateProgress ID="uppRegister" runat="server">
      <ProgressTemplate>
        <div class="status">working...</div>
      </ProgressTemplate>
    </asp:UpdateProgress>
    <a href="#" class="x jqmClose">X</a>
    Register
  </h3>
  <cc:register ID="ccRegister" runat="server" />
</div>

register.aspx
cc:register ID="reg" runat="server" in_page="true" />

First of all, you have to realize, since the <div id="register" ... > has a CSS class of 'jqmWindow, it will not be visible when the page loads. This is because it is going to be within a modal popup window. Also, you will notice that there is a <cc:register ... > control within. That is what causes the small change to register.aspx as the attribute 'in_page' is added.What this does is elimiate errors that may occur if two or more of these controls are on a single page, so the validators only validate the controls they are pertinant to. The code is in the Utils.cs file if you would like to examine it.

I am also using an UpdatePanel within the modal so the user is able to see their feedback; if it wasn't (or something similar) used, the modal would be hidden after postback.

Also, some links with the class 'triggerRegister' are added, these will be the links that will trigger the modal popup (using jqModal) with the following JS:

demo.master
$('#register').jqm({ trigger: false }).jqmAddTrigger($('.triggerRegister'));

And just that simply we made the registration available multiple ways across the entire project! If the user has javascript turned off, it will will still work just fine as we have a 'backup' register.aspx page that will handle the request.Ahh the beauty of jQuery.


« Part 1« Part 2

Making a registration system with Asp.Net and Linq-to-SQL (part 1)

This registration has a slick interface and user verification

NOTE* I do not cover encryption in this tutorial, but I highly discourage storing plain-text passwords in your DB!

It is inevitable that every programmer will want to eventually make a site which requires registration. Then you need to deal with spam accounts and all that good stuff. This is part one of a series of tutorials, where I will show you how to set up a registration process that requires a valid email address. I will be building on the code provided here for the next tutorial and so on. In the future, I will also include a login process I developed that will lock out accounts after a certain amount of attempts, retrieve passwords, and all sorts of other goodies. But before users can log in, they have to register.

I will be using a lot of other people's stuff in this example, such as jQuery, jQuery extensions, Grid960 and so on as well as a lot of my own Extensions, etc. With that said, this is going to have a lot of 'extras' included such as Ajax functionality and some UI niceties to make it a quality interface - you can feel free to cut these parts out, but I feel it will be nice for those that want it. All of the code referenced is included.

Storage

The first step is setting up your user table in the database. The most important thing to think of here is: what am I going to need to collect? I am all about being as simple as possible, so I am going to require two things: email and password - that is it. This is what I came up with:
  • userid - the primary key integer
  • email - the user's email
  • password - user's password
  • guid - guid for verification
  • created - date created; both for record keeping and to see if it was not confirmed after a long time it can be removed
  • confirmed - whether or not it is confirmed
  • last try* - the last login
  • number of failed logins* - number of failures for lockout

The two starred items will not really be used in this too tutorial and are optional if you do not want to prevent unlimited login attempts; though they will be relevant in upcoming tutorials.

Here is the SQL to create my table for users:
CREATE TABLE dbo.users (
userid INT NOT NULL PRIMARY KEY IDENTITY,
email VARCHAR(100) NOT NULL UNIQUE,
password_ VARCHAR(30) NOT NULL,
guid_ UNIQUEIDENTIFIER NOT NULL UNIQUE,
created DATETIME NOT NULL,
confirmed BIT NOT NULL DEFAULT 0,
last_try DATETIME NOT NULL,
tries INT NOT NULL DEFAULT 0
);

Markup

Now that we have our table, go ahead and drag it into a dbml - for this example, I will use one named db.dbml. Now we have our access layer built, we can work on making a registration control; I will be making an ascx registration control, so it can be plugged in aywhere I want to use it. Since I am only collecting two bits of information, this will be a simple control. Here is the markup, I will explain it afterwards:

register.ascx
<asp:UpdatePanel ID="upContact" runat="server">
  <ContentTemplate>
    <div class="pad">
      <asp:Panel ID="Report runat="server" />
      <asp:Panel ID="pnlRegister" runat="server" DefaultButton="registerSubmit">
        <div class="pad_sides">
          <div>
            <h4>
              <asp:RequiredFieldValidator ID="rfvRegisterEmail" runat="server" CssClass="validate" ValidationGroup="register"
                ControlToValidate="registerEmail" ErrorMessage="required" Display="Dynamic" />
            <asp:RegularExpressionValidator ID="regRegisterEmail" runat="server" ControlToValidate="registerEmail"
                ErrorMessage="invalid email" CssClass="validate" Display="Dynamic" ValidationGroup="register"
                ValidationExpression="^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"
            />
              email
            </h4>
            <asp:TextBox ID="registerEmail" runat="server" CssClass="inputBig full" />
          </div>
        <div>
          <h4>
            <asp:RequiredFieldValidator ID="rfvRegisterPassword" runat="server" CssClass="validate" ValidationGroup="register"
                ControlToValidate="registerPassword" ErrorMessage="required" Display="Dynamic" InitialValue="8 character minimum" />
            <asp:RegularExpressionValidator ID="regRegisterPassword" runat="server" CssClass="validate" ValidationGroup="register"
              ControlToValidate="registerPassword" ErrorMessage="must be at least 8 characters" Display="Dynamic"
              ValidationExpression="^.{8}.*$" />
            password
          </h4>
          <asp:TextBox ID="registerPassword" runat="server" CssClass="inputBig full wm watermark" Text="8 character minimum" />
        </div>
        <div class="summary field">
          <asp:LinkButton ID="registerSubmit" CssClass="button"
            Text="submit" runat="server" ValidationGroup="register" onclick="registerSubmit_Click" />
          </div>
        </div>
      </asp:Panel>
    </div>
  </ContentTemplate>
</asp:UpdatePanel>

Ok, there is a lot going on here, so I will go part by part.

First of all, you will notice that it is within a Asp.Net UpdatePanel which I have been trying to get away from for most things, but for such small controls I have found that is is the best way to go about it: easy and fast.

Next you will see that I have added a Panel with an ID of "Report" - I use this as a standard in most applications as to where to output my 'updates' to the user. This is explained here. The code for this is included in the Extensions.cs file.

Next there is a good amount of validation going on.
  • First I use RequiredFieldValidators for both fields
  • Then I added the RegularExpressionValidator for emails
  • Then I added the RegularExpressionValidator for password length
  • Finally you will notice that the password entry has a watermark which is called via jQuery in the MasterPage

You might notice that I am not using a password field or asking for password verification. This is something you might want to do, but for this example, security is not really a concern, simplicity is; so I figure if you can see your password, you wont screw it up. Also, since we will be adding a password retrieval function, this won't be a big deal.

Backend

That is the markup, but now we have to go to the code so it actually does something. Now what does this have to accomplish?
  • Check if the Email has already been registered
  • Create a new entry in the users table
  • Send an email with a verification link

Not too much going on here, here is the code for accomplishing that, followed by an explanation:

register.ascx.cs
using System;

public partial class controls_register : System.Web.UI.UserControl
{
  protected void Page_Load(object sender, EventArgs e)
  {
    if (this.Attributes["in_page"] != null)
    {
      Utils.DuplicateValidators(this);
    }
  }

  protected void registerSubmit_Click(object sender, EventArgs e)
  {
    try
    {
      dbDataContext db = new dbDataContext();
      if(Users.DuplicateEmail(db, registerEmail.Text))
        throw new Exception("email already registered");
      Guid g = Guid.NewGuid();
      user u = new user()
      {
        created = DateTime.Now,
        email = registerEmail.Text,
        guid_ = g,
        password_ = registerPassword.Text,
        last_try=DateTime.Now
      };
      db.users.InsertOnSubmit(u);
      db.SubmitChanges();
      Email email = new Email(registerEmail.Text, Settings.Get("gm"),
        "please verify your email address",
        "http://yoursite.com/confirm.aspx?guid=" + g.ToString()); //we will get to this in the next tutorial
      email.Send();
      Report.Success("account successfully created", "please check your email to verify your account");
      pnlRegister.Visible = false;
    }
      catch (Exception ex)
    {
      Report.Error(ex);
    }
  }
}

The first thing that happens here is the check for if the Attribute "in_page" is set. This is a bit of a sidebar as it just takes care of duplicate validators if there is more than one of these controls on the page, since I plan on showing how to use them both as a modal popup as well as a standalone page I had to add this check; that way, if you are filling out the popup instead of the form on the page it makes sure that it will not fire the validation for the form you are not using, all it does is change the validation group. The code is visible in the Utils class if you are curious about it. Don't really worry about this too much right now, as it will be covered in an upcoming tutorial.

Next it checks if the email is a duplicate. This calls the Users.cs class, we will get to that next; just remember for now it returns true if it is already in the system, false if not.

If it is new, a new user is then made and inserted into the DB via Linq-to-SQL.

An email is made and sent to the user with the link to the authorization page (which will be coevered in the next tutorial). This is sent using a simplified Email class. The authorization is the guid which was produced - I will cover the authorization page in the next part of the tutorial.

Then the user is notified of the status whether it is success or error using the panel reporting extensions.

This is all pretty simple, all that is left is to explain what is going on in the Users.cs class which is also simple:

Users.cs
using System.Linq;

public static class Users
{
  public static user GetFromEmail(dbDataContext db, string email)
  { return db.users.First(u => u.email.ToLower().Equals(email.ToLower())); }

  public static bool DuplicateEmail(dbDataContext db, string email)
  {
    try
    {
      user temp = GetFromEmail(db, email);
      span class="var">return true;
    }
    catch { return false; }
  }
}

As you can see, this is just two basic LINQ queries, the first one retrieving a user object based on an email string. And the duplicate check which tries to find a user with the given email, if it can, it will return true, meaning it is already in there, otherwise it spits out a false.

And that is all there is to it so far. It is not yet a working system as the user has not verified their identity, but we have accomplished the base of a registration system:
  • Collected the user's email address
  • Collected their password
  • Produced a unique Guid for verification
  • Sent them an email to verify their identity

Now we have it all built, we just need to display everything and call the necessary scripts. I am going to stick all of these pages within a masterpage which calls the scripts in the Page_Load:

demo.master.cs
protected void Page_Load(object sender, EventArgs e)
{
  Page.ClientScript.RegisterClientScriptInclude(typeof(demo), "jQuery", ResolveUrl("~/js/jquery.js"));
  //this will be used in the next tutorial
  Page.ClientScript.RegisterClientScriptInclude(typeof(demo), "jQuery", ResolveUrl("~/js/jqModal.js"));
}

Then just call the control (registered in the web.config file) and the js in the markup:

register.aspx
<h2>Registration</h2>
<cc:register id="reg" runat="server" />

and call the watermark frorm jQuery:

demo.master
<script type="text/javascript" language="javascript">
   $().ready(function() {
     swapValues = [];
     $(".wm").each(function(i) {
       swapValues[i] = $(this).val();
       $(this).focus(function() {
         if ($(this).val() == swapValues[i]) {
           $(this).val("").removeClass("watermark")
         }
       })
     })
   });
</script>

Notice that I am calling the watermark in the masterpage. This may seem strange, but this stops me from writing redundant code as this will take care of *all* watermarks that I will put into this project due to the versatiliy of jQuery.

All we have to do to complete this registration process is to verify the email which will be the next part to this tutorial. I am also going to show how to add this into a registration popup. The hard part is all finished.


Shout it » Part 2 » Part 3

Using jquery.autosuggest.js with Asp.Net

Simple Auto-Suggest with Asp.Net and jQuery

After getting fed up with the Ajax Control Toolkit's AutoCompleteExtender and it's inability to deal with strings that are numbers, I decided to look to my new friend jQuery. Apparently they decided for you if you are feeding it an array of number strings (i.e. { "001","002", etc.}) that the auto-suggest will strip all leading zeroes... BUT I NEEDED THOSE ZEROES!

The jQuery solution is pretty simple, much easier than I thought thanks to this awesome plugin: jquery.autocomplete.js. All you really need to do is make a simple aspx page that spits out the data you want based on a QueryString, use a little jquery to tie it up with a TextBox and you are all set. Here is how its done:


Make your data retrieval page

This plugin consumes it's data in one form: text, with one item per line. This makes it very easy to use and very versatile. You could simply point it at a static .txt file, feel it a javascript variable, or, what we are going to do, use Asp.Net to get you some filtered data.

This tutorial is going to use two examples, one pulling from a list of numbers 1-1000, and another pulling form an xml file.

First, the code-behind for number.aspx:
protected void Page_Load(object sender, EventArgs e)
{
  if (!string.IsNullOrEmpty(Request.QueryString["q"]))
  {
    int q = 0;
    if (Int32.TryParse(Request.QueryString["q"], out q))
    {
      for (int i = q; i < 1001; i++)
        if (i.ToString().Contains(q.ToString())) Response.Write(i + Environment.NewLine);
    }
    else
      Response.Write("Not a number fool!");
  }
}

Doesn't get much easier than that... simply writes out any numbers that contain the number (not mathematically, though we could do that) passed in the 'q' QueryString, so if you were to pass the url: number.aspx?q=100 you will get the results:
100
1000

simple.

Now we do the same thing, but dig into an xml file with Linq:
protected void Page_Load(object sender, EventArgs e)
{
  string q = Request.QueryString["q"] ?? string.Empty;
  IEnumerable<string> things = from p in XDocumentLoad(path).Descendants("thing")
        where p.Value.Contains(q) select p.Value;
  foreach(string s in things) Response.Write(s + Environment.NewLine);
}

That was actually the hardest part. Notice that on the Response.Write() I used Environment.NewLine - that will make a newline in the proper format for the jquery to digest, a <br /> or a \n will not work with this plugin. What was made is a psuedo-web-service (it's not really becuase it does not output xml).

Tie it to some TextBoxes

Now just make a couple TextBoxes that will use them:
<asp:textbox ID="txtNumbers" runat="server" />
<asp:textbox ID="txtThings" runat="server" />

Now use jQuery to attach the pages we made to the proper TextBox:

$().ready(function() {
  $("#txtNumbers").autocomplete("number.aspx");
  $("#txtThings").autocomplete("thingXml.aspx");
});

And that's it, you have working auto-suggesters; pretty simple. One thing to notice that can give you some headaches in Asp.Net is that I used the IDs for selection in the code, which is fine if you are not using User Controls or Masterpages, but if you are you get those funky '...ctl100_...' ids that are made at runtime, so you might want to select them with a different method, like making a dummy class and using that as a selector in jQuery

That's about it - but don't forget to style your auto-suggest box or it will just be transparent; there is some basic css showing the classes produced by the jquery in the example. This was just enough to get you started; there is a bunch of documentation and other variables, settings, formatting tricks that you can use (this is a really powerful plugin) - you can read up on them here: http://docs.jquery.com/Plugins/Autocomplete.

IMPORTANT: Remember to delete *everything* on your handling .aspx page other than the '@' declaration so you don't have any extra html in there (I think I left it in there on the download...).


jQuery TextBox Water Mark with asp.net

A jQuery alternative to the AjaxControlToolkit TextBoxWaterMarkExtender

I stole majority of this code from http://www.aspcode.net/A-watermark-texbox-with-JQuery-and-aspnet.aspx but I added a bit to make it swap css classes as well

$().ready(function() {
  swapValues = [];
  $(".wm").each(function(i) {
    swapValues[i] = $(this).val();
    $(this).focus(function() {
      if ($(this).val() == swapValues[i]) {
        $(this).val("").removeClass("watermark")
      }
    }).blur(function() {
        if ($.trim($(this).val()) == "") { $(this).val(swapValues[i]).addClass("watermark") } }) })
});

To use it, make sure your TextBox has (one of) it's css classes set to "wm". If you want a seperate style to be applied add that initially as well, in my example, it swaps "watermark" in and out as a css class.

<asp:TextBox ID="txt" runat="server"
  Text="this is the watermark" CssClass="wm watermark" />

GUI css writer: change your page style and rewrite your css on the fly

I have seen a lot of theme pickers out there, but not one that gives you 100% control like this

While working on a recent project, I had a complaint about the colors... I hate colors and I am no good at picking them, and when I do find some colors that I think are nice, apparently everyone else thinks they are crap.  This is why I truly respect web designers, as that is a true skill.  But to my chagrin I do not have a web designer, so I did the next best thing: get the blame off my back.  That's right, if you think you are so good with colors, why don't you pick them Mr. User?

 

So I went ahead and used the Farbtastic jQuery color picker Plug-in that I recently fell in love with, along with some nice Linq, XML, some good old .Net IO and a dash of clever css writing, and I was able to put together a (almost) fool-proof theme-designer with a friendly GUI.

 

First thing first, I needed both jQuery and the Farbtastic jQuery color picker Plug-in I just mentioned to be downloaded and called in my <head>.  Once I ran the Farbtastic demo to make sure everything was working fine, I set out on my adventure.

 

Next, I had to seperate my css into two distinct sheets, one: main_style.css would be jsut that, the main style; this never changes and is static.  Then, I made another stylesheet: theme.css that will hold my changing data and be re-written.  By using some clever techniques like not relying on any css border properties, I will be able to minimize the amount of code i have to re-write and be able to produce what looks like borders without actually using borders.  So instead of

/*theme.css*/
div.border { border: solid 5px Black; }

<!--html-->
<div class="border">some stuff with a border</div>

 

I will instead use something like this:

/*main_style.css*/
.border { padding:5px; }

/*theme.css*/
.border_color { background-color:Black; }
.content_color { background:White; }

<!--html-->
<div class="border border_color">
  <div class="inner_color">some stuff with a border</div>
</div>

 

These both produce what looks to be the exact same, the difference being that the second one does not actually have a border, it just looks like it with the padding and background color.  Now I know that the second one is more code, but that is the price you pay to have less code in your css and have your website be maintainable.  Once you write teh css writer one time, you will never have to touch the code again.  You can easily incorporate borders into the re-written css if you would like, that is just not the path I am going.

 

Now that that is understood, I can put in the color picker and the related TextBox controls to correspond to what colors I will be changing.  To do that, simply put this isnot your page where you want the picker: <div id="picker"></div> and then add your TextBox controls where you need them; each TextBox is the class 'colorwell' that allows them to be accessed easier by jQuery.  Once that is done, add a Button to submit everything.  So far, mine looks like the picture at the top of the post.  You will have to bind everything with jQuery now:

[code:js]

 <script type="text/javascript" charset="utf-8">
     $(document).ready(function() {
         var f = $.farbtastic('#picker');
         var p = $('#picker').css('opacity', 0.25);
         var selected;
         $('.colorwell')
      .each(function() { f.linkTo(this); $(this).css('opacity', 0.75); })
      .focus(function() {
          if (selected) {
              $(selected).css('opacity', 0.75).removeClass('colorwell-selected');
          }
          f.linkTo(this);
          p.css('opacity', 1);
          $(selected = this).css('opacity', 1).addClass('colorwell-selected');
      });
     });
 </script>

[/code]

 

Now comes the code-behind.  First thing I decided is that I am going to hold the data in an xml file; you could easily do this in a SQL database as well.  I named the file theme.xml and it looks like this:

<?xml version="1.0" encoding="utf-8"?>
<theme>
  <text>#444444</text>
  <borders>#4a4a4a</borders>
  <body>#ffffff</body>
  <links>#ff7700</links>
  <link_hover>#ffa500</link_hover>
  <button_text>#ffffff</button_text>
  <headers>#ffffff</headers>
  <background>#a53c3c</background>
</theme>

 

I populated it with my default color values of what will be changing.  Next, I made a class that will help me interact with the xml using Linq, I named this file xmlHelper.cs and placed it in my App_Code folder:

public static XElement getElement(XElement x, string element)
{ return (from e in x.Descendants(element) select e).First(); }

public static void writeElement(XElement x, string element, string value)
{
    XElement xe = getElement(x, element);
    xe.Value = value;
}

 

Now in my Page_Load I made a Dictionary<string, TextBox> and populated it with all of my TextBox controls and their corresponding xml Element name.  Now each time the page loads fresh, I simply load my values into the TextBox controls like this:

if (!IsPostBack)
{
    foreach (var v in colors)
        v.Value.Text = xmlHelper.getElement(x, v.Key).Value;
}

 

Now every time the page loads, it pulls the values out of the xml file and populates the TextBox controls.  Now that I have that, I need a way to write to the css file and the xml file.  A iadd that to my btnSubmit_Click event.  Once again, I can look through the Dictionary I had set up to this time use my xmlHelper class and write to the xml file.  That is done like this:

protected void btnSubmit_Click(object sender, EventArgs e)
{
    foreach (var v in colors) xmlHelper.writeElement(x, v.Key, v.Value.Text);
    x.Save(themePath);
    //writeCss(); //this will be used in a moment
}

 

Now the xml is written, we need to write the css.  For this I just use the old IO and StringBuilder to write my css and overwrite the old file:

protected void writeCss()
{
    string cssThemeFile = Server.MapPath("~") + "\\css\\theme.css";
    StringBuilder sb = new StringBuilder();
    sb.Append("html{background-color:" + txtBg.Text + ";}");
    sb.Append(".border_color{ background-color:" + txtBorders.Text + ";}");
    sb.Append(".content_color{ background-color:" + txtBody.Text + ";}");
    sb.Append(".header_text{color:" + txtHeader.Text + ";}");
    sb.Append("a{color:" + txtLink.Text + ";}");
    sb.Append("a:hover{color:" + txtLinkHover.Text + ";}");
    sb.Append(".button:hover{background-color:" + txtLinkHover.Text + ";}");
    sb.Append(".button{background:" + txtLink.Text + ";color:" + txtButtonText.Text + ";}");
    File.Delete(cssThemeFile);
    TextWriter tw = new StreamWriter(cssThemeFile);
    tw.WriteLine(sb.ToString());
    tw.Close();
}

 

That will write my theme.css file, and that is that.  Now on every click, the values will be written to the xml file (this is unneccessary, but it loads the previous settings up for your user).  After that, the css file is re-written and immediately used by your page.  This does require that you have write permissions to whatever directory/directories you house your theme.css and theme.xml files in.  This also is easy to implement with each user profile having their own saved style (easier with SQL).  I hope this comes in handy for someone, I love it and have used it on a few projects now.

 

...And now they see it's not soo easy picking colors that actually look good :)

 

 

Amazing jQuery Color Picker

This is by far the smoothest, most compact color picker I have found

 

Looking for a new color picker today, and I cam across this beauty!  The 'Farbtastic' color picker... what a name!  It requires jQuery, but is easily the best of it's kind I have ever found.  It is extremely easy to implement and looks/works great (I really like the fact that it is mroe compact than most). 

 

I just finished making a style customizer for one of our intranet applications that uses this to re-write our css and hence change the theme based on the user input.  This tool was super easy to work with and cut my development time down by a huge margin.  I can't say enough about this plugin!  Hopefully I can get a post up about the online css customizer pretty soon.

 

DOWNLOAD: http://acko.net/dev/farbtastic