Yearly Archives: 2012

Infragistics: Detect type of AJAX callback

This post continues topic started in “WHDG: Correctly detect Async Callback“. Back then I described a way to correctly detect server-side when an infragistics control (WebHierarchicalDataGrid) issues an async callback.

But what if you need to detect actual type of the call and distinguish paging from sorting from filtering from row expanding? Well, where there is will there is way. Infragistics says there’s no build-in flag indicating AJAX action, but we can determine the action by intercepting and interpreting HTTP Request object.

First let’s define a return type in form of an Enum describing all possible outcomes (it’s always good to work strongly typed values):

Public Enum GRID_AJAX_CALL_TYPE
   NON_AJAX = 0
   PAGING = 1
   SORTING = 2
   FILTERING = 3
   CHILD_POPULATING = 4
End Enum

And now actual function. In the previous post I described that presence of AJAX call can be determined if key starting with "__IGCallback" is present in Request.Form collection. By interpreting actual value of Request item with that key we can determine type of AJAX call. For example, when grid’s row is expanding during load-on-demand, it contains JSON data "eventName":"Populating","type":"loadOnDemand" so our function simple has to catch it:

Function GetGridAjaxCallType() As GRID_AJAX_CALL_TYPE
   Dim sIgCallBackKey As String = HttpContext.Current.Request.Form.AllKeys.SingleOrDefault(Function(S As String) S IsNot Nothing AndAlso S.StartsWith("__IGCallback"))
   Dim sIgCallBackRequest As String

   If sIgCallBackKey <> "" Then
      sIgCallBackRequest = HttpContext.Current.Request.Form(sIgCallBackKey)

      'Detecting Child Populating.
      If sIgCallBackRequest.Contains("""eventName"":""Populating"",""type"":""loadOnDemand""") Then Return GRID_AJAX_CALL_TYPE.CHILD_POPULATING

      Return GRID_AJAX_CALL_TYPE.NON_AJAX
   Else
      Return GRID_AJAX_CALL_TYPE.NON_AJAX
   End If

End Function

The function tries to locate "__IGCallback" key in HTTP request (Line 2), if the key present – function reads actual Request value (Line 6) and if Load-on-demand populating is detected (Line 9) – returns result saying so, otherwise returned result indicated non-ajax call.

This example implements only one detection – Load-on-demand populating, I will leave it to you to add sorting/filtering/paging detection. Once implemented – usage is pretty straightforward:

If Not IsPostBack Then
   '...
Else
   If GetGridAjaxCallType() = GRID_AJAX_CALL_TYPE.CHILD_POPULATING Then
      RebindTheGrid()
   End If
End if

Active CSS selector not working correctly for Input Button in IE

CSS has a cool selector called “:active“, it can be used for example to select a button when it is pressed. Let’s say you have an HTML markup like this:

<input type="button" class="mybutton" value="Click me" />

and you define CSS selector like this:

.mybutton:active {background-color:red}

the button will change its background color to red when clicked and only for the duration of the click (while the mouse button is down) as soon as mouse button is released – background color is reverted to original.

This works fine in all modern browsers and supposed to work in Internet Explorer since version 8. And it works – well kind of – only you click the button but not the button label (text of the button). If you click actual text – style does not change.

Weird, but with IE weird is often normal. To alleviate the problem use button HTML element instead of input:

<button type="button" class="mybutton">Click me"</button>

With this markup CSS described above works universally.

Of course if you need to target browser below IE8, CSS selector approach does not work, you have to resort to JavaScript:

<input type="button" style="background-color:white" value="Click Me" onmousedown="this.style.background='green'" onmouseup="this.style.background='white'" />

Solution: WebDataGrid loses styles after postback

Infragistics WebDataGrid control offers very flexible styling option – you can set font, color, size of almost any element from column to individual cell. Here is an example of basic markup that sets CSS classes of overall grid control, grid header, grid odd row and grid even row:

<ig:WebDataGrid ID="xMyGrid" runat="server"
   CssClass = "GridStyle"
   HeaderCaptionCssClass = "GridHeaderCellStyle"
   ItemCssClass = "GridCellStyle"
   AltItemCssClass = "GridAltCellStyle" 
>

And corresponding example of CSS class for even row:

tbody > tr.GridAltCellStyle > td
{
   font-size:11px;
   font-weight:normal;
   font-family:Verdana, Geneva, sans-serif;
   height:20px;
   padding: 2px 2px 2px 2px;
   border-bottom: none;
   border-right: 1px solid rgb(190,198,178);
   background-color:rgb(240,240,240);
}

(For a complete grid styling reference take a look at this styling guide)

And it all works fine, your grid renders so beautifully, Picasso would cry. But only on initial page load. And here comes dreadful postback. Continue reading →

Position:Absolute within Position:Absolute

Let’s say we have a basic HTML layout: a container DIV and within it another DIV and an image:

<div id="xdivContainer">
   <div id="xdivMenu" style="position:absolute"></div>
   <img id="ximgIcon" src="icon.gif" />
</div>

Inner (child) div is positioned absolutely and we want to place it at the coordinates of the image (think popup menu appearing on icon click). A very basic JavaScript function obtains position of the image:

// Class placeholder for coordinates
function CTopLeft(i_nTop, i_nLeft) {
   this.nTop = i_nTop;
   this.nLeft = i_nLeft;
}

// obtain position of a DOM element
function GetTopLeft(i_oElem) {
   var cTL = new CTopLeft(0, 0);
   var oElem = i_oElem;

   while (oElem) {
      cTL.nLeft += oElem.offsetLeft;
      cTL.nTop += oElem.offsetTop;
      oElem = oElem.offsetParent;
   }
   
   return cTL;
}

As you can see it simple collects offset positions of the HTML element, combining them into absolute coordinates. So to absolutely position our child DIV at the coordinates of the image we can call it like this (I am using $() notation as a shortcut for document.getElementById)

var oPos = GetTopLeft($('ximgIcon'));
$('xdivMenu').style.top = oPos.nTop + 'px';
$('xdivMenu').style.left = oPos.nLeft + 'px'

And it works fine. Until container DIV is in turn absolutely positioned: Continue reading →

Jelly Bean: Android 4.1 on Kindle Fire

And the saga continues. Tired of Ice Cream Sandwich I decided to step up. Turning my Kindle Fire into a Jelly Bean device (same Android version run by Google’s Nexus 7) is a snap. Just go to this XDA thread and download bright shiny new CyanogenMod 10.

Jelly Bean on Kindle Fire

It runs much smoother than ICS, seems a lot faster and more streamlined. There’re a lot of small things (like lockscreen trailing your finger) that make everyday tablet use a lot more enjoyable.

Jelly Bean on Kindle Fire Got a few new features as well, Google Now being one of the coolest one. As you continue to use your tablet, it learns your ways and begins supply you with useful array of information – from weather and traffic of your commute, to appointments and your favorite sports teams.

It doesn’t support Flash anymore, but with the advance of HTML5 Flash becomes more and more irrelevant in such areas as gaming and video. Major apps (Google Chrome, ROM Manager, Titanium Backup etc.) love Jelly Bean and runs perfect under Android 4.1.

Even new Optimum app released exclusively for Kindle Fire runs fine under Jelly Bean (yes sometimes I get so lazy so even finding a TV remote seems as too much of an effort and on Kindle I can watch my cable without getting up).

So, if you haven’t already done so – do yourself a favor and turn your Kindle fire from nothing more than an Amazon shopping cart into a full blown Android tablet, capable of many amazing things.

Disclaimer: Do it at your own risk. I am speaking from personal experience, but I am not responsible if you brick your device.

TSQL: work with yyyy-mm-dd date format in British English

If you work with SQL Server that is set to use UK (British English) format you may experience a strange behavior: when you try to assign a date that is in ‘yyyy-mm-dd’ format to a DateTime variable or insert it into a DateTime column – an error is thrown

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value

or similar. Or even worse – no error is thrown, but an incorrect date is inserted. This is happening because even though ‘yyyy-mm-dd’ looks like universal ISO format, a UK SQL Server interprets it as ‘yyyy-dd-mm’. So a date like ‘2011-07-21’ will throw the above error, but the date ‘2011-08-01’ will be stored as ‘January 8, 2001’ instead of expected ‘August 1, 2011’.

To alleviate this problem simple add a time part to your date – make the format ‘yyyy-mm-ddThh:mm:ss’. So the dates above will become ‘2011-07-21T00:00:00’ and ‘2011-08-01T00:00:00’ and be interpreted correctly by SQL Sercer

UltraWebGrid strange behavior in IE8 when IE=EmulateIE7

If you’re using Infragistics UltraWebGrid in Internet Explorer 8 you may experience strange visual (and other) issues if you have page compatibility set to emulate IE7, e.g.

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

Issues can range from column moving not working to weird distortion in grouped mode. According to Infragistics this combination is not supported as “unstable”, but you can still make it work.

Infragistics keeps internal flags of what browser is currently in use: ig_shared.IsIE7, ig_shared.IsIE8, etc. The trick is to detect IE8 and make it fall back to IE7:

if (ig_shared.IsIE8) {
    ig_shared.IsIE8 = false;
    ig_shared.IsIE7Compat = true;
}

Place this code on top of your page JavaScript code and when it sees IE8 it will tell grid to use IE7 rendering. This is most definitely a hack, but it works.

Attract traffic and increase your site Google PR

Do you want to get #1 place on Google and significantly increase your site traffic & sales?

Then I recommend you to check out this PR4-PR8 Contextual Link Building Service – it’s quite effective. They GUARANTEE rankings & PageRank increase on Google.

Now, I know as much about SEO as a fire hydrant (and it perhaps knows more), but these guys make site promotion incredible easy. They’re doing it by providing high quality PR4-PR8 link building service, which will skyrocket your site rankings on Google, increase your site traffic & sales for ~250% within 3 months on average, and increase its Google PageRank up to PR4, PR5 or even PR6! Sign up for free at linksmanagement.com today to see what kind of links they cab build for you, and where they’ll come from. Once you sign up, you’ll also get some valuable BONUS!

UltraWebGrid: “Input string was not in a correct format” error while setting width of a column

Infragistics UltraWebGrid allows you to set width of a column in client-side JavaScript, you can do it using code similar to this:

igtbl_getGridById('xmyGrid').Bands[0].Columns[3].setWidth(someValue)

But, while executing this code on the client, you may get a nasty surprise by getting following error from the server:

Input string was not in a correct format.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.FormatException: Input string was not in a correct format.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[FormatException: Input string was not in a correct format.]
System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) +10163939
System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) +207
Infragistics.WebUI.UltraWebGrid.StateChangeProcessor.ProcessChanges() +6230
Infragistics.WebUI.UltraWebGrid.UltraWebGrid.ProcessChanges(StateChanges stateChanges, Boolean fireEvents) +701
Infragistics.WebUI.UltraWebGrid.UltraWebGrid.LoadPostData(String postDataKey, NameValueCollection values) +7580
System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +945
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2071

Now, you do know that your someValue is definitely a number, why this error then? Let alone – why client-size resize causes a server call? But I will leave this to Infragistics. Actual cause of the error – number not being Integer. If you change the code from above to

igtbl_getGridById('xmyGrid').Bands[0].Columns[3].setWidth(Math.ceil(someValue))

it will execute without any errors. Go figure.

Correctly compare file date against TSQL stored date

If you need to track whether a particular file has changed or not (and I am not talking about FileSystemWatcher, often it’s an overkill), one way is to compare file’s LastWriteTime against stored value. But if you store the date value in SQL Server you may be in for a surprise – even if file date hasn’t changed – dates will not compare as equal. Consider following example:

'Reading current system file date/time
Dim dCurrentFileDate As DateTime = File.GetLastWriteTime(sFilePath)

'Storing file date/time in SQL Server table
CMyDatabaseClass.SaveDate(sFilePath, dCurrentFileDate)

'Immediately reading date/time value back
Dim dStoredFileDate As DateTime = CMyDatabaseClass.LoadDate(sFilePath)

'Comparing stored value against current
If dCurrentFileDate = dStoredFileDate
'
End If

The If statement on Line 11 will produce False results even if the dates seem identical. The reason – millisecond part of the datetime. SQL Server and .NET disagree on how to treat it so the best thing to do is to strip milliseconds from system file date/time before storing it or comparing against stored value.

Joe from StackOverflow.com offers a very elegant solution. That solution is in C# and here it is converted to VB.NET. To apply it to the example above simple add after the second line:

dCurrentFileDate = dCurrentFileDate.Value.AddTicks(-(dCurrentFileDate.Value.Ticks Mod TimeSpan.TicksPerSecond))

This will remove milliseconds from the date/time value and next time if you compare to the same value – values will be really equal.