Corey Coogan

Python, .Net, C#, ASP.NET MVC, Architecture and Design

  • Subscribe

  • Archives

  • Blog Stats

    • 99,462 hits
  • Meta

Using jQuery to Dynamically Display a Slideout

Posted by coreycoogan on May 19, 2011


Here’s something I find myself needing to do often enough that it warrants a post. Here’s the situation…

I am dynamically displaying an unknown number of data items. The item itself is unimportant for this post, however, the item may contain some attributes that shouldn’t be displayed on the page all the time.  Perhaps it’s a  long description or information about how the item was last updated.  Whatever it is, this data is better to be hidden unless someone actually wants to see it.  This may be a good use case for some sort of panel that slides out when an “info” icon or “>>” button is clicked.

Making this happen with jQuery is pretty simple and consists of a few steps:

  1. Wire up a “click” event to the button or text from where the panel will slide.
  2. Using the clicked on element as an anchor, use jQuery’s offset() method to get the coordinates.
  3. Either clone an existing element, such as a DIV, or create one on the fly and assign the following CSS rules to it:
    1. Position – This should be set to absolute so the panel displays relative to its containing element.
    2. Top – The distance in pixels, from the top of the containing element, where the panel should be placed.
    3. Left – The distance in pixels, from the left of the containing element, where the panel should be placed.
  4. Append the new panel to the container that is holding the list of data items.
  5. Display the panel using a cool effect – or hide it.
 A couple of notes before we get to the example.  First, there are 2 ways to get an element’s position in jQuery – offset() and position().  You can read the descriptions to understand what they both do, but offset() typically works for me. I’m also using the ‘slide’ toggle effect from jQuery UI to slide my panel from left to right with the toggle() method.

Now for an example:


<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){

	//either get data from a service here or have it ready from server-side code

});

function showMoreInfo(anchor,itemId)
{
	//make a jQuery object
	anchor = $(anchor);

	//the dynamic ID of the moreInfo panel
	var panelId = 'moreInfo_' + itemId;
	//see if the panel already exists
	var info = anchor.parent().parent().find('#' + panelId);

	if(!info.length){
		//the panel doesn't exist, so create it

		//get the coordinates from our anchor
		var coords = anchor.offset();
		//clone our info panel, or use jQuery templates
		info = $('#moreInfoPanel').clone();

		info.find('#description').html('<b>Get this data based on the itemId</b>');
		info.find('#lastUpdated').html('<b>Get this data based on the itemId</b>');

		//set the new dynamic ID
		info.attr('id',panelId);

		//now set the CSS to make the panel display where we want
		info.css({
			position: 'absolute',
			top: coords.top-(info.height()),
			left: coords.left+anchor.width() + 15
		});
		//append the panel to the item div
		anchor.parent().parent().append(info);
	}

	//use the jquery UI slide definition
	info.toggle('slide',function(){
		//slide callback to change the button text depending on the state
		if(info.is(':visible')){
			anchor.html('<< Less'); 		}else{ 			anchor.html('More >>');
		}
	});

}
</script>

<body>

<div id='moreInfoPanel' style='display:none;background:silver;padding:20px;'>
	<div id='description'></div>
	<div id='lastUpdated'></div>
</div>

<div id='dataItems'>

	<!-- this is an example data item. this would be generated dynamically server side or from a web service -->
	<!-- jQuery Templates could be nice here -->
	<div id='dataItem_ITEMID' class='dataItem' style='border:1px solid black;width:200px'>
		<div style='text-align:right'>
			<!-- wire up the click event -->
			<button onclick='javascript:showMoreInfo(this,"ITEMID");'>More >></button>
		</div>
		<hr/>
		<div>
			Main content goes here
		</div>
		
	</div>
</div>

</body>

Posted in jQuery, UI | Tagged: , , , , , | Comments Off

Google Chrome JavaScript Error Notification

Posted by coreycoogan on April 8, 2011


I love Google Chrome – it’s fast, simple and standards-based. I really like the built-in developer tools, which are just like Firebug, but readily available without managing any add-ons or extensions.

One thing that is lacking from Chrome for a developer is the notification of JS errors on a page. Typically, I would hit [SHIFT+CTL+J] to fire up the JavaScript console and see if there are any errors. This can be a bit of a hassle and has caused me to miss some subtle errors at the times where I wasn’t using the console.

Knowing that Google has an extensive set of extensions available, I figured I’d check for something to notify me when there’s an error on the page. Sure enough, I found the JavaScript Errors Notifier extension that gives me exactly what I’ve been longing for. Why did it take me so long to search this out?

Posted in Helpful Tips | Tagged: , , , , | Comments Off

Adding to an Enum in Postgres 8.x and 9.0

Posted by coreycoogan on April 4, 2011


Postgres has an emum type that I’m quite fond of. To create one, you just something like this:

CREATE TYPE order_status AS ENUM ('Pending','Processing','Shipped');

Now let’s say that I realize later I also need an order status for BackOrdered. In PG 9.1, adding an enum value becomes much simpler, but for those of us on earlier versions, we’ll have to do this the hard way.

Postgres stores enum values in the pg_enum system table. It stores the enum types in the pg_type table. For user-defined types, such as an enum, PG will prefix the name with an underscore. So my enum type of “order_status” is actually stored by PG as “_order_status”. Knowing this, I can simply insert my new value into the pg_enum table, using the numeric ID used by PG for the special underscore name.

Here’s the result:

INSERT INTO pg_enum (enumtypid, enumlabel)
  SELECT typelem, 'BackOrdered' FROM pg_type WHERE
    typname='_order_status';

This will put the new value at the end of the enum. If you care where it goes, and I can’t see a reason why you would, you’ll have to resort to some other trickery. I learned this method, as well as ways to change the order, from this post on Stack Overflow.

Posted in Database, Postgres | Tagged: , , , | Comments Off

Get the most from O’Reilly Books

Posted by coreycoogan on March 10, 2011


I love technical books and have purchased a fair amount from Manning, who gives a free eBook edition with their print books. I also like O’Reilly books and have purchased hard-copy books from their website in the past. Now that I have an iPad, I like the idea of having the books available to read on it, but some technical books are better suited to print. Having to flip through several pages to see a code sample can really become distracting.

I recently went to purchase some books from O’Reilly (3/9/2011) and they were having a buy 2 get 1 free deal. I tried to buy the print/eBook bundles and realized I couldn’t combine the “bundle” offer with the Buy Two promotion. Then it occurred to me that the bundle is unnecessary.

If there are any promotions happening on O’Reilly, ALWAYS take it over the bundle. NEVER take the bundle over any other promotion. The reason? Once you have a print book, you can go back to O’Reilly’s website and get the eBook for $4.99 – anytime. Now you get the bundle AND the current promotion.

Posted in Developer Life | Tagged: , , , | Comments Off

Enter the Python

Posted by coreycoogan on March 1, 2011


My .NET related posts have been pretty sparse lately, mainly because I spend almost no time doing .NET development anymore. That’s right, my platform of choice over the last 11 years is now on the back-burner as it makes room for Python.

There is a lot of hype over Ruby and specifically Ruby on Rails these days. I had been following it and thought that would be the dynamic language and web framework I would cut my teeth on. However, a really great project came along and the requirements included nothing from the MS stack:

  • Python
  • Linux
  • Apache
  • CherryPy or other WSGI server
  • PHP
  • Postgres
  • SQLAlchemy (ORM)
  • Python

    I was very excited to learn something new and have found that I really enjoy working with Python.  It’s dynamic, flexible and easy to work with.  One thing I have really learned to love over static languages is that it doesn’t compile.  That means I just code and go.  That also means I get an interpretter where I can easily spike some code and see how things look and feel.  This makes development much faster for me and I have more confidence than I would with straight TDD.  I can shape my code on the fly and run it with a 2 hits of the ENTER key.

    Speaking of TDD, mocking in Python is an absolute dream.  No more time-consuming and costly setups to mock my objects with Rhino.  Using the Mock module is as easy as can be.   A simple example of stubbing a “firstName” property looks like this:

    person = Mock()
    person.firstName = 'corey'
    

    If I want to stub a method, it’s as simple as this:

    person.fullName.return_value = 'corey a. coogan'
    

    There’s much more that can be done, but stubbing alone probably satisfies 80% of my mocking needs.

    On the Web

    Often times when people think of Python they think of Django.  Django looks really terrific and I look forward to having an opportunity to use it.  For now, however, PHP is the answer.  I’ve only worked a little bit with PHP in the past and formed an opinion many years ago.  After working with it for several months, I am still not an advocate for PHP, but it does have it’s strengths. Fortunately, much of the PHP work involves calling JSON services and then using jQuery and JS on the client to do something with it.  There is still a fair amount of PHP tag soup, reminiscant of my classic ASP roots, but I hope to eradicate that one day.

    SQLAlchemy

    SQLAlchemy(SA) is to Python what NHibernate is to .NET.  They both allow for domain classes that are completely separated from the mappings, but SA also has some other styles, such as Declarative and SQL Soup, that can come in pretty handy.  The syntax seems pretty clunky at first, but I’m getting used to it.  The documentation is a bit rough, as many of the methods accept  *args,**kwargs, which means you can pass in any number of values and name/value pairs.  The doc tells you what are acceptable arguments, but the examples tend to be a bit scarce.  Look for an upcoming post that has examples for all the things that have tripped me up so far.

    The Times They Are a Changin’

    This blog will continue to focus on technology agnostic goodness, like JavaScript, jQuery, SQL, etc, but .NET content will be far and few between.  I’ll be sharing more of what I’ve learned in Postgres, SQLAlchemy and Python.  Hopefully I don’t lose too many of my .NET readers and hope that my content can help out a new group of people.

    Until next time…

    Posted in Python, SQLAlchemy | Tagged: , , , , | Comments Off

    Hide the X in the corner of a JQuery Dialog

    Posted by coreycoogan on January 31, 2011


    NOTE TO SELF:

    Until you find a better way, here’s how you remove the X that closes a JQuery dialog box:

    $( ‘a.ui-dialog-titlebar-close’ ).remove();

    OR

    Change the Style definition in the HEAD.

    Posted in jQuery | Tagged: , | 2 Comments »

    Use Excel to Automate Data Entry

    Posted by coreycoogan on January 27, 2011


    Over the course of my career, I have frequently been given random excel spreadsheets that contain data that needs to be either inserted or updated to a database. There are many routes one can go with this task, most of which are more complicated then necessary. I find the simplest solution is to use Excel formulas to generate my SQL statements for me.

    1. Create a formula for the SQL statement in a blank cell of the spreadsheet’s first row of data.
    2. Copy and paste the formula to the same blank cell in every other row. This fastest way I know to do the paste is to: select the first cell you wish to paste.  Hold down CTL+SHIFT+END.  This will select everything from the point of selection to the last row and last cell in the spreadsheet.  At this point, continue to hold down shift and arrow back to the left to get to the original column and hit enter.

      With the cursor on the cell with the formula, Excel outlines the cell with a tiny square on the bottom right corner.  Double click on that tiny square and your formula is repeated all the way to where the data ends next to it.
      (Thanks to Todd Boehm for posting this to the comments)

      The formula will now be copied to each row.

    3. Select every row that contains the sql and paste into your database query window.
    4. Run the queries and you are done.

    An Example

    Given the following spreadsheet for some customers, I will show a simple formula to do an insert into the customer table.

    A B C D
    1 NAME PHONE SIGNUP_DATE
    2 Joe Smith (920) 555-1112 5/21/2010 = “insert into CUSTOMER (name,phone,signupDate) values (‘” & A2 & “‘, ‘” & B2 & “‘, ‘” & TEXT(C2,”M/dd/yyyy”) & “‘)”

    Convert Excel Date to Text or String

    Notice the use of the TEXT function against the value for SIGNUP_DATE.  This is necessary with dates because Excel will spit that value out in a serial format, which isn’t what we want in our database.  Use the TEXT function to convert the Excel Date to text for the insert.

    Posted in Business, Database, Helpful Tips | Tagged: , , , | 1 Comment »

    How to Move PostgreSql Tables to a Different Schema

    Posted by coreycoogan on December 22, 2010


    Recently an application I’m working on had the need to move a mess of tables from the PG default “Public” schema to a new one, which we’re calling “Selection”. The more recent versions of PG (8.2 as of this writing) have a SET SCHEMA action available on the ALTER TABLE command.

    ALTER TABLE name SET SCHEMA new_schema

    SET SCHEMA is very nice in that it not only moves the tables, but any associated indexes, sequences and constraints.

    From the 8.2 Documentation:

    This form moves the table into another schema. Associated indexes, constraints, and sequences owned by table columns are moved as well.

    This is all fine and good, but if you have more than a couple tables to move, this can be hassle. Here’s how to use PG’s pg_tables System Table to generate the sql for every table in your database. Run this query against the database that has the tables you wish to move. Then simply copy/paste the output into another query window and execute. Don’t forget to make the schema first!

    select 'alter table "' || tablename || '" set schema "Selection";' 
    from pg_tables  
    where schemaname='public';
    

    Posted in Database | Tagged: , , , , | 1 Comment »

    Calling ASP.NET Web Service (ASMX) from JQuery

    Posted by coreycoogan on December 17, 2010


    UPDATE: 12/17/2010 12:55 AM CST – Thanks to Dave’s comments below, I learned that the script service handles object serialization to JSON for me. This means that if your return type is that of an object, it will automatically serialize this object to JSON. If you want to create an anonymous object, such as you may do from a LINQ query, just set your return type to “object”. I thought I had to turn that into a string, but that’s not necessary. Thanks again Dave. I also removed the [ScriptMethod] attribute, which is isn’t necessary and actually causes the JSON returned to be a string and not a JSON object.

    I’ve not done anything real meaningful in Web Forms in some time, so I was very surprised at how much trouble I had trying to call a simple HelloWorld service from a jQuery Post and have it return some JSON back to my screen.  It took a couple hours to finally get it right, and I know I’m not the only one.  There are Stack Overflow posts about this and many blog posts as well. Unfortunately, as helpful as those posts were, it seems that I was still missing things… the things I’m going to cover in this here post.

    ASMX Web Service

    First, let’s start with the old school web service that I’d like to use to communicate with the client.  Sure I could go WCF, but an ASMX is just fine for my needs and darn simple. The important things to note on the service:

    • To call a service from JavaScript, the service class must be decorated with the [ScriptService] attribute.
    • The service method should not decorated with the [ScriptMethod] attribute, only the [WebMethod] attribute. The ScriptMethod causes the return JSON to be a string that needs to be deserialized on the client. Without it, it comes down as a valid JSON object, automatically deserialized by jQuery for me.
    • If you are going to return a hardcoded JSON string for jQuery to parse, it has be formated with double quotes around the names and properties.  I was using single ticks, which I have gotten away with in some cases, but not here (return “{\”response\”:\”Hello World\”}”).
    • Mark the return type of the method to “object” if you want to return with an anonymous object from a LINQ query or something like that. 

    This is an example of a working service:

        [ScriptService]
        [WebService(Namespace = "http://tempuri.org/")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        public class HelloWorld : System.Web.Services.WebService
        {
            [WebMethod]
            //[ScriptMethod(ResponseFormat = ResponseFormat.Json)] Don't need this attribute.  
            public HelloWorldResponse SayIt(string name)
            {
                //the Identity of the logged in user is available
                var userName = HttpContext.Current.User.Identity.Name;
                
               return new HelloWorldResponse() {Name = name, NickName = "Mad Dog"};
            }
    
            public class HelloWorldResponse
            {
                public string Name { get; set; }
                public string NickName { get; set; }
            }
        }
    

    AJAX and jQuery

    Now for the jQuery, for which I’m using version 1.4.4.  Here’s the things that tripped me up:

    • I was using a JQ $.post call in my web pages to communicate with the server.  That caused me some problems in that the data was always returned as XML, no matter what I tried.  Knowing that $.post is a shortcut against the $.ajax method, I switched to using that so I could explicitly set the contentType to “application/json”.  I do realize that I can probably set that on the $.post method, as I’m pretty sure I’ve done that in the past, but that can cause confusion, especially with new developers.
    • If you are accessing more than one service in more than place, create a utility method or use the $.ajaxSetup method to configure the defaults.
    • If you don’t set the dataType to “json”, the response data is returned as xml.
    • If you don’t pass empty data when there are no parameters needed for the service, the response data will be returned as xml.
    • The dictionary passed to the service in the data parameter must be quoted or the service will throw a 500 error.  Web Service parameters are passed with the name of the parameter as the key (see example).
    • This is discovered soon enough, but the response from the service comes wrapped in another JSON object, available at the ‘d’ key.  If the value for ‘d’ is a JSON string, it will have to be deserialized into a proper JSON object.  I use jQuery’s $.parseJSON function for that. This example will return ‘d’ as a proper JSON object.
    <script>
        $(document).ready(function() {
    
            //this would be done in a common script file if you are going to
            //make a lot of these calls
            $.ajaxSetup({ type: 'POST', dataType: 'json', contentType: 'application/json', data: {} });
    
            $('#btn').click(function() { 
                 //call the web service with the button is clicked
                $.ajax({ url: 'webservices/helloworld.asmx/SayIt',
                    data: '{ "name": "Corey" }', //ensure the data is enclosed in a quote
                    success: function(data) {
                        var responseJson = data.d; //the real json is wrapped, get it and parse it
                        $('#sayit').html(responseJson.Name + ' aka ' + responseJson.NickName); //put the response value from the return json
                    }
                });
    
                //return false to avoid a postback
                return false;
            });
    
        });
    </script>
    
    <div>
    	<button id='btn'>Load It</button>
    	<div id='sayit'></div>
    </div>
    

    Authorization and Authentication

    Any ASMX service written in our web project will be available to the world.  If you are using a ROLES and MEMBERSHIP provider and your site requires authentication, use the <location> tag in your web.config to lock down the directory where you put all your services.  In my example, I’ve put all my services in a WebServices directory and only authenticated users in the Admins role have access.

     <location path="WebServices">
        <system.web>
          <authorization>
            <deny users="?"/>
            <allow roles="Admins"/>
            <deny users="*"/>
          </authorization>
        </system.web>
      </location>
    

    If the user is logged in, there will be an active IIdentity in HttpContext.Current.User.Identity, so your service can use that for authorization where necessary.

    var userName = HttpContext.Current.User.Identity.Name;

    Posted in Ajax, ASP.NET, jQuery | Tagged: , , , , , | 9 Comments »

     
    Follow

    Get every new post delivered to your Inbox.