loads of useful information, examples and tutorials pertaining to web development utilizing asp.net, c#, vb, css, xhtml, javascript, sql, xml, ajax and everything else...

 



Advertise Here
C-Sharpener.com - Programming is Easy!  Learn Asp.Net & C# in just days, Guaranteed!

Creating Nice '|' Divided Menus with CSS

by naspinski 1/8/2011 11:25:00 PM

it is common for websites (this one included) to have the ubiquitous '|' as a link divider, here is a neat way to do it with pure css

To get this menu:

You dont need to actually put in the '|' character, you can do it with just the following advanced css selectors:
<style type="text/css">
	ul#nav li{
		float:left; 
		margin-right:20px;
	}
	
	ul#nav li:after{
		content:'|';
		margin-left:20px;
	}
	
	ul#nav > li:last-child:after{
		content:'';	
		margin-left:0;
	}
</style>

<ul id="nav">
    <li><a href="#">Home</a></li>
    <li><a href="#">Contact</a></li>
    <li><a href="#">FAQ</a></li>
    <li><a href="#">Other Crap</a></li>
</ul>

I realize it's not exactly space-saving, but it is a cool trick that could be adapted to all sorts of possible situations.

Currently rated 3.0 by 1 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

css | html

Inline AJAX DropDown and Text Editing with Asp.Net MVC and jQuery

by naspinski 7/12/2010 5:31:00 AM

including how to use a database to populate the dropdown

First thing is first, you will need to download jQuery and the Jeditable plugin (I prefer to refer to it as the Jedi-Table!). Be sure to put these references in your View (or Masterpage). Next, you have to set up a view on which to use an inline edit. I find that I often want to use this approach on tables of information. For this View, I will set it to use an IEnumerable of an Item I have called 'ItemOwner' (this is arbitrary and does not really matter). It will be a simple table that lists the Name and the Country of the owner, both of which will be editable inline. Here is the Index in my ExampleController.cs:
myDataContext db = new myDataContext();
public ActionResult Index()
{
    // get the info for the 'Countries' dropdown:
    ViewData["countries"] = db.Countries
        .Select(x => new SelectListItem() 
        { 
            Text = x.Name, 
            Value = x.Id.ToString() 
        }).ToJson();

    // get the 'ItemOwners' I am interested in:
    var owners = db.ItemOwners.Take(3);

    return View(owners);
}

As you can see there, I am also pulling the countries from the database and throwing them into the ViewState - we will get to this later. Since the Country is actually a foreign key relation, the value is set to an integer which is the identity field in the database. It is also using a .ToJson() extension which takes a IEnumerable<SelectListItem> and puts it into a simple JSON string that I use which is here:
public static string 
    ToJson(this IEnumerable<SelectListItem> slis)
{
    string output = "{";
    if (slis != null)
    {
        for (int i = 0; i < slis.Count(); i++)
        {    
            output += " '" + slis.Skip(i)
            .First().Value + "': '" + 
            slis.Skip(i).First().Text + "'" + 
            (i == slis.Count() - 1 ? " " : ",");
        }
    }
    return output += "}";
}

There is probably a better way to do that... but I don't know it?!

I am also pulling 3 ItemOwners from the database, I know this is silly, but it just an example. Here is how I am displaying them in the view:
<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Country</th>
        </tr>
    </thead>
    <tbody>
        <% foreach(var owner in Model) { %>
        <tr>
            <td><%= owner.Name %></td>
            <td><%= owner.Country.Abbreviation %></td>
        </tr>
        <% } %>
    </tbody>
</table>

Now that there is a simple table we want to make it a bit more interactive. Since we aregoing to make all of these fields editable, we need to add in a way to distinguish exactly what they are. To do that, we will need two things: the id of the item they are editing, and the type of inline editing we will be doing (i.e. dropdown or text input). So to do that, let's add in a few css classes and an identifieng ID:
<td id="name<%= owner.Id %>" class="editable text">
    <%= owner.Name %></td>
<td id="ctry<%= owner.Id %>" class="editable dropdown">
    <%= owner.Country.Abbreviation %></td>

And now add a little css to make them appear to be clickable:
td.editable:hover 
{ cursor:pointer; background-color:Orange; }

Now they all look like you can click on them, so we can move on to making the click actually do something.

This is where the jQuery comes in, and it is very simple. I have made these 'helper' methods in Javascript to make all of my inline calls centrally controllable, I keep this in my sites script folder so if I change one inline edit, I change them all; it also makes for more readable Javascript on each page.
function InlineDropdown(collectionToDropDown, ajaxAddress, dropDownDataSet) {
    collectionToDropDown.editable(ajaxAddress,
    {
        data: dropDownDataSet,
        type: 'select',
        indicator: 'saving...',
        tooltip: 'click to edit...',
        submit: 'Save',
        style: 'inherit',
        placeholder: 'click to edit'
    });
}

function InlineTextbox(collectionToInline, ajaxAddress) {
    collectionToInline.editable(ajaxAddress, 
    {
        indicator: 'saving...',
        tooltip: 'click to edit...',
        style: 'inherit',
        placeholder: 'click to edit'
    });
}

function InlineTextarea(collectionToInline, ajaxAddress) {
    collectionToInline.editable(ajaxAddress, 
    {
        type        : 'textarea',
        rows        : 4,
        indicator   : 'saving...',
        tooltip     : 'click to edit...',
        style       : 'inherit',
        submit      : 'Save',
        onblur      : 'ignore',
        placeholder : 'click to edit'
    });
}

Obviously you can read all about the options on the Jeditable page, but this is how I set them. Also notice I have a InineTextarea included as well for a textarea which is not covered here but works the exact same.

Now the jQuery calls are almost trivial:
InlineTextbox(
    $('td.editable.text'), 
    "<%= Url.Content("~/Ajax/ItemOwner.ashx") %>"
);

InlineDropdown(
    $('td.editable.dropdown'), 
    "<%= Url.Content("~/Ajax/ItemOwner.ashx") %>", 
    <%= ViewData["countries"].ToString() %>
);

What that is doing is sending the POST requests to the specified address. The POST contains a few things:
  • id - the id of the element that sent the request
  • value - the new value passed by the element
We are also passing more information there - remember that we passed both the type of field to edit and the id of the ItemOwner to edit, ie [name837] which emans we want to edit the Name field of ItemOwner 837. So we simply set up an ashx handler (which we specified above) to do the dirty work:
public void ProcessRequest(HttpContext context)
{
    string newValue;
    try
    {
        myDataContext db = new myDataContext();
        string elementId = context.Request.Form["id"];

        // since we made the first 4 of the id the 'field' whic to edit
        // we can just pull the first 4 letters for use in our switch:
        string fieldToEdit = elementId.Substring(0, 4);

        //now take anything after those 4 and it is the Id:
        int idToEdit = Convert.ToInt32(elementId.Remove(0, 4));

        // the value is simply a string:
        newValue = context.Request.Form["value"].Trim();

        // now that we have the id, get the ItemOwner from the db
        ItemOwner owner = db.ItemOwners.FirstOrDefault(x => x.Id == idToEdit);

        // after all is said and done, we will return newValue to the user so the field
        // looks as if the change has taken place (which it has)

        // using the field we pulled above, decide what to do:
        switch (fieldToEdit)
        {
            // name is easy
            case "name": owner.Name = newValue; break;

            // since the country is an integer foreign key, we need to Convert.ToInt32:
            case "ctry":
                owner.CountryId = Convert.ToInt32(newValue);
                // now that we have recorded the value, we want to return the text to
                // the user and not the id value which would make no sense
                newValue = db.Countries.FirstOrDefault(x => x.Id == owner.CountryId).Abbreviation;
                break;
            // if it wasn't caught, something is wrong:
            default: throw new Exception("invalid fieldToEdit passed");
        }

        db.SubmitChanges(); // save it
    }
    // now if an exceptions were reported, the user can see what happened
    // this also inform the user nothing was saved
    // you could easily make this not reported to the user and logged elsewhere
    catch (Exception ex) 
    { newValue = "Error: " + ex.Message + " [nothing written to db]"; }

    //now return what you want in the element:
    context.Response.Write(newValue);       
}

And that is all it takes.

Currently rated 4.0 by 3 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

ajax | asp.net | c# | css | javascript | jquery | mvc

Forganizer - unobtrusive network file organizer - new open source project

by naspinski 10/21/2009 11:49:00 AM

An unobtrusive intranet ASP.NET MVC application for logically tagging, organizing and searching network files in one centralized location with a fast and simple interface

Me and some friends have a network set up where we share movies and music. This is a Windows domain network and we all simply share our folders as 'shares' across the network. The problem is that there are so many different files and they are all spread out, there was no way to browse them all at once in any sort of convenient way. That is where the idea for forganizer came up, it is simply a tagging and search interface for multiple shared drives (or just your local ones if you want). Since I hadn't really made any MVC projects yet, I decided to do this one in ASP.NET MVC, a great new technology. Also, this was my first attempt at many new programming techniques I hadn't really used in the past such as Unit Testing, Inversion of Control (Dependency Injection) and Mocking, all very useful!

I want to say right up front, this is for a Windows network, and will work best with... err... IE7+, because it works best with your file explorer - some features like folder opening and downloads may not work with other browsers.

You can always check out my source code if you want to see how something was done, here I am just going to explain what the program does from a user point of view.

clean install

Once forganizer is installed (just run Content/setup.sql and publish the rest to a website, making sure you have MVC installed and all that good stuff) you will see this:

Now you need to add some files to the system, here is the directory we are going to add for the demo. Notice that there are some files in the top folder, and also some folders that go down (quite a few nested folders actually).

adding some files

To add new files in, simply click on the 'manage' tab on the upper right. The default page for manage is 'add files' so you simply enter the network path in the 'from folder' field and click 'run it'.
Notice that it only uploaded 8 files, those are the files in the root. If you check the 'recursive' checkbox, if will go ahead and run through all of the files regardless of depth:
The system will never add a file more than once, so feel free to run the same folders over and over, in fact, that is how you enter new files that have been put on the shares - I think later I will implement and auto-updater. Now if we were to will in more of the textboxes the system would be more selective. Say I wanted to exclude all of the .txt files I have, I would just fill '.txt' in the 'exclude extensions' blank. Similarly, if I am only interested in video files, I would just put '.avi .mpg .mpeg' in the 'include only these extensions' field - it's really pretty self-explanatory.

now you are up and running

Click on the 'search' tab or on 'forganizer' and you will see that you now have a tidy list of files. Also, you will notice that on the right side, all of the file extensions that were in your folders are now represented in the extensions cloud, sized by the relation of file count - in my example, there are many more .cs files than anything else:
Each file has download, open folder and delete links next to it. They all do what you think they would, except delete does not actually delete a file, just the reference in forganizer. If you delete a reference, then later restore it, it will still hold all the tags you previously assigned to it.

tag some stuff

As of right now, this doesn't do us much good, they are searchable by file extension (just click on the file extension on the right), but you could do that in Explorer. We want to add some tags, so click on 'manage' again, and then on 'mass tag adding' on the right side menu.
In this example, I am adding the tag 'Testing' to all the files in the directory \\network_drive\share\folder\forganizer\Forganizer.Tests. Now go back to the search, and you can see that many of the files have been tagged:
The 'mass tag delete' and 'mass tag edit' work just the same as above (actually runs the same exact code). Notice that I also manually added the 'wallpaper' tags to a couple .jpg files - that was done simply by typing 'wallpaper' in the small textbox by each file and clicking '+tags' or pressing enter. You will also see that now there is a cloud tag on the right showing the tags that are in the present search.

create categories

Now you can make some categories to make searching easier. Categories are just groups of file extensions, I am going to make a 'programming' category that includes .js and .cs files:

the manual tagging interface

Now going back to the main search, you will see that a 'programming' category is now in the sidebar. In the following picture, you can see that I have clicked on the 'WebUI' tag and the '.js' file extension. Now all I see is the .js files that are tagged with 'WebUI', it's just that simple! Also take note of the intuitive urls achieved with MVC.
I also typed MS in some of the .js file blanks as I am going to tag those as MS javascript files by pressing enter:
Those MS tags are now inserted.

Now if you want to delete a tag, simply hover over it and a [delete] link will show up:
Click it and the tag is removed:
Pretty basic stuff and simple to figure out and use. This same add/delete interface is used for categories as well.

file cleanup

Now what if someone went and deleted some files, since forganizer does not actually constantly monitor the files, it will be out of date. That is why I built a cleanup feature - say I delete these files:

I can just go to manage -> file cleanup and click the big button:
And you are all cleaned up. One great feature on this is if any file is deleted, either manually or by the cleanup tool, its tags will be preserved; if that file is ever re-added, or restored, it will still have all the meta-data that it always had.

some more stuff

I went ahead and added the 'WebUI' tag to all the files in the \\network_drive\share\folder\forganizer\forganizer.WebUI folder, and 'DomainModel' to all files in the \\network_drive\share\folder\forganizer\forganizer.Tests folder, and finally 'forganizer' to all the files in the \\\network_drive\share\folder\forganizer\forganizer folder, so I can easily discern all of those files. I also added a 'visual_studio' category that include .csproj, .sln and .suo extensions, as well as a documents and images category.

So now I want to find all the Visual Studio related files in forganizer; all I need to do is click on 'visual_studio' in the categories, and 'forganizer' in the tags section and I get the files I am interested in:
Think of it now as "showing all the .csproj, .sln and .suo files with the forganizer tag" Notice that in the upper right, 'and' has a box around it, you can also choose 'or' and it will be a broader search. Say I clicked the 'or' link and then clicked the 'wallpaper' tag and 'images' as well, now forganizer would be showing "showing all the .csproj, .sln, .suo, .png, .jpg and .jpeg files with the forganizer tag OR the wallpaper tag"
You will also see that each cloud (tags/extensions/categories) will be broken into 2 parts, the active (green) links and the inactive (grey) links. The active links are files that are showing in the search right now, the inactive ones are things you can add to the search that will broaden it; if you have 'and' picked in the tag section, you will not see and inactive tags, as that wouldn't make sense.

remember, this is all unobtrusive

This never actually does anything with the files, deleting only deleted the reference, the files will still be there! This is just a layer on top to help sort/search.

I hope this is interesting to someone out there, if not, it was great to help learn MVC and some other great technologies.

Currently rated 4.4 by 5 people

  • Currently 4.4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , , , ,

asp.net | c# | css | linq-to-sql | mvc | my projects

<i> is for image, sprite image

by naspinski 10/11/2009 4:29:00 AM

a slightly modified, very simple approach to css sprites

Css Sprites are nothing new, it is a way to take one image and use it for everything for faster page loads; pretty simple. On my latest project, I came across a simple way to to employ these sprites in a logical manner; this method even makes for intellisense images in Visual Studio.

prepare your sprites

The first thing to do, is to get your sprites together in a zip file. Basically gather up all the pictures and icons you will be using and put them into a single folder, then zip them up. Here is the zip I am using for the demo demo_sprite.zip (14.12 kb). Then simply go to Project Fondue set up your settings and process. For the purposes of this method, set the 'Css Prefix' to 'i' and clear the other 'Class Output option' fields. Now you have your css, and you can download the image that Fondue produced, which is the image directly to the left in this post. The tough work is alreaday done, now you are ready to implement it.

the <i> tag

As stated in the title, I chose to use the <i> tag. This tag was originally used for italics, but that practice is not always followed, and most people use CSS reset anyway, so it is up to us to choose what we want it to mean... and I chose 'image' (the img tag wont work as it rendered the ugly 'image not found' image in most browsers). So for this to work, you are going to have to first reset the <i> tag to nothing in css, then set it's background to the sprite image; I will assume you are using your own css reset, and my sprite to the right is called sprites.png.:
i {background:url(Images/sprites.png) no-repeat; 
   display:inline-block; width:24px; height:24px; }

/* code produced by Fondue */
i.danger { background-position: 0 0; } 
i.download { background-position: 0 -74px; } 
i.error { background-position: 0 -148px; } 
i.folder { background-position: 0 -222px; } 
i.reload { background-position: 0 -296px; } 
i.success { background-position: 0 -370px; } 
i.trash { background-position: 0 -444px; } 
i.warning { background-position: 0 -518px; } 

I am setting the default height/width to 24px because that is the size of my icons, if all of your are not the same, you can either set a default size here, or size every one indivually; I recommend using the most common size as the default for the smallest css.

*If you do have images of different sizes, be sure to set their height/width in their corresponding css classes.

use it

Now you are all set, the html:

<i class="danger"></i>


Produces and:

<i class="download"></i>


Produces and so on. Plus, if you are using visual studio, you will notice since these are css classes, they pop up in your intellisense, so it is easy to push out images on the fly in code.

Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

css | html

Setting the row background color in a GridView based on a value in the the row

by naspinski 2/8/2009 8:42:00 AM

This is something that needs to be done often, but it is not always obvious how to do it

Often times you want a row to be colored different or highlighted based on values, this can be useful for multiple reasons. This is a very simple thing, but not all that obvious.

Make your different CSS classes

Set up some CSS classes that will be used for the row coloring:
.blue { background:Blue; }
.orange { background:Orange; }
.normal { background:Transparent; }

Set your RowDataBound event in your GridView

This is going to happen on the RowDataBound event, so be sure to call one in your GridView:
<asp:Repeater ID="gv" onrowdatabound="gv_RowDataBound" ...

Set up your event to handle the row

Now handle each row in the event:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
  e.Row.CssClass = e.Row.Cells[0].Text.Equals("1") ? "blue" : "normal";
}

It's just that simple. Now, if the text in Cell[0] (the first cell) of a row is equal to "1" the row will have it's CssClass set to "blue", otherwise it will be "normal".

Now if you want to have multiple different cases:
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
  switch(e.Row.Cells[0].Text)
  {
    case "1" : e.Row.CssClass = "blue"; break;
    case "2" : e.Row.CssClass = "orange"; break;
    default : e.Row.CssClass = "normal"; break;
  }
}

Now if the first cell is equal to "1", it will be blue, if it is equal to "2" is will be orange, or else it will be transparent; so simple!

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

asp.net | css