Technology, Continued...

Ramblings about business, technology, development and my life

Phonegap and fast resume on WP8

When building a Phonegap application for the Windows Phone platform, it defaults to not enabling fast resume.  To back up a bit, when you use the back key to return to a WP8 application, it resumes where you left off.  However, when you return to the application via other means, such as the start menu, the application will restart.  There are some reasons why you might want this, but I personally can’t think of many for the average user.  Normally I want to return to my same place in the application regardless of how I’m getting to the application (one exception is with alerts, where the user does need to see the alert within the application itself).

So, if you want to have your Phonegap application fast resume, you need to change a setting the AppManifest file for the WP8 app.  With Phonegap, it will be at the following path off of your application’s home directory…

app/platforms/wp8/Properties/WMAppManifest.xml

Find the DefaultTask element and add ActivationPolicy=”Resume”.

<DefaultTask ActivationPolicy="Resume" Name="_default" NavigationPage="MainPage.xaml" />

For more information, this is a great read on fast resume.

http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj735579(v=vs.105).aspx

Little tricks for the Windows Phone 8 emulator

I found two handy posts about using the WP8 emulator.

Starting the WP8 emulator without going through Visual Studio.

http://social.technet.microsoft.com/wiki/contents/articles/18173.how-to-launch-windows-phone-8-emulator-without-using-visual-studio-2012.aspx

Using the keyboard on your computer with the WP8 emulator. 

Note that it’s opposite depending on whether you’re using WP7 or WP8 (WP8 is page down).

http://aceontech.com/2013/04/08/how-to-use-your-computers-keyboard-with-the-windows-phone-emulators/

Copying Azure VMs from one account to another

I had to copy my VM blob from one account to another.  I wanted a way that wouldn’t require me to download the vhd locally, just to then have to turn around and upload it again.  Instead, I wanted to be able to have the copy done within the Azure cloud itself.  Fortunately, I found free software to do just that.  It’s called AZCopy.  Here’s the link you need:

http://blogs.msdn.com/b/windowsazurestorage/archive/2013/04/01/azcopy-using-cross-account-copy-blob.aspx

You don’t have to install anything.  Just run it from the command prompt.  Here’s the syntax of the command I used:

   1: AzCopy https://<sourceaccount>.blob.core.windows.net/<sourcecontainer>/ https://<destaccount>.blob.core.windows.net/<destcontainer>/  /sourcekey:<key> /destkey:<key> /S

I’m not sure when you have to use https and when you don’t.  My paths in Azure didn’t show https, but when I tried to copy to my destination, I kept getting the error below.

Error parsing destination location "http://dest.blob.core.windows.net/vhds/": The underlying connection was closed: An unexpected error occurred on a receive.

Once I changed it to https, it worked great.  Here’s the output of my results.

C:\_utilities>azcopy http://source.blob.core.windows.net/vhds/ https://dest.blob.core.windows.net/vhds/ /sourcekey:srckey /destkey:dstkey /S

Transferring files /

Transfer summary:
-----------------
Total files transferred: 1
Transfer successfully:   1
Transfer failed:         0

127GB copied in just a few minutes!  Perfect.

SSRS 2012 Tile View Customization

I don’t know about you, but I don’t like the default tile view in SSRS 2012.  First, I feel like there’s too much white space.  Second, I want my report titles to wrap.  And finally, I don’t want the dropdowns on the tile view.  I’m constantly getting them when I just want to view the report (especially on touch devices), and it confuses my users.

Desired Outcome

So, I want to customize SSRS report list view to change the following:

image

 

To be more like this.  Wrapping, check.  Less whitespace, check.  No dropdown, check.

image

 

Again, importantly, I DO want the dropdown in the Details view, and the changes below do so.

Instructions

To do this, we have to edit the report javascript and css files.  I found more info here:

http://msdn.microsoft.com/en-us/library/ms345247(v=sql.110).aspx

On my server, the files were under the following directory:

C:\Program Files\Microsoft SQL Server\MSRS11.MSSQLSERVER\Reporting Services\ReportManager

Under this folder is a js and a styles folder.  The js folder has ReportingServices.js, while the styles folder has ReportingServices.css.  These are the two files we’ll be editing.

ReportingServices.js

Warning: this is a hack done in about 30 minutes.  I haven’t tested on different browsers or in all scenarios, so use at your own risk.

ReportingServices.js is compressed, so it’s rather jumbled.  Instead of finding the existing functions that need to be changed, just go to the end and insert the following javascript:

   1: //jw 2013-07-30
   2: //customized this to stop dropdown on tile view while still allowing it on details view
   3:  
   4: //this will stop the custom formatting for the dropdown
   5: function ChangeReportItemStyleOnMouseOver(a, c, b) {
   6:     var tagname = GetUnSelectedParentTagName(this);
   7:  
   8:     if (tagname == "DIV") {
   9:         return true;
  10:     }
  11:     else {
  12:         _unselectedItemStyle = b;
  13:         _mouseOverItem = a;
  14:         if (_tabFocusedItem != "") {
  15:             ChangeReportItemStyle(_tabFocusedItem, _unselectedItemStyle);
  16:             _tabFocusedItem = ""
  17:         }
  18:         ChangeReportItemStyle(a, c)
  19:     }
  20: }
  21:  
  22: //this will stop the click event from displaying the dropdown
  23: function Clicked(b, l) {
  24:     var tagname = GetUnSelectedParentTagName(this);
  25:  
  26:     if (tagname == "DIV") {
  27:         return true;
  28:     }
  29:     else {
  30:         if (!_onLink) {
  31:             ClearTimeouts(); SelectContextMenuFromColletion(l);
  32:             _itemSelected = true;
  33:             if (b == null) b = window.event;
  34:             var i = b.target != null ? b.target : b.srcElement, a = GetOuterElementOfType(i, "table"), e = GetElementPosition(a); _selectedItemId = a.id;
  35:             _selectedIdHiddenField.value = a.value;
  36:             a.className = "msrs-SelectedItem";
  37:             ResetContextMenu();
  38:             var g = _divContextMenu.offsetHeight, h = _divContextMenu.offsetWidth, o = a.offsetHeight, p = a.offsetWidth, j = e.left, k = e.top, d = 0, c = 0;
  39:             if (typeof window.innerWidth == "number")
  40:             { d = window.innerWidth; c = window.innerHeight }
  41:             else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
  42:                 d = document.documentElement.clientWidth;
  43:                 c = document.documentElement.clientHeight
  44:             }
  45:             else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
  46:                 d = document.body.clientWidth; c = document.body.clientHeight
  47:             }
  48:             var f = document.compatMode && document.compatMode != "BackCompat" ? document.documentElement : document.body, m = document.all ? f.scrollLeft : pageXOffset, n = document.all ? f.scrollTop : pageYOffset; _divContextMenu.style.left = SetContextMenuHorizonatalPosition(d, m, j, h, p) + "px";
  49:             _divContextMenu.style.top = SetContextMenuVerticalPosition(c, n, k, g, o) + "px";
  50:             ChangeOpacityForElement(100, _divContextMenu.id);
  51:             document.getElementById(_currentContextMenuId).firstChild.focus()
  52:         }
  53:     }
  54: }
  55:  
  56: //gets tag name before the object with the specified class name.
  57: //i found that it's a DIV in tile view, and not when in details view, so it's the differentiator i use to see what view i'm in
  58: //i'm sure there are multiple ways to do this, and this way is brittle, but hey, it works for now.
  59: function GetUnSelectedParentTagName(obj) {
  60:     var tagname = "";
  61:     try {
  62:         var src = obj.event.srcElement;
  63:         while (src.className != "msrs-UnSelectedItem") {
  64:             src = src.parentNode;
  65:         }
  66:         tagname = src.parentNode.tagName;
  67:  
  68:     }
  69:     catch (e) {
  70:     }
  71:     return tagname;
  72: }

That’s it.  Basically I’m finding out whether we’re in tile or details view by seeing if our menu item is contained in a DIV (for tile view) or not.  If we are in a div, I just stop processing in the key functions.

ReportingServices.css

I only changed two styles in the stylesheet.  Here’s the old style:

   1: div.msrs-tileView { float: left; height: 70px; }
   2: a.msrs-itemName  { white-space: nowrap; width: 250px; overflow: hidden; text-overflow: ellipsis; color:#000000; }

And here’s the new:

   1: div.msrs-tileView { float: left; height:50px; }
   2: a.msrs-itemName  { width: 250px; text-overflow: ellipsis; color:#000000; }

Basically, I’m tightening up the whitespace by changing the height of each tile menu item, and then I’m stopping the style from hiding the overflow text, and letting the text wrap.

Summary

That’s it.  If you do this correctly, the changes will be reflected immediately after saving the css and js files and refreshing your tile view.