Monday, December 22, 2014

Chrome's console.table

Google Chrome's console.table( ) is a great feature.  The following example code (source) shows how powerful and useful this feature of Chrome can be.

var arr = [];
for( var i = 0; i < 256; i++ ){
  var char = String.fromCharCode( i );
  if( encodeURI( char ) !== encodeURIComponent( char )){
    arr.push({  
      character: char, 
      encodeURI: encodeURI( char ),
      encodeURIComponent: encodeURIComponent( char )
    });
  }
}
console.table( arr );

It produces the following table within the console of Chrome.
** Note: to enter line break in the Chrome's console, use [Shift] + [Enter] keys.


Sunday, November 23, 2014

Smooth Scroll in Visual Studio on VM Windows in Parallels Desktop

When using Visual Studio in Windows running on Parallels Desktop on Mac, I used to have a jumpy scroll issue on the Source Code or the Solution Explorer window. Whether I used the built-in MacBook Pro's TrackPad or an external mouse's scroll wheel, I was not able to fine-control the number of lines to scroll up or down while using the Visual Studio. The only way to scroll a few lines at a time was by using the scroll bar on the right, but this can be very counter-intruitive, since we are so used to the scrolling via the scroll wheel.

The easy workaround to this nuisance is rather simple. Go into the VM settings in the Parallels Desktop VM, select Hardware --> Mouse & Keyboard, and then un-check "Enable smooth scrolling".

Un-check "Enable smooth scrolling" to Enable smooth scrolling.

Wednesday, September 10, 2014

Static Member in C#

A good explanation and examples are found at http://csharp.net-tutorials.com/classes/static-members/

public class Rectangle
{
    private int width, height;
    public Rectangle(int width, int height)
    {
        this.width = width;
        this.height = height;
    }
    public void OutputArea()
    {
        Console.WriteLine("Area output: " + Rectangle.CalculateArea(this.width, this.height));
    }
    public static int CalculateArea(int width, int height)
    {
        return width * height;
    }
}


I like the author's example using Rectangle.CalculateArea( this.width, this.height) as an example of using a static member in a non-static class.

Thursday, September 4, 2014

Entity Framework : Update only changed fields instead of all fields

If we follow the Entity Framework's general approach to edit, it would be something similar to this.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "FacilityID, FacilityName, AddressLine1, AddressLine2")] 
Facility facility)
{
  ...
  if( ModelState.IsValid )
  {
    db.Entry(facility).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
  }
..
}

The code in the above treats all fields as `Modified` and saves all field data into the database whether the old and new value of each field is the same or different.

However, there are times that we need to update only certain fields, instead of updating all fields data. The above example would update all field data (FacilityName, AddressLine1, AddressLine2), even when only AddressLine1 was changed by user. In order to save only the changed field data into the database, we can try the following approach: compare each field's value between old and new first and perform update only on the ones that are different.
using System.Data.Entity.Infrastructure;
...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(
  [Bind(Include = "FacilityID, FacilityName, AddressLine1, AddressLine2")] 
   Facility facility)
{
  ...
  if( ModelState.IsValid)
  {
    db.Facilities.Attach( facility );
    DbEntityEntry entry = db.Entry( facility );
    foreach( var propertyName in entry.OriginalValues.PropertyNames )
    {
      // Get the old field value from the database.
      var original = entry.GetDatabaseValues().GetValue<object>(propertyName);
      // Get the current value from posted edit page.
      var current = entry.GetCurrentValues.GetValue<object>(propertyName);
      if(!object.Equals(original, current))
      {
        entry.Property( propertyName ).isModified = true;
      }
    }
    db.SaveChanges();
  }
}


Here we first get all property names (field names) and inspect each property's old and new values. Old values are retrieved from the database. New values are ones submitted by user through post.
// Get the old field value from the database.
var original = entry.GetDatabaseValues().GetValue<object>(propertyName); 
// Get the current value from posted edit page.
var current = entry.GetCurrentValues().GetValue<object>(propertyName); 
When the two values of original and current of a property are not equal,
that property will be assigned `IsModifed = true`, and its current value will be saved into the database.

On the other hand, if current field's values exist in the database already, those field values will be skipped while db.SaveChanges() is performed .


Remove containment from draggable jQuery UI Dialog

By default,  a draggable jQuery UI Dialog has containtment such that when you drag the dialog, you will be restricted by the browser's window. While comparing this default behavior against SharePoint's modal detail/edit dialog, SharePoint's dialog feels more user friendly and natural, because it lets users drag the dialog beyond the browser window. It simply feels natural to be able to move around the modal dialog outside browser window so that you can view the underlying main page's data as much as possible.

To remove containment from a draggable jQuery UI Dialog, try the following.
The trick is to use draggable's containtment property via widget of the dialog.

// Button that opens the dialog and a div to be used as the dialog
<input type="button" id="btnOpenDialog" value="Open Dialog" />
<div id="dialog"></div>
<script type="text/javascript">
  var myDialog = null; // global variable
  $(function(){
    $('#btnOpenDialog').on('click', function(){

      // Step 1.
      // Get the dialog ready.
      myDialog = $('#dialog').dialog({
        autoOpen: false, modal: true, resizable: true, width: 400, 
        buttons: {
          OK: function(){ // perform some actions ...},
          Cancel: function(){ $(this).dialog('close'); } // close the dialog 
        }
      });
      
      // Step 2.
      // `myDialog` is a global variable and has a reference to the dialog.
      // Use `myDialog` to remove containment from the dialog.
      myDialog.dialog("widget").draggable({ containment: false });

      // Step 3.
      // Show the dialog
      myDialog.dialog("open");

    });
  });
  
</script>

Thursday, August 28, 2014

Using Less in Visual Studio 2013 Web Project

Here is a cheat sheet on "what to do" to start using LESS on Visual Studio 2013 web project.

  1. Install "dotless" using Package Manager Console ("install-package dotless") or the Nuget Package Manager
  2. Open Web.config, locate the "dotless" section, and change it as the following.
    The main thing is to add
    <validation validateIntegratedModeConfiguration="false"/>
    
    to the <system.webServer> node.
    <dotless minifyCss="false" cache="true" web="false" />
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <handlers>
          <add name="dotless" path="*.less" verb="GET" type="dotless.Core.LessCssHttpHandler,dotless.Core" resourceType="File" preCondition="" />
        </handlers>
    </system.webServer>
    
  3. If the main less file is "my.less", which imports all other less files, add the following comment at the top of each less file except the "my.less".
    /// <reference path="my.less" />
    

Wednesday, August 20, 2014

Enable vertical split of the same CSHTML view file in Visual Studio 2013

In Visual Studio 2013, you can open the same C# file twice and view them vertically side-by-side by opening the C# file, selecting the menu [Window] --> [New Window] and then selecting [Window] --> [New Vertical Tab Group]. However, for *.cshtml MVC View files, this does not work. The [Window] --> [New Window] menu item is grayed out. To enable [Window] --> [New Window] menu item for *.cshtml file, you can try this registry hack.

  1. Close Visual Studio 2013 if currently open.
  2. Use RegEdit and go to
    [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\Languages\Language Services\HTMLX] .
  3. Find "Single Code Window Only" entry. 
  4. Change its value from 1 to 0.
  5. Start Visual Studio.
Now you should be able to open a *.cshtml file, select [New Window] from the [Window] menu to open another editor window of the same *.cshtml file, right-click on the the new editor window's tab and select [New Vertical Tab Group] to create side-by-side editor view of the same file. Changes you make on one editor window will instantly appear on the other editor window of the same file. 


onclick event handler - get reference to the clicked element

There are a couple of ways to get the reference to the clicked element, which has onclick event on itself.


Method 1
<input type="button" id="btn1" value="Remove" onclick="removeSelf(event)" />

<script type="text/javascript">
  function removeSelf(e){
    var target = (e.target) ? e.target : e.srcElement // IE uses srcElement
    target.style.display = 'none'; 
    target.parentNode.removeChild( target ); // to remove the element
    $(target).remove(); // to remove the element using jQuery
  }
</script>

In Method 1, event is used as parameter. An Event object is created automatically whenever an event is fired, i.e., via user action, key press, mouse movement, etc. To find the source where the event occurred, the property name is either target or srcElement (in IE).


Method 2
<input type="button" id="btn1" value="Remove" onclick="removeSelf(this)" />

<script type="text/javascript">
  function removeSelf(object){    
    object.style.display = 'none';
    target.parentNode.removeChild( target ); // to remove the element
    $(target).remove(); // to remove the element using jQuery
  }
</script>


Monday, July 7, 2014

MVC Ad-hoc DropDownList for PageSize

Example of Razor DropDown List for PageSize in an Index View using ViewBag.

Here is a controller
public class ProductController : Controller
{
  public ActionResult Index( int? page, int? pagesize )
  {
    ...
    int pageSize = pagesize ?? 5;
 
    List<SelectListItem> items = new List<SelectListItem>{
      new SelectListItem{ Text="5", Value="5" },
      new SelectListItem{ Text="10", Value="10" }
    }
    
    // items = List<SelectListItem>
    // "Value" = ValueText
    // "Text" = DisplayText
    // pagesize = SelectedListItem's Value from querystring
    ViewBag.PageSizeList = new SelectList( items, "Value", "Text", pagesize );
    
    ViewBag.CurrentPageSize = pageSize
  }
}
Here is the view
@using PagedList
@using PagedList.Mvc
@model IEnumerable

<form id="form1" action=@Url.Action("Index", "Product") method="get">
...
  @Html.DropDownList( "pagesize", (SelectList)ViewBag.PageSizeList )
  // We keep DropDown list's name separate from ViewBag element's name


  @foreach ( var item in Model ) {  }
  <table><tbody>
  <tr><td>...</td></tr>
  </tbody></table>

  @Html.PagedListPager( (IPagedList)Model, 
    page => Url.Action( "Index", new { page, pagesize = @ViewBag.CurrentPageSize })

</form>
<script type="text/javascript" src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js">
</script>
<script type="text/javascript">
  $(function(){
    // When onchange event occurs on <select id="pagesize">, 
    // simply submit the form, which will submit the new pagesize value as querystring.
    $('#pagesize').on('change', function(){
      $('#form1').submit();
    });
  });
</script>

Saturday, February 15, 2014

jQuery UI dialog jump issue workaround

When jQueryUI Dialog is used with "draggable = on", it would jump down by the scroll offset of parent page when the Dialog is being dragged via mouse. One of the nice workarounds to keep the draggable jQuery UI dialog in proper position without "jumping down" would be to set the dialog's parent position to 'fixed'. (By the way, this is the default behavior of Bootstrap's default modal window behavior, too.)

Below is a simple example to implement this workaround to a jQuery UI dialog. This works equally well for both modal and non-modal dialogs.

$(function(){
  $('#dialog_1').dialog({
    autoOpen: false,
    create: function( event ){  
      // set dialog's parent position to 'fixed' under the create event    
      $( event.target ).parent().css( 'position', 'fixed' );
    }
  });
  $('#btn_1').click(function(){
    // to reposition the dialog to the center when re-opened
    $('#dialog_1').dialog( 'option', 'position', 'center' );
    $('#dialog_1').dialog( 'open' );
  });
});

Hopefully, this workaround will provide better user experience on top of all the great features in jQuery UI library.

Tuesday, February 11, 2014

Get disk space info of all drives

The following SQL Server stored procedure could be useful when you need to get all disk space info quickly.


ALTER procedure [dbo].[usp_get_disk_space_info]
( @freeDiskSpace varchar(4000) output, @totalDiskSpace varchar(4000) output )
as
begin
 exec ( 'sp_configure ''xp_cmdshell'', 1' )
 exec ( 'reconfigure')
 declare @psinfo table ( data nvarchar(1000) )
 declare @t table(Drive varchar(2), FreeSpaceGB decimal(17,1), SizeGB decimal(17,1))
 insert into @psinfo
 EXEC xp_cmdshell 'Powershell.exe "Get-WMIObject Win32_LogicalDisk -filter "DriveType=3"| Format-Table DeviceID, FreeSpace, Size"' 
 delete from @psinfo where data is null or data like '%DeviceID%' or data like '%---%'
 update @psinfo set data = REPLACE(data, ' ', ',');
 ;With DriveSpace as (
 select SUBSTRING(data,1,2)  as [Drive], 
 replace((left((substring(data,(patindex('%[0-9]%',data)) , len(data))),CHARINDEX(',', (substring(data,(patindex('%[0-9]%',data)) , len(data))))-1)),',','') 
 as [FreeSpace] , 
 replace(right((substring(data,(patindex('%[0-9]%',data)) , len(data))),PATINDEX('%,%', (substring(data,(patindex('%[0-9]%',data)) , len(data))))) ,',','') 
 as [Size] 
 from @psinfo
 ) 
 insert into @t
 SELECT Drive, 
 convert(dec( 6,2),CONVERT(dec(17,1),FreeSpace)/(1024*1024*1024)) as FreeSpaceGB, 
 convert(dec( 6,2),CONVERT(dec(17,1), size)/(1024*1024*1024)) as SizeGB 
 FROM DriveSpace;
 declare @FreeSpaceGB varchar(1000)
 declare @SizeGB varchar(1000)
 set @FreeSpaceGB = stuff((select ', ' + Drive + ' ' + cast(FreeSpaceGB as varchar) + 'GB' from  @t for XML PATH('') ), 1, 2, '')
 set @SizeGB = stuff((select ', ' + Drive + ' ' + cast(SizeGB as varchar) + 'GB' from  @t for XML PATH('') ), 1, 2, '')

 select @freeDiskSpace = @FreeSpaceGB
 select @totalDiskSpace = @SizeGB


 exec ( 'sp_configure ''xp_cmdshell'', 0' )
 exec ( 'reconfigure')

end