Please stop pushing JavaScript down my throat.

by Admin 2. September 2012 09:45

I am primarily a web applications software engineer.  This has been my career path for last 12 of the 17 years I have been working.  That being said, I never overlook the merits of client applications in certain situations (graphically intense, constant connection or the need to integrate with other applications).  I have always found that any code that you have complete control over should keep in mind the following paradigms:

Standard OO principals:

  • Polymorphism: IAnimal -> Mammal -> Dog -> Basset Hound
  • Inheritance: Dog::Eats(){ return “Dog Food”}: Dog overrides Eat From Mammal where it is overridden from IAnimal.
  • Interfacing: IAnimal can be passed around regardless of the type of the inheriting animal.
  • Encapsulation: There is no reason to expose everything to everyone. Something’s should be exposed to the sub classes and (like in life) some things should just be private.

Other important constructs:

  • “Compiled” vs. “Interpreted”: This construct allows programming languages to be compiled down to a lower level language making them run as fast as possible on the target platform.
  • Type Safety (Strongly Typed): Increases performance and reduces runtime errors because the compiler catches issues and optimizes performance for the particular types. NOTE: I incorrectly stated performance is increased with type safety.  This is incorrect, it is a compile time construct and will not increase performance.

Now web applications by default are multiplatform targeted.  They should react the same way on one IE 9 running on Windows as on Chrome running on Mac (they don’t, but bear with me I am getting to the point).  This is where JavaScript excels. Since the actually code is pushed down to the compliant browsers the implementation of that code is left to the browser with guidance of ECMA standards.

I love JavaScript, I love JQuery, I think it is awesome.  But stop trying to make me run it on my servers or on my desktop FOR EVERYTHING.  .Net, Java, C++ all work great as compiled server side languages. Objective C and the previous also work awesome as compiled rich client applications (as long as you know the target system).  So why on earth would I want a language that breaks 3 of my core tenants of programming when I know the target system?

Yes for those that don’t know it let me reiterate JavaScript is not encapsulated, there is no way to mark a method as private. It is certainly not complied (sorry Closure you are an optimizer and calling yourself a compiler is an insult to anyone that has ever built a real compiler).  Finally it isn’t type safe.   I can do the following:

var something = 1; //something is an int
something =  "Ted"; //something is an string
something = function () { return "ted"; } //something is a method pointer
something = 1.34343; //something is a float
something = [1,2,3,4,5]; //something is an array

WOW, something can do anything, and I guarantee the above will run with no issues.  Yes I can do something similar with dynamic types, but there is a time and a place for dynamicity and all the time is not it.  

So when I read about Node.JS used in place of IIS/Apache and JSDB/TaffyDB used in place of Oracle/Sql Server or MySql I shudder a bit.  The only constant theme for why I should do this: is the same language is used client side and server side.  No performance gains (BTW scalability and performance are two completely different dynamics) and no additional features.  Sorry I just can't jump on the bandwagon.

I may sound like a bitter old programmer when I hear the terms "Bandwidth is cheap" or "Processors can handle a lot more these days" or "Just add some more memory/servers".  But why write less efficient code in the the first place.  Always weigh the benefits of performance vs. maintainability.  One should not completely override the other.

Learn PL/TSQL, learn an OO language, learn a server side scripting language(Perl, Python, Ruby), learn JavaScript and learn HTML.  But more importantly, learn when to use each and keep it where it belongs.  To quote my Grandfather, "Just because you can do something doesn’t mean you should."

Tags: , , ,

JavaScript | jquery | NodeJS | OOD | SQL Server

JQuery Tooltips with MVC3 and CSS 3.0 (Part 2)

by Admin 25. March 2012 02:56

So in my previous post I explained all of the steps required to create a simple but effective CSS 3 JQuery tooltip implementation.  This was a good start, I had all I needed to fulfill my requirement of a consistent tooltip in my application.  But I needed it to be a little easier to use throughout the application.  A custom Html Helper Extension to the rescue. Creating an HTML Helper is a pretty straight forward task this one, however, needed a bit of special sauce to make it work the way I wanted.

First I wanted to make sure I could bind it to my model, in case in the future I wanted to default it to the [Display] property on the model.  Second I wanted to be able to use the @<text></text> syntax for the contents of the tooltip.  It made sense to work backwards I wanted the control to work like this: 

@Html.InfoTooltipFor(model => model.ToolTipTitle,
	@<text>
	<h4>@Model.ToolTipTitle</h4>
	<ul>
   		<li>
			<b>Scott Guthrie</b> – 
			<a href="http://weblogs.asp.net/scottgu/">
				ScottGu's Blog
			</a> One of the best resources for all things Microsoft Web
                </li>
		<li>
			<b>Scott Hanselman</b> – 
				<a href="http://www.hanselman.com/blog/">
					Scott Hanselman's Computer Zen
				</a> Another great resource very current and very informative.
		</li>
		<li>
			<b>ASP.NET</b> – 
				<a href="http://www.asp.net/mvc">
					ASP.NET MVC
				</a> The mother of all things ASP.NET MVC
		</li>
     </ul>
</text>)

 

Seemed simple enough so at first I create the Helper as follows:

 

public static MvcHtmlString InfoTooltipFor<TModel, TValue>(
    this HtmlHelper<TModel> html, 
    Expression<Func<TModel, TValue>> expression, 
    string tooltip)
{
...
}

 

Nope that won't work... 

 

And once I thought about it makes sense that a string won't work.  It isn't anything remotely like a string it contains functions, delegates and properties. I know this type of implementation exists I have seen it in other controls.  So how is it done?  After an exhaustive google search I found this article by Phil Haack.  It was close to what I needed, so, after some trial and error I came up with this:

public static MvcHtmlString InfoTooltipFor<TModel, TValue>(this HtmlHelper<TModel> html, 
		Expression<Func<TModel, TValue>> expression, 
		Func<object, HelperResult> tooltip)
{
	//Get the Model metadata
	ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
	string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
	string tooltipId = metadata.PropertyName ? ? htmlFieldName.Split('.').Last();

	if (String.IsNullOrEmpty(tooltipId))
	{
		return MvcHtmlString.Empty;
	}
	//creates the span tag for the image
	TagBuilder spanTag = new TagBuilder("span");
	spanTag.MergeAttribute("class", "tooltipItem");
	spanTag.MergeAttribute("id", tooltipId);
	spanTag.MergeAttribute("data-tooltip", "tt" + tooltipId);

	TagBuilder imgTag = new TagBuilder("img");
	imgTag.MergeAttributes(new RouteValueDictionary(
		new
		{
			@class = "infoimage",
			src = UrlHelper.GenerateContentUrl("~/Content/info.png", html.ViewContext.HttpContext),
			alt = "info"
		}
		));
	spanTag.InnerHtml = imgTag.ToString(TagRenderMode.Normal);

	//creates the tooltip contents
	TagBuilder tooltipTag = new TagBuilder("div");
	tooltipTag.MergeAttribute("class", "hidden");
	tooltipTag.MergeAttribute("id", "tt" + tooltipId);
	tooltipTag.MergeAttribute("name", "tt" + tooltipId);
	tooltipTag.MergeAttribute("data-tooltip", "tt" + tooltipId);
	tooltipTag.InnerHtml = tooltip(null).ToString();

	return MvcHtmlString.Create(spanTag.ToString(TagRenderMode.Normal) + tooltipTag.ToString(TagRenderMode.Normal));
}

The key is Func<object, HelperResult> this allows templated items to be passed into helper method.  This was exactly what I needed and poof like magic it worked.  MVC is awesome, creating a control like that in standard ASP.NET would have been a major pain. 

The entire solution is in the attached zip...

EasyTooltips.zip (2.46 mb)

Tags: , , , ,

AJAX | css | jquery | MVC3

JQuery Tooltips with MVC3 and CSS 3.0 (Part 1)

by Admin 24. March 2012 17:58

I am a developer and no graphic artist by any strech of the imagination, but I am often thrown into that roll.   Seriously, how many small projects have the budget for a Graphic artist and a developer, not to mention the fact management rarely knows the difference.  

Regardless, I needed to create some tooltips to be used throughout an internal web application I was creating.  There are about 30 trillion jquery tooltip plugins on the internet, and most of them are good, I felt a little plugin overloaded, so I decide to roll my own.  The CSS 3.0 implementation was pretty simple (only 2 classes):

.tooltipwindow
{
   border-bottom-left-radius: 15px;
   border-top-left-radius: 0px;
   border-bottom-right-radius: 15px;
   border-top-right-radius: 15px;
   border: 1px solid #0099FF;
   position:absolute;
   padding:5px;
   background-color:#fff;
   z-index: 20000;
   box-shadow: 3px 3px 2px #808080;
   font-size:smaller;
}
 
.hidden
{
   display:none;
}

Only a few CSS 3.0 items to mention box-shadow (for the drop shadow effect) and border-radius (for the rounded corners on all but the top right) other than that pretty standard.  The JavaScript was pretty simple as well:

A few global variables:

//A 1/2 Second fade-in/out
var toolTipHideDelay = 500;
//A 1/4 second before the tooltip begins to fade
var toolTipMouseoutDelay = 250;
//The timer to determine when the fade should start
var toolTipHideTimer = null;
//The variable containing the tool tip contents
var tooltipWindow = null;
//The current Id of the tool tip
var tooltipCurrentId = null;

Then the actual tool event handlers:

//standard doc ready event
$(document).ready(function () {
 
    initializeTooltips();
})
 
function initializeTooltips() {
    //there is only one window for all tooltips on the page.
    tooltipWindow = $("#tooltipWindow");
    //all tooltips implement the following class
    var tooltipItem = $(".tooltipItem");
 
    //tooltip mouse events (not using hover because I want the tooltip to follow the cursor
    tooltipItem.mousemove(function (e) {
        //check to see if the tooltip is already opened
        if (toolTipHideTimer) {
            //clear the timeout since the user is hovering over the item again
            clearTimeout(toolTipHideTimer);
            //retrieve the tooltip data item from the current element
            if (tooltipCurrentId != $(this).data("tooltip")) {
                setToolTipPosition(this, e);
                //set the tooltip inner content
                tooltipWindow.html($("#" + $(this).data("tooltip")).html());
            }
        } else {
            //show the tooltip
            setToolTipPosition(this, e);
            //the tooltip is hidden do fade it in
            tooltipWindow.fadeIn(toolTipHideDelay);
            //set the tooltip inner content
            tooltipWindow.html($("#" + $(this).data("tooltip")).html());
        }
    });
    tooltipItem.mouseout(function (e) {
        //get ready to hide the tooltip
        toolTipHideTimer = setTimeout(function () {
            toolTipHideTimer = null;
            tooltipWindow.fadeOut();
        }, toolTipMouseoutDelay);
    });
 
    //tooltip window mouse events
    tooltipWindow.mouseover(function () {
        //keep the tooltip open if the user is over the tooltip window
        if (toolTipHideTimer) {
            clearTimeout(toolTipHideTimer);
        }
    });
    tooltipWindow.mouseout(function () {
        //get ready to hide the tooltip
        toolTipHideTimer = setTimeout(function () {
            toolTipHideTimer = null;
            tooltipWindow.fadeOut();
        }, toolTipMouseoutDelay);
    });
}

Then just a simple postion helper:

function setToolTipPosition(item, mouseevent) {
    var tooltipitem = $("#tooltipWindow");
    //set the tool tip to the current mouse position the 
    //2+ is so the user can still click the element under the 
    //tooltip
    tooltipitem.css({
        left: 2+(mouseevent.pageX) + "px",
        top: 2+(mouseevent.pageY) + "px"
    });
}

So now we have all of the client pieces we need, infact the following html will generate a tooltip:

<h3 style="display:inline-block">For More info hover over the icon</h3>
<span class="tooltipItem" data-tooltip="ttToolTipTitle" id="ToolTipTitle">
  <img alt="info" class="infoimage" src="/Content/info.png" />
</span>
 
<div class="hidden" data-tooltip="ttToolTipTitle" id="ttToolTipTitle" name="ttToolTipTitle">        
            <h4>Learn More from these sites</h4>
            <ul>
                <li><b>Scott Guthrie</b> – <a href="http://weblogs.asp.net/scottgu/">ScottGu's Blog</a> One of the best resources for all things Microsoft Web</li>
                <li><b>Scott Hanselman</b> – <a href="http://www.hanselman.com/blog/">Scott Hanselman's Computer Zen</a> Another great resource very current and very informative.</li>
                <li><b>ASP.NET</b> – <a href="http://www.asp.net/mvc">ASP.NET MVC</a> The mother of all things ASP.NET MVC</li>
            </ul>
        </div>
</div>
 
<div id="tooltipWindow" class="hidden tooltipwindow">
</div>

 

That looks like this:

 

So we are good to go, I just didnt want to have to copy all of this HTML for every tooltip I created in the system.  In Part 2 I will talk about how to integrate this with an MVC Html Helper.

 

Tags: , , ,

css | jquery

MVC Makes AJAX easier

by Admin 12. February 2012 19:07

MVC is a pretty new paridigm to me, I just started using it about 5 months ago, but one of the first things I noticed is how much easier it has made AJAX.  This is coming from someone who has had a very long career in ASP.NET.  There were a few different ways to provide Ajax functionality in ASP.NET the evil update panel being the easiest to implement.  My preference and, IMO, the more correct approach was to use the AJAX framework in conjunction with AJAX Aware WCF/Web Services.  The low framework overhead (no Eventing Model) in conjuction with the relatively small request/response package made these fairly easy to implement and perform very well.  The problem with these services is they were still tied up in all sorts of framework gook.

With MVC, all of that framework gook is gone, it is a much simpler PHP style implementation of AJAX.  There are several ways to utilize AJAX in the MVC world, there are the AJAX MVC Helper Class which is very easy to work with, but I perfer a pure JQuery ajax approach.

Enough talk here is an example of a simple implementation of ajax using 4 commonly used methods:

First the Controller (in this case I am using the Products table of the Northwind Database (kickin' it old school)):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
namespace JqueryAjax.Controllers
{
    public class ProductsController : Controller
    {
        //
        // GET: /Products/
 
        public ActionResult Index()
        {
 
            List<Product> prodList = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prodList = ctx.Products.OrderBy(p => p.ProductName).ToList();
 
            }
            return View(prodList);
        }
 
        public ActionResult _productInfoJSON(int? id)
        {
            Product prod = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == id);
 
            }
            return Json(prod, JsonRequestBehavior.AllowGet);
        }
 
        public ActionResult _productInfo(int? id)
        {
            Product prod = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == id);
 
            }
            return PartialView(prod);
        }
 
        [HttpPost]
        public ActionResult _productInfoJSONParams()
        {
            Product prod = null;
            int prodId = int.Parse(this.ValueProvider.GetValue("id").AttemptedValue);
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == prodId);
 
            }
            return Json(new { prod.ProductName, prod.UnitPrice });
        }
 
    }
}

I use the "_" syntax to denote partial actions and views.  So looking at the above code you will notice there is only one full action "Index", so lets look at its view:

@model IEnumerable<JqueryAjax.Product>
 
@{
    ViewBag.Title = "Products List";
}
 
@section script{
    <script src="@Url.Content("~/Scripts/Info.js")" type="text/javascript"></script>
}
<h2>Index</h2>
<table>
    <tr>
        <th>
 
        </th>
        <th>
            ProductName
        </th>
    </tr>
 
@foreach (var item in Model) {
    <tr>
        <td>
            <a class="prodInfo" href="#" data-product-id="@item.ProductID">
                <img src="../../Content/Images/info.jpg" width="20" height="20" alt="info" border="0" />
            </a>
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProductName)
            <div id="product-@item.ProductID" style="display:none;">
            </div>
        </td>
    </tr>
}
 
</table>
So in this view I am simply building a Table of product names with an info image, easy peasy.  The Ajax parts of the html are housed in the:
 
<div id="product-@item.ProductID" style="display:none;">
And the:
<a class="prodInfo" href="#" data-product-id="@item.ProductID">

The former is the place holder for our dynamic content and the latter is the link to our dynamic content.  Now that we have all of the page scaffolding in place we need to hook up the pieces.  There are several ways we can retrive the content.  We could retrieve a standard JSON object from a controller _productInfoJSON and _productInfoJSONParams or you can return a partial view.  This is where the power of MVC really hits home.  You can craft a fully functional page and return it to your AJAX container.  That is pretty sweet...  But first lets look at the JSON example:

I created 2 a JSON Get (useful for RESTful services) and a JSON Post (prefered for internal web site calls):

Here is the Java script for calling the JSON get in conjuntion with the previously crafted view and controller:

/// <reference path="jquery-1.7.1.min.js" />
$(document).ready(function () {
    $(".prodInfo").click(function (e) {
        //stop the href="#" from firing
        e.preventDefault();
 
        var prodId = $(this).data("productId");
        jsonGet(prodId);
 
    });
});

function jsonGet(prodId) {
    $.ajax({
        url: "/Products/_productInfoJSON/" + prodId,
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html("<span> price:"+ data.UnitPrice +"</span>");
        }
    });
}
and the JSON parameterized post:

jsonPost(prodId);

function jsonPost(prodId) {
    $.ajax({
        url: "/Products/_productInfoJSONParams",
        type: "POST",
        data: { id: prodId },
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html("<span> price:" + data.UnitPrice + "</span>");
        }
    });
}

This will get you a simple return value that you can format in JQuery.

Pretty simple right?  Well its about to get easier.  Now lets say we want to return a significant amount of data to the client and we don't want to do that messy JavaScript HTML formatting.  Partial Views to the rescue.  Create the following partial view from the _productInfo action:

@model JqueryAjax.Product
 
<fieldset>
    <legend>Product Info</legend>
 
    <div class="display-label"></div>
    <div class="display-field">
        QuantityPerUnit: @Html.DisplayFor(model => model.QuantityPerUnit)
    </div>
 
    <div class="display-field">
        UnitPrice: @Html.DisplayFor(model => model.UnitPrice)
    </div>
 
    <div class="display-field">
        UnitsInStock: @Html.DisplayFor(model => model.UnitsInStock)
    </div>
 
    <div class="display-field">
        UnitsOnOrder: @Html.DisplayFor(model => model.UnitsOnOrder)
    </div>
 
    <div class="display-field">
        ReorderLevel: @Html.DisplayFor(model => model.ReorderLevel)
    </div>
 
    <div class="display-field">
        Discontinued: @Html.DisplayFor(model => model.Discontinued)
    </div>
</fieldset>

Now change the JS click event to fire:

partialJqueryGet(prodId);

with the function definition of:

function partialJqueryGet(prodId) {
    $.get("/Products/_productInfo/" + prodId,
    function (data) {
        $("#product-" + prodId).toggle();
        $("#product-" + prodId).html(data);
    });
}

BA BAM done.  Now you are returning a partial view from an ajax call.  You can also use a pure jquery ajax implementation as opposed to the Get helper class:

function partialAjaxGet(prodId) 
{
    $.ajax({
        url: "/Products/_productInfo/" + prodId,
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html(data);
        }
    });
 
}

 

All of the code and the northwind database can be found here:

JqueryAjax.zip (2.67 mb)

http://www.microsoft.com/download/en/details.aspx?id=23654

 

Tags: , , , , , ,

AJAX | ASP.NET | jquery | JSON | MVC3 | Razor

Calendar

<<  October 2014  >>
MoTuWeThFrSaSu
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar

Page List

RecentComments

None